AppArmor, short for Application Armor, is a Linux kernel security module that provides Mandatory Access Control (MAC) for applications. It acts as an additional layer of defense by confining individual programs to a set of rules, restricting their capabilities and access to resources on the system.
This is installed by default in most Linux distribution systems. To check:
systemctl status apparmor
To use AppArmor, the AppArmor kernel module must first be loaded on all the nodes where the containers will run. To check:
To apply AppArmor, we also use a profile which must be loaded into the kernel. To check the profiles loaded:
If it not installed, we can simply install AppArmor using apt-get (for Ubuntu) and dnf (for RedHat):
apt-get install -y apparmor-utils
To load an existing profile:
apparmor_parser /etc/apparmor.d/my-profile.json
To disable a profile, add the -R flag and then create a symlink:
apparmor_parser -R /etc/apparmor.d/my-profile.json
ln -s /etc/apparmor.d/my-profile.json /etc/apparmor.d/disable/
As an example, we can create a AppArmor profile which denies all writes to all files in the filesystem.
### /etc/apparmor.d/apparmor-deny-write
# Last Modified: Mon Jan 17 15:30:32 2022
profile deny_all_writes flags=(attach_disconnected,mediate_deleted) {
# Deny all writes to the entire filesystem
deny /** w,
}
To apply the AppArmor profile, you need to reload AppArmor and then enforce the new profile.
sudo systemctl reload apparmor
We can also restrict the writes to files under a specific directory, let’s say /proc directory.
### /etc/apparmor.d/apparmor-deny-proc-write
# Last Modified: Mon Jan 17 15:30:32 2022
profile deny_all_writes flags=(attach_disconnected) {
# Deny all writes to /proc
file,
deny /proc/* w,
}
Reload the AppArmor.
sudo systemctl reload apparmor
To check the status:
aa-status
AppArmor operates in two primary modes:
In Enforce mode, AppArmor strictly enforces the security policies defined in its profiles. If an application attempts an action not explicitly allowed by the AppArmor profile, the action is denied, and the kernel logs an audit message.
To activate enforce mode:
sudo aa-enforce /etc/apparmor.d/my_profile
Complain mode is more permissive than Enforce mode. In this mode, AppArmor logs security policy violations but allows the actions to proceed.
To activate complain mode:
sudo aa-complain /etc/apparmor.d/my_profile
In this mode, AppArmor will allow the application to perform any task and it does not log the tasks as events.
You can switch between Enforce and Complain modes for individual profiles using the aa-enforce and aa-complain commands.
During the development and testing of AppArmor profiles, Complain mode is often used initially to identify potential issues. Once the profiles are refined and tested thoroughly, Enforce mode can be applied in production.
Kubernetes support for AppArmor was added in Kubernetes version 1.4. The pre-requisites are:
As an example, we’ll launch a sleeper pod. Since it does not need any write access to the filesystem, we can apply an AppArmore profile.
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
spec:
containers:
- name: ubuntu-sleeper
image: ubuntu:latest
command: ["sleep", "3600"]
Create the profile.
### /etc/apparmor.d/apparmor-deny-write
profile apparmor-deny-write flags=(attach_disconnected) {
# Deny all writes
file,
deny /** w,
}
Verify that the AppArmor is loaded in the worker node.
aa-status
Since AppArmor is applied per container, add the parameter as an annotation in the Pod manifest.
## ubuntu-sleeper.yml
apiVersion: v1
kind: Pod
metadata:
name: sleep-pod
annotations:
container.apparmor.security.beta.kubernetes.io/ubuntu-sleeper: localhost/apparmor-deny-write
spec:
containers:
- name: ubuntu-container
image: ubuntu:latest
command: ["sleep", "3600"]
Apply the YAML file.
kubectl apply -f ubuntu-sleeper
Now try to create a file inside the container. This will fail, since the AppArmor profile prevents the container to perform any writes on the filesystem.
$ kubectl exec -it ubuntu-sleeper -- touch /tmp/testing
touch: cannot touch '/tmp/testing': Permission denied
command terminated with exit code 1