-
Notifications
You must be signed in to change notification settings - Fork 971
Description
The current docker image does not work OOTB on a host with AppArmor enabled (e.g. any recent Debian/Ubuntu release), as the default AppArmor profile provided by Docker is too restrictive.
A possible workaround is to pass apparmor=unconfined as a security option (see #13085), but a better option would be to use a custom profile adapted to the application requirements, without throwing away the rest of the security features.
Unfortunately I wasn't able to find an easy way to inspect and adapt the profile used by Docker at runtime, so I've used the template from the repo (see github.com/moby/profiles/apparmor/template.go), to which I've just added the few syscalls which were previously blocked (mount and userns):
#include <tunables/global>
profile collabora-docker flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network,
capability,
file,
umount,
mount, # <-- was `deny mount`
userns, # <-- was undefined, so blocked by default
# Host (privileged) processes may send signals to container processes.
signal (receive) peer=unconfined,
# runc may send signals to container processes (for "docker stop").
signal (receive) peer=runc,
# crun may send signals to container processes (for "docker stop" when used with crun OCI runtime).
signal (receive) peer=crun,
# dockerd may send signals to container processes (for "docker kill").
signal (receive) peer=unconfined,
# Container processes may send signals amongst themselves.
signal (send,receive) peer=@{profile_name}, # <-- Replaced `peer=docker-default` with the current one
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
# deny write to files not in /proc/<number>/** or /proc/sys/**
deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9/]*}/** w,
deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/
deny @{PROC}/sysrq-trigger rwklx,
deny @{PROC}/kcore rwklx,
deny /sys/[^f]*/** wklx,
deny /sys/f[^s]*/** wklx,
deny /sys/fs/[^c]*/** wklx,
deny /sys/fs/c[^g]*/** wklx,
deny /sys/fs/cg[^r]*/** wklx,
deny /sys/firmware/** rwklx,
deny /sys/devices/virtual/powercap/** rwklx,
deny /sys/kernel/security/** rwklx,
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
ptrace (trace,read,tracedby,readby) peer=@{profile_name} # <-- Same as above
}
A few notes, mostly for a future myself.
- I named the profile
collabora-docker, but the name can be any "normal" string -- provided that it does not conflict with the name or path of any executable on the system, otherwise AppArmor will automatically apply the profile to it). - Any
deny ...instruction will silently block the execution of the corresponding entry (i.e. without leaving a message to syslog); similarly the allowed instructions will be silently allowed. All the instructions not defined in the profile will be denied with a corresponding message to the syslog. It is also possible to prepend an instruction withaudit ..., to print a message to the syslog whenever it is encountered (either allowed or denied). - I replaced
peer=docker-defaultwithpeer=@{profile_name}so not to break IPC inside the container (signals andptrace). Conversely it should block them across containers (being in different peer groups, i.e. under different profiles), but that should not be an issue as long as no signals are sent between processes in different containers (if that's even possible, as each container is in its own PID namespace). - Many rules are automatically inherited by the
#includeclauses, so thesignalandptraceinstructions are partially redundant (check the preprocessed output usingapparmor_parser -p /path/to/profile).
To activate the profile the best way is to place the file under /etc/apparmor.d, then run systemctl reload apparmor, which will automatically load all the profiles in the aforementioned dir.
I tested the profile under Debian 13/Trixie (Docker 26.1.5, AppArmor 4.1.0) with a userns profile using the following options, and it seems to be working without any issue nor complaints in the log:
security_opt:
- seccomp=cool-seccomp-profile.json
- apparmor=collabora-docker
- no-new-privileges=true
Obviously a more restrictive profile --designed around the exact operations needed by the application-- would be even better, but that's well above my capabilities ^.^
Metadata
Metadata
Assignees
Labels
Type
Projects
Status