Comment ajouter ou supprimer des capacités avec les commandes Docker

DockerBeginner
Pratiquer maintenant

Introduction

Docker est un outil puissant pour la conteneurisation des applications, et comprendre comment gérer les capacités des conteneurs est crucial pour optimiser la sécurité et les performances. Ce tutoriel vous guidera à travers le processus d'ajout et de suppression de capacités en utilisant les commandes Docker, vous aidant ainsi à adapter votre environnement de conteneur aux besoins spécifiques.

Dans ce lab, vous apprendrez ce que sont les capacités Docker, comment elles améliorent la sécurité des conteneurs et comment les gérer efficacement. À la fin de ce tutoriel, vous serez en mesure d'ajouter et de supprimer en toute confiance des capacités de vos conteneurs Docker.

Comprendre les Capacités Docker

Les capacités Docker sont une fonctionnalité de sécurité qui vous permet d'accorder ou de révoquer des permissions spécifiques du noyau Linux à un conteneur. Avant de commencer à expérimenter avec les capacités, comprenons ce qu'elles sont et pourquoi elles sont importantes.

Que sont les Capacités Docker ?

Les capacités dans Docker sont basées sur le système de capacités du noyau Linux, qui divise les privilèges traditionnellement associés à l'utilisateur root en unités distinctes. Cette approche est plus sûre que le modèle traditionnel de privilège root tout-ou-rien.

Par défaut, les conteneurs Docker s'exécutent avec un ensemble limité de capacités, offrant un équilibre raisonnable entre fonctionnalité et sécurité. Cependant, vous devrez peut-être ajouter ou supprimer des capacités en fonction des exigences de votre application.

Examinons les capacités par défaut d'un conteneur Docker. Exécutez la commande suivante pour démarrer un conteneur et afficher ses capacités :

docker run --rm -it ubuntu:22.04 capsh --print

Vous devriez voir une sortie similaire à celle-ci :

Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Ambient set =
Current IAB: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Securebits: 00/0x0/1'b0
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
 secure-no-ambient-raise: no (unlocked)
uid=0(root) gid=0(root) groups=0(root)

Cette sortie montre les capacités accordées au conteneur par défaut. Ces capacités contrôlent ce que le conteneur peut faire au sein du système.

Pourquoi les Capacités sont-elles Importantes ?

La gestion appropriée des capacités Docker est cruciale pour :

  1. Sécurité améliorée : En limitant les capacités, vous réduisez les dommages potentiels si un conteneur est compromis.
  2. Contrôle précis : Vous pouvez autoriser des opérations privilégiées spécifiques sans accorder un accès root complet.
  3. Principe du moindre privilège : Les conteneurs ne doivent avoir que les capacités dont ils ont besoin pour fonctionner correctement.

Ensuite, explorons comment ajouter des capacités aux conteneurs Docker.

Ajout de Capacités aux Conteneurs Docker

Dans cette étape, nous allons apprendre à ajouter des capacités spécifiques à un conteneur Docker en utilisant le flag --cap-add. Ceci est utile lorsque votre application nécessite certains privilèges qui ne sont pas inclus dans l'ensemble par défaut.

Syntaxe de base pour l'ajout de capacités

La syntaxe de base pour ajouter une capacité à un conteneur Docker est la suivante :

docker run --cap-add=<CAPABILITY> <IMAGE> <COMMAND>

Essayons d'ajouter la capacité NET_ADMIN, qui permet au conteneur d'effectuer diverses opérations liées au réseau :

docker run --rm -it --cap-add=NET_ADMIN ubuntu:22.04 capsh --print

La sortie montrera que la capacité NET_ADMIN a été ajoutée au conteneur :

Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap,cap_net_admin=ep

Notez l'ajout de cap_net_admin à la fin de la liste des capacités.

Ajout de plusieurs capacités

Souvent, vous devrez peut-être ajouter plusieurs capacités à un conteneur. Vous pouvez le faire en spécifiant le flag --cap-add plusieurs fois :

docker run --rm -it --cap-add=NET_ADMIN --cap-add=SYS_TIME ubuntu:22.04 capsh --print

Cette commande ajoute les capacités NET_ADMIN et SYS_TIME au conteneur. La capacité SYS_TIME permet au conteneur de modifier l'horloge système.

Exemple pratique : Modification des interfaces réseau

Pour démontrer une utilisation pratique des capacités, créons un conteneur avec la capacité NET_ADMIN et tentons de modifier les paramètres de l'interface réseau :

docker run --rm -it --cap-add=NET_ADMIN ubuntu:22.04 /bin/bash

Vous êtes maintenant à l'intérieur du conteneur avec un shell bash. Installons le paquet iproute2 pour travailler avec les interfaces réseau :

apt-get update && apt-get install -y iproute2

Maintenant, essayez de créer une interface réseau factice :

ip link add dummy0 type dummy
ip link show dummy0

Vous devriez voir une sortie montrant la nouvelle interface réseau factice créée :

6: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 2a:d5:cd:70:91:f4 brd ff:ff:ff:ff:ff:ff

