post image :date_long | 3 min Read

CKS Kernel Hardening Tools

Requirements for Apparmor
  • container runtime needs to support Apparmor
  • Apparmor needs to be installed on every node
  • Apparmor profiles need to be available on every node
  • Apparmor profiles are specified per container (done via annotations) not per pod!

AppArmor Profile Modes

Create a simple Apparmor profile for curl
# Install neceassary packages
apt-get install apparmor
apt-get install apparmor-utils # important!
aa-status

# Generate a profile for CURL
aa-genprof curl

Edit a profile according your needs

cat  /etc/apparmor.d/usr.bin.curl
# Last Modified: Tue Apr 13 20:23:56 2021
#include <tunables/global>

/usr/bin/curl {
  #include <abstractions/base>

  /lib/x86_64-linux-gnu/ld-*.so mr,
  /usr/bin/curl mr,

}
Load newly defined profile to Apparmor

It is very unlikely to write your own apparmor profile during an exam but one has to know:

  • how to load a new apparmor profile
  • how to use it in Kubernetes pod
# load newly defined profile
apparmor_parser /etc/apparmor.d/docker-nginx

# remove already existing profile
apparmor_parser -R /etc/apparmor.d/some-profile
Hwo to use apparmor with Docker
# default AppArmor profile
 docker run --security-opt apparmor=docker-default nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
f7ec5a41d630: Pull complete
aa1efa14b3bf: Pull complete
b78b95af9b17: Pull complete
c7d6bca2b8dc: Pull complete
cf16cd8e71e0: Pull complete
0241c68333ef: Pull complete
Digest: sha256:75a55d33ecc73c2a242450a9f1cc858499d468f077ea942867e662c247b5e412
Status: Downloaded newer image for nginx:latest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up


# custom AppArmor profile
 docker run --security-opt apparmor=docker-nginx nginx
/docker-entrypoint.sh: No files found in /docker-entrypoint.d/, skipping configuration
/docker-entrypoint.sh: 13: /docker-entrypoint.sh: cannot create /dev/null: Permission denied
Create a pod which uses an Apparmor profile
root@scw-k8s-cmdx:~# cat secure.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: secure
  name: secure
  annotations:
    container.apparmor.security.beta.kubernetes.io/secure: localhost/docker-nginx
spec:
  containers:
  - image: nginx
    name: secure
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Seccomp (Secure Computing Mode)
  • security facility in the Linux Kernel
  • restricts execution of syscalls

Download seccomp profile:
wget https://raw.githubusercontent.com/killer-sh/cks-course-environment/master/course-content/system-hardening/kernel-hardening-tools/seccomp/profile-docker-nginx.json
Use this profile with docker
root@scw-k8s-cmdx:~# docker run --name=hmm-with-seccomp --security-opt seccomp=profile-docker-nginx.json nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
...
How about if you simply remove write premissions from file: profile-docker-nginx.json
Container will not start because of missing write syscall
root@scw-k8s-cmdx:~# docker run --name=removed-write-seccomp --security-opt seccomp=profile-docker-nginx.json nginx
docker: Error response from daemon: OCI runtime start failed: cannot start an already running container: unknown.
ERRO[0001] error waiting for container: context canceled

How to create Seccomp profile in Kubernetes for kubelet
root@scw-k8s-cmdx:~# mkdir  /var/lib/kubelet/seccomp
root@scw-k8s-cmdx:~# cp profile-docker-nginx.json /var/lib/kubelet/seccomp/

Generate a pod according a documentation
root@scw-k8s-cmdx:~# cat seccomp.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/profile-docker-nginx.json
  containers:
  - image: nginx
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Now if you run it - you will see it fails
root@scw-k8s-cmdx:~# k describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
...
  Warning  Failed     11s (x2 over 14s)  kubelet            Error: failed to create containerd container: cannot load seccomp profile "/var/lib/kubelet/seccomp/profiles/profile-docker-nginx.json": open /var/lib/kubelet/seccomp/profiles/profile-docker-nginx.json: no such file or directory
r
We need to create a subfolder under seccomp folder in kubelet location
root@scw-k8s-cmdx:~# mkdir /var/lib/kubelet/seccomp/profiles
root@scw-k8s-cmdx:~# mv /var/lib/kubelet/seccomp/profile-docker-nginx.json /var/lib/kubelet/seccomp/profiles/

root@scw-k8s-cmdx:~# k delete -f seccomp.yaml
root@scw-k8s-cmdx:~# k create -f seccomp.yaml

root@scw-k8s-cmdx:~# k get pods
NAME     READY   STATUS    RESTARTS   AGE
nginx    1/1     Running   0          6s
secure   1/1     Running   0          35m

author image

Jan Toth

I have been in DevOps related jobs for past 6 years dealing mainly with Kubernetes in AWS and on-premise as well. I spent quite a lot …

comments powered by Disqus