⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

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.

Note

Ce 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,
}
  1. 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.

  2. Chargez le profil.

    $ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
    
  3. 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
    
  4. Entrez dans le conteneur en cours d'exécution.

    $ docker container exec -it apparmor-nginx bash
    
  5. 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.