Cette opération échouerait sans la capacité NET_ADMIN. Vous pouvez quitter le conteneur en tapant exit.

Affichage des capacités du conteneur

Pour inspecter les capacités d'un conteneur en cours d'exécution, vous pouvez utiliser la commande docker inspect. Tout d'abord, démarrons un conteneur avec des capacités ajoutées en mode détaché :

docker run -d --name cap-test --cap-add=NET_ADMIN ubuntu:22.04 sleep 3600

Maintenant, inspectez le conteneur pour afficher ses capacités :

docker inspect cap-test | grep -A 20 CapAdd

La sortie montrera que la capacité NET_ADMIN a été ajoutée :

            "CapAdd": [
                "NET_ADMIN"
            ],

N'oubliez pas de nettoyer après cette étape :

docker stop cap-test
docker rm cap-test

Comprendre comment ajouter des capacités aux conteneurs Docker vous donne plus de contrôle sur ce que vos conteneurs peuvent faire, tout en maintenant la sécurité.

Suppression de Capacités des Conteneurs Docker

Dans cette étape, nous allons apprendre à supprimer des capacités des conteneurs Docker en utilisant le flag --cap-drop. Il s'agit d'une pratique de sécurité importante qui suit le principe du moindre privilège - les conteneurs ne doivent avoir que les capacités dont ils ont absolument besoin.

Syntaxe de base pour la suppression de capacités

La syntaxe de base pour supprimer une capacité d'un conteneur Docker est la suivante :

docker run --cap-drop=<CAPABILITY> <IMAGE> <COMMAND>

Essayons de supprimer la capacité CHOWN, qui permet de modifier la propriété des fichiers :

docker run --rm -it --cap-drop=CHOWN ubuntu:22.04 capsh --print

Dans la sortie, vous remarquerez que cap_chown n'est plus répertorié parmi les capacités :

Current: cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep

Suppression de plusieurs capacités

Vous pouvez supprimer plusieurs capacités en spécifiant le flag --cap-drop plusieurs fois :

docker run --rm -it --cap-drop=CHOWN --cap-drop=NET_RAW ubuntu:22.04 capsh --print

Cette commande supprime les capacités CHOWN et NET_RAW du conteneur.

Exemple pratique : Test des restrictions de capacité

Créons un conteneur avec la capacité CHOWN supprimée et tentons de modifier la propriété du fichier :

docker run --rm -it --cap-drop=CHOWN ubuntu:22.04 /bin/bash

À l'intérieur du conteneur, créons un fichier de test et essayons de modifier sa propriété :

touch test_file
ls -l test_file
chown nobody:nogroup test_file

Vous devriez voir un message d'erreur indiquant que l'opération n'est pas autorisée :

chown: changing ownership of 'test_file': Operation not permitted

Cela démontre que la suppression de la capacité CHOWN empêche le conteneur de modifier la propriété du fichier, même si le conteneur s'exécute en tant que root. Tapez exit pour quitter le conteneur.

Utilisation de --cap-add et --cap-drop

Vous pouvez utiliser les flags --cap-add et --cap-drop dans la même commande pour contrôler précisément les capacités de votre conteneur :

docker run --rm -it --cap-add=NET_ADMIN --cap-drop=CHOWN ubuntu:22.04 capsh --print

Cette commande ajoute la capacité NET_ADMIN tout en supprimant la capacité CHOWN.

Suppression de toutes les capacités et ajout de capacités spécifiques

Pour une sécurité maximale, vous pouvez supprimer toutes les capacités, puis ajouter uniquement celles dont votre application a besoin :

docker run --rm -it --cap-drop=ALL --cap-add=NET_BIND_SERVICE ubuntu:22.04 capsh --print

Cette commande crée un conteneur avec uniquement la capacité NET_BIND_SERVICE, qui permet de se lier aux ports privilégiés (inférieurs à 1024).

Test d'un conteneur avec toutes les capacités supprimées

Créons un conteneur avec toutes les capacités supprimées et observons les restrictions :

docker run -d --name no-caps --cap-drop=ALL ubuntu:22.04 sleep 3600

Maintenant, attachons-nous au conteneur et essayons d'effectuer diverses opérations :

docker exec -it no-caps /bin/bash

À l'intérieur du conteneur, essayez de pinger un hôte externe :

apt-get update && apt-get install -y iputils-ping
ping -c 1 google.com

Vous verrez probablement une erreur car le conteneur n'a pas les capacités nécessaires pour créer des sockets réseau bruts requis pour ping.

Quittez le conteneur en tapant exit, puis nettoyez :

docker stop no-caps
docker rm no-caps

En comprenant comment supprimer des capacités des conteneurs Docker, vous pouvez améliorer considérablement la sécurité de vos applications conteneurisées en limitant strictement ce que chaque conteneur peut faire.

Combinaison de la Gestion des Capacités avec les Bonnes Pratiques de Sécurité

Dans cette dernière étape, nous allons explorer comment combiner la gestion des capacités Docker avec d'autres bonnes pratiques de sécurité pour créer des conteneurs sécurisés et à privilèges minimaux.

