others-prepare for cks exam with me 7: AppArmor in Linux, Docker and Kubernetes

1. Purpose

In this post, I would continue to write about preparing for the CKS (Certified Kubernetes Security Specialist) exam. I would write my own notes about the exam, and you can refer to these articles to prepare your own.

List of the series of posts:

-prepare for cks exam with me 1: Linux user and group management

-prepare for cks exam with me 2: Linux ssh hardening

-prepare for cks exam with me 3: Linux remove obsolete packages and services

-prepare for cks exam with me 4: Linux kernal hardening

-prepare for cks exam with me 5: Linux UFW(Uncomplicated firewall)

-prepare for cks exam with me 6: Seccomp in Linux, Docker and Kubernetes

-prepare for cks exam with me 7: Apparmor in Linux, Docker and Kubernetes

-prepare for cks exam with me 8: Security context in Kubernetes

-prepare for cks exam with me 9: Admission controllers in Kubernetes

-prepare for cks exam with me 10: Pod security policy in Kubernetes

-prepare for cks exam with me 11: Open policy agent in Kubernetes

-prepare for cks exam with me 12: Secrets in Kubernetes

-prepare for cks exam with me 13: Container runtimes(gvisor/kata containers) in Kubernetes

-prepare for cks exam with me 14: Container Image security in Docker and Kubernetes

2. Environment

  • CKS
  • Ubuntu System

3. Apparmor in Linux, Docker and Kubernetes

3.1 What is apparmor?

AppArmor is a Linux kernel security module that allows the system administrator to restrict programs’ capabilities with per-program profiles. Profiles can allow capabilities like network access, raw socket access, and the permission to read, write, or execute files on matching paths

3.2 Linux apparmor commands

Check apparmor service status

$ systemctl status apparmor

Check whether apparmor is loaded by the system:

[email protected]:~# cat /sys/module/apparmor/parameters/enabled

List apparmor profiles:

[email protected]:~# cat /sys/kernel/security/apparmor/profiles
docker-default (enforce)
/usr/sbin/tcpdump (enforce)
/usr/sbin/ntpd (enforce)
/usr/sbin/chronyd (enforce)
/usr/lib/connman/scripts/dhclient-script (enforce)
/usr/lib/NetworkManager/nm-dhcp-helper (enforce)
/usr/lib/NetworkManager/nm-dhcp-client.action (enforce)
/sbin/dhclient (enforce)
man_groff (enforce)
man_filter (enforce)
/usr/bin/man (enforce)

But what is profile in apparmor?

AppArmor confinement is provided via profiles loaded into the kernel, typically on boot. AppArmor profiles can be in one of two modes: enforcement and complain. Profiles loaded in enforcement mode will result in enforcement of the policy defined in the profile as well as reporting policy violation attempts (either via syslog or auditd). Profiles in complain mode will not enforce policy but instead report policy violation attempts.

There are three profile modes:

  • enforce

    In the enforce mode, system begins enforcing the rules and report the violation attempts in syslog or auditd (only if auditd is installed) and operation will not be permitted.

  • complain

    In the complain mode, system doesn’t enforce any rules. It will only log the violation attempts.

  • unconfined

Just as name implies, there is no limit in this mode

Check the internal status of apparmor:

[email protected]:~# aa-status
apparmor module is loaded.
11 profiles are loaded.
11 profiles are in enforce mode.
0 profiles are in complain mode.
1 processes have profiles defined.
1 processes are in enforce mode.
   /usr/sbin/chronyd (767)
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.

3.3 Apparmor with Docker and Kubernetes

We can load apparmor in pod like this:

apiVersion: v1
kind: Pod
  name: myapp-pod
  container.apparmor.security.beta.kubernetes.io/myapp-container: localhost/xxx
    app: myapp
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

Pay attention to the container.apparmor.security.beta.kubernetes.io/myapp-container: localhost/xxx, the format is:

container.apparmor.security.beta.kubernetes.io/<containerName>: localhost/<profileName>

Caution: The containerName must be same as the name of the container in the pod. And the profileName should be same as the profile name in the apparmor profile.

3.4 Demo how to use custom profile with Kubernetes and apparmor

First, write a profile:

#include <tunables/global>

profile custom-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  network inet tcp,
  network inet udp,
  network inet icmp,
  deny network raw,
  deny network packet,

The profile name is custom-nginx, and then save this file as usr.sbin.nginx in the default profile location of apparmor:


Load the profile via apparmor_parser into apparmor:

apparmor_parser  /etc/apparmor.d/usr.sbin.nginx

Verify that the profile is loaded successfully in apparmor:

aa-status|grep custom-nginx

You should see the custom-nginx is loaded in the status output.

Then we should configure the pod to use the apparmor profile as follows:

apiVersion: v1
kind: Pod
    name: nginx
        container.apparmor.security.beta.kubernetes.io/nginx: localhost/custom-nginx
        - image: 'nginx:alpine'
          name: nginx

Then run the pod, it should be running now.

4. Summary

In this post, I write some examples about how to do linux syscall hardening by apparmor when using linux operating systems.