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

Fonctionnalités et avantages clés

Subscription: Business
For: Administrators

Espace de noms utilisateur Linux sur tous les conteneurs

Avec l'Isolation de Conteneurs Renforcée, tous les conteneurs utilisateur tirent parti de l'espace de noms utilisateur Linux pour une isolation supplémentaire. Cela signifie que l'utilisateur root dans le conteneur est mappé vers un utilisateur non privilégié dans la VM Linux Docker Desktop.

Par exemple :

$ docker run -it --rm --name=first alpine
/ # cat /proc/self/uid_map
         0     100000      65536

La sortie 0 100000 65536 est la signature de l'espace de noms utilisateur Linux. Cela signifie que l'utilisateur root (0) dans le conteneur est mappé vers l'utilisateur non privilégié 100000 dans la VM Linux Docker Desktop, et le mappage s'étend sur une plage continue de 64K identifiants utilisateur. La même logique s'applique aux identifiants de groupe.

Chaque conteneur obtient une plage exclusive de mappages, gérée par Sysbox. Par exemple, si un deuxième conteneur est lancé, la plage de mappage est différente :

$ docker run -it --rm --name=second alpine
/ # cat /proc/self/uid_map
         0     165536      65536

En revanche, sans l'Isolation de Conteneurs Renforcée, l'utilisateur root du conteneur est en fait root sur l'hôte (alias "vrai root") et cela s'applique à tous les conteneurs :

$ docker run -it --rm alpine
/ # cat /proc/self/uid_map
         0       0     4294967295

En vertu de l'utilisation de l'espace de noms utilisateur Linux, l'Isolation de Conteneurs Renforcée garantit que les processus de conteneur ne s'exécutent jamais en tant qu'utilisateur ID 0 (vrai root) dans la VM Linux. En fait, ils ne s'exécutent jamais avec un ID utilisateur valide dans la VM Linux. Ainsi, leurs capacités Linux sont contraintes aux ressources à l'intérieur du conteneur uniquement, augmentant significativement l'isolation par rapport aux conteneurs réguliers, à la fois pour l'isolation conteneur-vers-hôte et inter-conteneurs.

Les conteneurs privilégiés sont également sécurisés

Les conteneurs privilégiés docker run --privileged ... sont peu sécurisés car ils donnent au conteneur un accès complet au noyau Linux. C'est-à-dire, le conteneur s'exécute en tant que vrai root avec toutes les capacités activées, les restrictions seccomp et AppArmor sont désactivées, tous les périphériques matériels sont exposés, par exemple.

Les organisations visant à sécuriser Docker Desktop sur les machines des développeurs font face à des défis avec les conteneurs privilégiés. Ces conteneurs, qu'ils exécutent des charges de travail bénignes ou malveillantes, peuvent prendre le contrôle du noyau Linux à l'intérieur de la VM Docker Desktop, potentiellement altérant les paramètres liés à la sécurité, par exemple la gestion d'accès au registre et les proxies réseau.

Avec l'Isolation de Conteneurs Renforcée, les conteneurs privilégiés ne peuvent plus faire cela. La combinaison de l'espace de noms utilisateur Linux et d'autres techniques de sécurité utilisées par Sysbox garantit que les processus à l'intérieur d'un conteneur privilégié ne peuvent accéder qu'aux ressources assignées au conteneur.

Note

L'Isolation de Conteneurs Renforcée n'empêche pas les utilisateurs de lancer des conteneurs privilégiés, mais les exécute plutôt de manière sécurisée en s'assurant qu'ils ne peuvent modifier que les ressources associées au conteneur. Les charges de travail privilégiées qui modifient les paramètres globaux du noyau, par exemple charger un module noyau ou changer les paramètres Berkeley Packet Filters (BPF) ne fonctionneront pas correctement car elles recevront une erreur "permission refusée" lors de la tentative de telles opérations.

