AppArmor (Application Armor) is a security module for Linux used to enforce mandatory access control. It provides a framework used to restrict capabilities of programs with profiles. A profile has definition of files, network access, and capabilities that program has access to. This enhances your system security as it limits the potential system breach from vulnerable software applications. In summary, a profile defines what resources your application has access to, and the kind of operations it can perform on those resources.
We had the following error on Debian Linux machine when launching a new container:
$ podman run -ti docker.io/library/alpine /bin/sh
Error: AppArmor profile "container-default" specified but not loaded
If you get the error message “AppArmor profile ‘container-default’ specified but not loaded“, it is an indication that AppArmor profile specified for use in a container is not available on the system. To fix the issue, make sure AppArmor is installed.
sudo apt update
sudo apt install apparmor apparmor-utils
Start and enable AppArmor service.
sudo systemctl start apparmor
sudo systemctl enable apparmor
Check status of AppArmor
$ sudo aa-status
apparmor module is loaded.
11 profiles are loaded.
11 profiles are in enforce mode.
/usr/bin/man
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/connman/scripts/dhclient-script
/{,usr/}sbin/dhclient
lsb_release
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
tcpdump
0 profiles are in complain mode.
0 profiles are in kill mode.
0 profiles are in unconfined mode.
0 processes have profiles defined.
0 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
0 processes are in mixed mode.
0 processes are in kill mode.
Create a new profile named container-default
in the /etc/apparmor.d/
directory:
- When using Podman
sudo tee /etc/apparmor.d/container-default<<EOF
#include <tunables/global>
profile container-default flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
file,
mount,
network,
capability,
# Allow read access to all files
/ r,
/** r,
# Allow write access to container-specific directories
/var/lib/containers/storage/** rw,
/run/containers/** rw,
# Network access
network inet stream,
network inet dgram,
# Allow various capabilities
capability sys_admin,
capability chown,
capability dac_override,
capability fowner,
capability fsetid,
capability kill,
capability setgid,
capability setuid,
capability sys_chroot,
capability sys_ptrace,
}
EOF
- When using Docker
sudo tee /etc/apparmor.d/container-default<<EOF
#include <tunables/global>
profile container-default flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/docker>
file,
mount,
network,
capability,
# Allow read access to all files
/ r,
/** r,
# Allow write access to container-specific directories
/var/lib/docker/** rw,
/run/docker/** rw,
/var/run/docker.sock rw,
# Network access
network inet stream,
network inet dgram,
# Allow various capabilities
capability sys_admin,
capability chown,
capability dac_override,
capability fowner,
capability fsetid,
capability kill,
capability setgid,
capability setuid,
capability sys_chroot,
capability sys_ptrace,
}
EOF
Next we load the AppArmor profile using apparmor_parser
:
sudo apparmor_parser -r /etc/apparmor.d/container-default
Restart AppArmor service to ensure the newly loaded profile is active:
sudo systemctl restart apparmor
See profiles loaded in AppArmor:
$ sudo aa-status
apparmor module is loaded.
14 profiles are loaded.
14 profiles are in enforce mode.
/usr/bin/man
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/connman/scripts/dhclient-script
/{,usr/}sbin/dhclient
container-default
lsb_release
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
passt
pasta
tcpdump
0 profiles are in complain mode.
0 profiles are in kill mode.
0 profiles are in unconfined mode.
0 processes have profiles defined.
0 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
0 processes are in mixed mode.
0 processes are in kill mode.
Try running the container:
$ podman run -ti docker.io/library/alpine /bin/sh
/ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
v3.20.1-161-g92564a0d909 [https://dl-cdn.alpinelinux.org/alpine/v3.20/main]
v3.20.1-163-gc21bd5e8a59 [https://dl-cdn.alpinelinux.org/alpine/v3.20/community]
OK: 24157 distinct packages available
/ #
You can also specify the profile when running the container:
# Docker
docker run --security-opt apparmor=container-default <container_image>
# Podman
podman run --security-opt apparmor=container-default <container_image>