Profils de sécurité AppArmor pour Docker
AppArmor (Application Armor) est un module de sécurité Linux qui protège un système d'exploitation et ses applications contre les menaces de sécurité. Pour l'utiliser, un administrateur système associe un profil de sécurité AppArmor à chaque programme. Docker s'attend à trouver une politique AppArmor chargée et appliquée.
Docker génère automatiquement et charge un profil par défaut pour les conteneurs nommé
docker-default
. Le binaire Docker génère ce profil dans tmpfs
puis
le charge dans le noyau.
NoteCe profil est utilisé sur les conteneurs, pas sur le démon Docker.
Un profil pour le démon Docker Engine existe mais il n'est pas actuellement installé
avec les paquets deb
. Si vous êtes intéressé par la source du profil de démon,
elle se trouve dans
contrib/apparmor
dans le dépôt source Docker Engine.
Comprendre les politiques
Le profil docker-default
est le défaut pour l'exécution de conteneurs. Il est
modérément protecteur tout en fournissant une large compatibilité d'application. Le
profil est généré à partir du
modèle suivant.
Lorsque vous exécutez un conteneur, il utilise la politique docker-default
à moins que vous
ne la remplaciez avec l'option security-opt
. Par exemple, ce qui suit
spécifie explicitement la politique par défaut :
$ docker run --rm -it --security-opt apparmor=docker-default hello-world
Charger et décharger des profils
Pour charger un nouveau profil dans AppArmor pour utilisation avec des conteneurs :
$ apparmor_parser -r -W /path/to/your_profile
Ensuite, exécutez le profil personnalisé avec --security-opt
:
$ docker run --rm -it --security-opt apparmor=your_profile hello-world
Pour décharger un profil d'AppArmor :
# décharger le profil
$ apparmor_parser -R /path/to/profile
Ressources pour écrire des profils
La syntaxe pour le globbing de fichier dans AppArmor est un peu différente de certaines autres implémentations de globbing. Il est fortement suggéré de jeter un œil à certaines des ressources ci-dessous concernant la syntaxe des profils AppArmor.
Exemple de profil Nginx
Dans cet exemple, vous créez un profil AppArmor personnalisé pour Nginx. Ci-dessous se trouve le profil personnalisé.
#include <tunables/global>
profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
network inet udp,
network inet icmp,
deny network raw,
deny network packet,
file,
umount,
deny /bin/** wl,
deny /boot/** wl,
deny /dev/** wl,
deny /etc/** wl,
deny /home/** wl,
deny /lib/** wl,
deny /lib64/** wl,
deny /media/** wl,
deny /mnt/** wl,
deny /opt/** wl,
deny /proc/** wl,
deny /root/** wl,
deny /sbin/** wl,
deny /srv/** wl,
deny /tmp/** wl,
deny /sys/** wl,
deny /usr/** wl,
audit /** w,
/var/run/nginx.pid w,
/usr/sbin/nginx ix,
deny /bin/dash mrwklx,
deny /bin/sh mrwklx,
deny /usr/bin/top mrwklx,
capability chown,
capability dac_override,
capability setuid,
capability setgid,
capability net_bind_service,
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}/mem rwklx,
deny @{PROC}/kmem rwklx,
deny @{PROC}/kcore rwklx,
deny mount,
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/kernel/security/** rwklx,
}
-
Enregistrez le profil personnalisé sur le disque dans le fichier
/etc/apparmor.d/containers/docker-nginx
.Le chemin de fichier dans cet exemple n'est pas une exigence. En production, vous pourriez en utiliser un autre.
-
Chargez le profil.
$ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
-
Exécutez un conteneur avec le profil.
Pour exécuter nginx en mode détaché :
$ docker run --security-opt "apparmor=docker-nginx" \ -p 80:80 -d --name apparmor-nginx nginx
-
Entrez dans le conteneur en cours d'exécution.
$ docker container exec -it apparmor-nginx bash
-
Essayez quelques opérations pour tester le profil.
root@6da5a2a930b9:~# ping 8.8.8.8 ping: Lacking privilege for raw socket. root@6da5a2a930b9:/# top bash: /usr/bin/top: Permission denied root@6da5a2a930b9:~# touch ~/thing touch: cannot touch 'thing': Permission denied root@6da5a2a930b9:/# sh bash: /bin/sh: Permission denied root@6da5a2a930b9:/# dash bash: /bin/dash: Permission denied
Vous venez de déployer un conteneur sécurisé avec un profil apparmor personnalisé.
Déboguer AppArmor
Vous pouvez utiliser dmesg
pour déboguer les problèmes et aa-status
pour vérifier les profils chargés.
Utiliser dmesg
Voici quelques conseils utiles pour déboguer les problèmes que vous pourriez rencontrer avec AppArmor.
AppArmor envoie des messages assez verbeux à dmesg
. Habituellement une ligne AppArmor
ressemble à ce qui suit :
[ 5442.864673] audit: type=1400 audit(1453830992.845:37): apparmor="ALLOWED" operation="open" profile="/usr/bin/docker" name="/home/jessie/docker/man/man1/docker-attach.1" pid=10923 comm="docker" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
Dans l'exemple ci-dessus, vous pouvez voir profile=/usr/bin/docker
. Cela signifie que
l'utilisateur a le profil docker-engine
(démon Docker Engine) chargé.
Regardez une autre ligne de journal :
[ 3256.689120] type=1400 audit(1405454041.341:73): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=17651 comm="docker" requested_mask="receive" denied_mask="receive"
Cette fois le profil est docker-default
, qui est exécuté sur les conteneurs par
défaut sauf en mode privileged
. Cette ligne montre qu'apparmor a refusé
ptrace
dans le conteneur. C'est exactement comme attendu.
Utiliser aa-status
Si vous devez vérifier quels profils sont chargés, vous pouvez utiliser aa-status
. La
sortie ressemble à :
$ sudo aa-status
apparmor module is loaded.
14 profiles are loaded.
1 profiles are in enforce mode.
docker-default
13 profiles are in complain mode.
/usr/bin/docker
/usr/bin/docker///bin/cat
/usr/bin/docker///bin/ps
/usr/bin/docker///sbin/apparmor_parser
/usr/bin/docker///sbin/auplink
/usr/bin/docker///sbin/blkid
/usr/bin/docker///sbin/iptables
/usr/bin/docker///sbin/mke2fs
/usr/bin/docker///sbin/modprobe
/usr/bin/docker///sbin/tune2fs
/usr/bin/docker///sbin/xtables-multi
/usr/bin/docker///sbin/zfs
/usr/bin/docker///usr/bin/xz
38 processes have profiles defined.
37 processes are in enforce mode.
docker-default (6044)
...
docker-default (31899)
1 processes are in complain mode.
/usr/bin/docker (29756)
0 processes are unconfined but have a profile defined.
La sortie ci-dessus montre que le profil docker-default
s'exécutant sur divers
PIDs de conteneur est en mode enforce
. Cela signifie qu'AppArmor bloque activement
et audite dans dmesg
tout ce qui est en dehors des limites du profil docker-default
.
La sortie ci-dessus montre également que le profil /usr/bin/docker
(démon Docker Engine)
s'exécute en mode complain
. Cela signifie qu'AppArmor ne fait que journaliser dans dmesg
l'activité en dehors des limites du profil. (Sauf dans le cas d'Ubuntu
Trusty, où certains comportements intéressants sont appliqués.)
Contribuer au code AppArmor de Docker
Les utilisateurs avancés et les gestionnaires de paquets peuvent trouver un profil pour /usr/bin/docker
(démon Docker Engine) sous
contrib/apparmor
dans le dépôt source Docker Engine.
Le profil docker-default
pour les conteneurs se trouve dans
profiles/apparmor.