Par exemple, l'Isolation de Conteneurs Renforcée garantit que les conteneurs privilégiés ne peuvent pas accéder aux paramètres réseau Docker Desktop dans la VM Linux configurés via BPF :

$ docker run --privileged djs55/bpftool map show
Error: can't get next map: Operation not permitted

En revanche, sans l'Isolation de Conteneurs Renforcée, les conteneurs privilégiés peuvent facilement faire cela :

$ docker run --privileged djs55/bpftool map show
17: ringbuf  name blocked_packets  flags 0x0
        key 0B  value 0B  max_entries 16777216  memlock 0B
18: hash  name allowed_map  flags 0x0
        key 4B  value 4B  max_entries 10000  memlock 81920B
20: lpm_trie  name allowed_trie  flags 0x1
        key 8B  value 8B  max_entries 1024  memlock 16384B

Notez que certaines charges de travail de conteneur avancées nécessitent des conteneurs privilégiés, par exemple Docker-in-Docker, Kubernetes-in-Docker, etc. Avec l'Isolation de Conteneurs Renforcée, vous pouvez toujours exécuter de telles charges de travail mais le faire de manière beaucoup plus sécurisée qu'auparavant.

Les conteneurs ne peuvent pas partager d'espaces de noms avec la VM Linux

Quand l'Isolation de Conteneurs Renforcée est activée, les conteneurs ne peuvent pas partager d'espaces de noms Linux avec l'hôte (par ex., PID, réseau, uts, etc.) car cela brise essentiellement l'isolation.

Par exemple, partager l'espace de noms PID échoue :

$ docker run -it --rm --pid=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown.

De même, partager l'espace de noms réseau échoue :

$ docker run -it --rm --network=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown.

De plus, le flag --userns=host, utilisé pour désactiver l'espace de noms utilisateur sur le conteneur, est ignoré :

$ docker run -it --rm --userns=host alpine
/ # cat /proc/self/uid_map
         0     100000      65536

Enfin, Docker build --network=host et les droits Docker buildx (network.host, security.insecure) ne sont pas autorisés. Les constructions qui nécessitent ceux-ci ne fonctionneront pas correctement.

Restrictions de montage de liaison

Quand l'Isolation de Conteneurs Renforcée est activée, les utilisateurs Docker Desktop peuvent continuer à monter par liaison les répertoires hôte dans les conteneurs comme configuré via Paramètres > Ressources > Partage de fichiers, mais ils ne sont plus autorisés à monter par liaison des répertoires arbitraires de la VM Linux dans les conteneurs.

Cela empêche les conteneurs de modifier les fichiers sensibles à l'intérieur de la VM Linux Docker Desktop, fichiers qui peuvent contenir des configurations pour la gestion d'accès au registre, proxies, configurations Docker Engine, et plus.