Création d'un conteneur avec un profil de capacités personnalisé

Créons un exemple plus complexe qui combine la gestion des capacités avec d'autres fonctionnalités de sécurité :

docker run -d --name secure-container \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  --read-only \
  --tmpfs /tmp \
  ubuntu:22.04 sleep 3600

Cette commande :

  • Supprime toutes les capacités
  • Ajoute uniquement la capacité NET_BIND_SERVICE
  • Rend le système de fichiers du conteneur en lecture seule
  • Crée un système de fichiers temporaire à /tmp pour les opérations d'écriture

Inspectons ce conteneur pour voir sa configuration :

docker inspect secure-container | grep -A 5 CapAdd
docker inspect secure-container | grep -A 5 CapDrop
docker inspect secure-container | grep ReadonlyRootfs

Vous devriez voir une sortie confirmant ces paramètres de sécurité :

            "CapAdd": [
                "NET_BIND_SERVICE"
            ],
            "CapDrop": [
                "ALL"
            ],
"ReadonlyRootfs": true,

Test des restrictions

Connectons-nous à notre conteneur sécurisé et testons les restrictions :

docker exec -it secure-container /bin/bash

Dans le conteneur, essayez de modifier un fichier système :

echo "test" > /etc/test

Vous devriez voir une erreur car le système de fichiers est en lecture seule :

bash: /etc/test: Read-only file system

Maintenant, essayez d'écrire dans le répertoire /tmp :

echo "test" > /tmp/test
cat /tmp/test

Cela devrait fonctionner car nous avons monté un tmpfs accessible en écriture à /tmp :

test

Quittez le conteneur en tapant exit.

Utilisation des capacités avec des utilisateurs non-root

Pour une sécurité supplémentaire, vous pouvez exécuter des conteneurs en tant qu'utilisateurs non-root tout en gérant les capacités. Tout d'abord, créons un nouveau conteneur qui combine un utilisateur non-root avec des capacités spécifiques :

docker run -d --name nonroot-container \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  --user 1000:1000 \
  ubuntu:22.04 sleep 3600

Notez que même si nous avons ajouté la capacité NET_BIND_SERVICE et que nous nous exécutons en tant qu'utilisateur non-root, les capacités Linux ne sont appliquées aux processus s'exécutant en tant que root par défaut. Pour permettre aux utilisateurs non-root d'utiliser les capacités, des configurations supplémentaires telles que les binaires setuid ou les capacités ambiantes seraient nécessaires.

Capacités dans docker-compose

Si vous utilisez docker-compose pour gérer plusieurs conteneurs, vous pouvez spécifier les capacités dans votre fichier docker-compose.yml :

version: "3"
services:
  webapp:
    image: ubuntu:22.04
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /tmp

Cela fournit un moyen cohérent de gérer les capacités dans vos déploiements de conteneurs.

Nettoyage

Nettoyons les conteneurs que nous avons créés :

docker stop secure-container nonroot-container
docker rm secure-container nonroot-container

Résumé des bonnes pratiques

Voici quelques bonnes pratiques pour la gestion des capacités Docker :

  1. Supprimez toutes les capacités et ajoutez uniquement ce dont vous avez besoin
  2. Combinez la gestion des capacités avec d'autres fonctionnalités de sécurité :
    • Système de fichiers en lecture seule
    • Utilisateurs non-root
    • Profils Seccomp
    • AppArmor ou SELinux
  3. Auditez régulièrement les capacités des conteneurs
  4. Maintenez Docker et les images de conteneurs à jour
  5. Utilisez des outils d'analyse des vulnérabilités des conteneurs

En suivant ces pratiques, vous pouvez améliorer considérablement la sécurité de vos conteneurs Docker.

Résumé

Dans ce laboratoire, vous avez appris à gérer efficacement les capacités des conteneurs Docker pour améliorer la sécurité et les fonctionnalités. Voici un récapitulatif de ce que vous avez accompli :

  1. Vous avez compris ce que sont les capacités Docker et pourquoi elles sont importantes pour la sécurité des conteneurs.
  2. Vous avez appris à ajouter des capacités aux conteneurs en utilisant le flag --cap-add, permettant aux conteneurs d'effectuer des opérations privilégiées spécifiques.
  3. Vous avez pratiqué la suppression de capacités avec le flag --cap-drop, mettant en œuvre le principe du moindre privilège.
  4. Vous avez exploré les meilleures pratiques pour combiner la gestion des capacités avec d'autres fonctionnalités de sécurité afin de créer des environnements de conteneurs sécurisés.

En appliquant ces techniques, vous pouvez créer des conteneurs qui ont précisément les permissions dont ils ont besoin, ni plus ni moins. Cette approche réduit considérablement la surface d'attaque potentielle de vos applications conteneurisées tout en garantissant qu'elles disposent des fonctionnalités nécessaires pour fonctionner correctement.

Continuez à explorer les fonctionnalités de sécurité Docker et n'oubliez pas d'auditer et de mettre à jour régulièrement vos configurations de conteneurs pour maintenir une solide posture de sécurité dans vos environnements conteneurisés.