Par exemple, le montage de liaison suivant du fichier de configuration de Docker Engine (/etc/docker/daemon.json à l'intérieur de la VM Linux) dans un conteneur est restreint et donc échoue :

$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown

En revanche, sans l'Isolation de Conteneurs Renforcée, ce montage fonctionne et donne au conteneur un accès complet en lecture et écriture à la configuration de Docker Engine.

Bien sûr, les montages de liaison de fichiers hôte continuent de fonctionner comme d'habitude. Par exemple, en supposant qu'un utilisateur configure Docker Desktop pour partager son répertoire $HOME, elle peut le monter par liaison dans le conteneur :

$ docker run -it --rm -v $HOME:/mnt alpine
/ #
Note

Par défaut, l'Isolation de Conteneurs Renforcée n'autorise pas le montage par liaison du socket Docker Engine (/var/run/docker.sock) dans un conteneur, car cela accorde essentiellement au conteneur le contrôle de Docker Engine, brisant ainsi l'isolation du conteneur. Cependant, comme certains cas d'usage légitimes nécessitent cela, il est possible d'assouplir cette restriction pour les images de conteneur de confiance. Voir Permissions de montage du socket Docker.

Vérification des appels système sensibles

Une autre fonctionnalité de l'Isolation de Conteneurs Renforcée est qu'elle intercepte et vérifie quelques appels système hautement sensibles à l'intérieur des conteneurs, tels que mount et umount. Cela garantit que les processus qui ont les capacités d'exécuter ces appels système ne peuvent pas les utiliser pour briser le conteneur.

Par exemple, un conteneur qui a CAP_SYS_ADMIN (requis pour exécuter l'appel système mount) ne peut pas utiliser cette capacité pour changer un montage de liaison en lecture seule en montage lecture-écriture :

$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine
/ # mount -o remount,rw /mnt /mnt
mount: permission denied (are you root?)

Puisque le répertoire $HOME a été monté dans le répertoire /mnt du conteneur en lecture seule, il ne peut pas être changé de l'intérieur du conteneur en lecture-écriture, même si le processus du conteneur a la capacité de le faire. Cela garantit que les processus de conteneur ne peuvent pas utiliser mount, ou umount, pour briser le système de fichiers racine du conteneur.

Notez cependant que dans l'exemple précédent le conteneur peut toujours créer des montages à l'intérieur du conteneur, et les monter en lecture seule ou lecture-écriture selon les besoins. Ces montages sont autorisés puisqu'ils se produisent à l'intérieur du conteneur, et donc ne brisent pas le système de fichiers racine du conteneur :

/ # mkdir /root/tmpfs
/ # mount -t tmpfs tmpfs /root/tmpfs
/ # mount -o remount,ro /root/tmpfs /root/tmpfs

/ # findmnt | grep tmpfs
├─/root/tmpfs    tmpfs      tmpfs    ro,relatime,uid=100000,gid=100000

/ # mount -o remount,rw /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs    tmpfs      tmpfs    rw,relatime,uid=100000,gid=100000

Cette fonctionnalité, avec l'espace de noms utilisateur, garantit que même si un processus de conteneur a tous les Linux capabilities ils ne peuvent pas être utilisés pour briser le conteneur.

Enfin, l'Isolation de Conteneurs Renforcée fait la vérification des appels système de telle manière qu'elle ne affecte pas les performances des conteneurs dans la plupart des cas. Elle intercepte les appels système de chemin d'accès qui sont rarement utilisés dans la plupart des charges de travail de conteneur mais les appels système de chemin de données ne sont pas interceptés.

Mappages d'ID utilisateur de système de fichiers

Comme mentionné, ECI active l'espace de noms utilisateur Linux sur tous les conteneurs. Cela garantit que la plage d'ID utilisateur du conteneur (0->64K) est mappée vers une plage non privilégiée d'ID utilisateur "réel" dans la VM Linux Docker Desktop (par ex., 100000->165535).

De plus, chaque conteneur obtient une plage exclusive d'ID utilisateur réel dans la VM Linux (par ex., le conteneur 0 pourrait obtenir mappé à 100000->165535, le conteneur 2 à 165536->231071, le conteneur 3 à 231072->296607, et ainsi de suite). La même logique s'applique aux ID de groupe. En outre, si un conteneur est arrêté et redémarré, il n'y a aucune garantie qu'il recevra le même mappage qu'avant. C'est par conception et cela améliore la sécurité.

Cependant, cela présente un problème lors de la montage de volumes Docker dans les conteneurs. Les fichiers écrits dans de tels volumes ont les ID utilisateur/groupe réel et donc ne seront pas accessibles entre le démarrage/arrêt/redémarrage d'un conteneur, ou entre les conteneurs en raison de l'ID utilisateur/groupe réel de chaque conteneur.

Enfin, l'Isolation de Conteneurs Renforcée fait la vérification des appels système de telle manière qu'elle n'affecte pas les performances des conteneurs dans la grande majorité des cas. Elle intercepte les appels système de chemin de contrôle qui sont rarement utilisés dans la plupart des charges de travail de conteneur mais les appels système de chemin de données ne sont pas interceptés.

Mappages d'ID utilisateur de système de fichiers

Comme mentionné, ECI active l'espace de noms utilisateur Linux sur tous les conteneurs. Cela garantit que la plage d'ID utilisateur du conteneur (0->64K) est mappée vers une plage non privilégiée d'ID utilisateur "réels" dans la VM Linux Docker Desktop (par ex., 100000->165535).

De plus, chaque conteneur obtient une plage exclusive d'ID utilisateur réels dans la VM Linux (par ex., le conteneur 0 pourrait être mappé à 100000->165535, le conteneur 2 à 165536->231071, le conteneur 3 à 231072->296607, et ainsi de suite). La même logique s'applique aux ID de groupe. En outre, si un conteneur est arrêté et redémarré, il n'y a aucune garantie qu'il recevra le même mappage qu'avant. C'est par conception et améliore davantage la sécurité.

Cependant, cela présente un problème lors du montage de volumes Docker dans les conteneurs. Les fichiers écrits dans de tels volumes ont les ID utilisateur/groupe réels et donc ne seront pas accessibles lors du démarrage/arrêt/redémarrage d'un conteneur, ou entre les conteneurs en raison des différents ID utilisateur/groupe réels de chaque conteneur.

Pour résoudre ce problème, Sysbox utilise le "remappage d'ID utilisateur de système de fichiers" via la fonctionnalité ID-mapped mounts du noyau Linux (ajoutée en 2021) ou un module alternatif shiftsfs. Ces technologies mappent les accès au système de fichiers depuis l'ID utilisateur réel du conteneur (par ex., plage 100000->165535) vers la plage (0->65535) à l'intérieur de la VM Linux Docker Desktop. De cette façon, les volumes peuvent maintenant être montés ou partagés entre les conteneurs, même si chaque conteneur utilise une plage exclusive d'ID utilisateur. Les utilisateurs n'ont pas besoin de se soucier des ID utilisateur réels du conteneur.

Bien que le remappage d'ID utilisateur de système de fichiers puisse amener les conteneurs à accéder aux fichiers de la VM Linux montés dans le conteneur avec l'ID utilisateur réel 0, la fonctionnalité de montages restreints garantit que les fichiers sensibles de la VM Linux ne peuvent pas être montés dans le conteneur.

Émulation Procfs & sysfs

Une autre fonctionnalité de l'Isolation de Conteneurs Renforcée est qu'à l'intérieur de chaque conteneur, les systèmes de fichiers /proc et /sys sont partiellement émulés. Cela sert plusieurs objectifs, tels que cacher les informations sensibles de l'hôte à l'intérieur du conteneur et créer des espaces de noms pour les ressources du noyau hôte qui ne sont pas encore nommées par le noyau Linux lui-même.

Comme exemple simple, quand l'Isolation de Conteneurs Renforcée est activée, le fichier /proc/uptime montre le temps de fonctionnement du conteneur lui-même, pas celui de la VM Linux Docker Desktop :

$ docker run -it --rm alpine
/ # cat /proc/uptime
5.86 5.86

En revanche, sans l'Isolation de Conteneurs Renforcée, vous voyez le temps de fonctionnement de la VM Linux Docker Desktop. Bien que ce soit un exemple trivial, il montre comment l'Isolation de Conteneurs Renforcée vise à empêcher la configuration et les informations de la VM Linux de fuiter dans le conteneur pour rendre plus difficile la violation de la VM.

De plus, plusieurs autres ressources sous /proc/sys qui ne sont pas nommées par le noyau Linux sont également émulées à l'intérieur du conteneur. Chaque conteneur voit une vue séparée de chaque ressource et Sysbox réconcilie les valeurs à travers les conteneurs lors de la programmation du paramètre du noyau Linux correspondant.

Cela a l'avantage de permettre aux charges de travail de conteneur qui nécessiteraient autrement des conteneurs vraiment privilégiés pour accéder à de telles ressources de noyau non nommées de s'exécuter avec l'Isolation de Conteneurs Renforcée activée, améliorant ainsi la sécurité.