Introduction
La gestion des autorisations dans Docker est un aspect crucial de la gestion de vos applications conteneurisées. Ce tutoriel vous guidera dans la compréhension des autorisations de fichiers Docker, la définition des autorisations dans les conteneurs Docker et l'exploration des meilleures pratiques pour la gestion des autorisations. À la fin, vous aurez les connaissances nécessaires pour gérer efficacement les autorisations dans vos projets basés sur Docker.
Dans ce labo (LabEx), vous apprendrez comment fonctionnent les autorisations des conteneurs Docker, comment créer et utiliser des utilisateurs non root dans les conteneurs, et comment gérer les autorisations lors du partage de données entre l'hôte et les conteneurs.
Comprendre les autorisations par défaut dans Docker
Dans Docker, comprendre le fonctionnement des autorisations est essentiel pour maintenir des conteneurs sécurisés. Commençons par explorer les paramètres d'autorisations par défaut dans les conteneurs Docker.
Vérifier l'utilisateur par défaut dans Docker
Par défaut, Docker exécute les processus à l'intérieur des conteneurs en tant qu'utilisateur root. Cela peut entraîner des problèmes de sécurité potentiels si le conteneur est compromis. Pour observer ce comportement, créons un simple conteneur et vérifions quel utilisateur exécute les processus.
Tout d'abord, assurez-vous d'être dans votre répertoire de projet :
cd ~/project
Maintenant, exécutons un conteneur Ubuntu de base et vérifions l'utilisateur actuel :
docker run -it --rm ubuntu:22.04 whoami
Vous devriez voir la sortie suivante :
root
Cela confirme que Docker utilise l'utilisateur root par défaut. Maintenant, vérifions l'identifiant utilisateur (UID) et l'identifiant de groupe (GID) :
docker run -it --rm ubuntu:22.04 id
La sortie devrait ressembler à :
uid=0(root) gid=0(root) groups=0(root)
uid=0 et gid=0 indiquent que le conteneur s'exécute en tant qu'utilisateur et groupe root, qui ont un accès complet à toutes les ressources du conteneur.
Explorer les autorisations de fichiers à l'intérieur d'un conteneur
Examinons comment les autorisations de fichiers fonctionnent à l'intérieur d'un conteneur Docker. Créons un simple fichier à l'intérieur d'un conteneur et vérifions ses autorisations.
Tout d'abord, créons un conteneur qui s'exécutera en arrière-plan :
docker run -d --name permissions-demo ubuntu:22.04 sleep 3600
Maintenant, exécutons des commandes à l'intérieur de ce conteneur pour créer un fichier et vérifier ses autorisations :
docker exec permissions-demo touch /test-file
docker exec permissions-demo ls -l /test-file
Vous devriez voir une sortie similaire à :
-rw-r--r-- 1 root root 0 May 15 12:34 /test-file
Notez que le fichier est propriété de l'utilisateur et du groupe root. Cela démontre que tous les fichiers créés à l'intérieur d'un conteneur Docker par défaut sont propriété de l'utilisateur root.
Créons un répertoire et vérifions également ses autorisations :
docker exec permissions-demo mkdir /test-directory
docker exec permissions-demo ls -ld /test-directory
La sortie devrait être similaire à :
drwxr-xr-x 2 root root 4096 May 15 12:35 /test-directory
Encore une fois, le répertoire est propriété de l'utilisateur et du groupe root.
Nettoyons le conteneur avant de passer à l'étape suivante :
docker stop permissions-demo
docker rm permissions-demo
Cela démontre le comportement par défaut de Docker en ce qui concerne les autorisations utilisateur. Dans l'étape suivante, nous apprendrons à créer et utiliser des utilisateurs non root dans les conteneurs Docker pour améliorer la sécurité.
Création et utilisation d'utilisateurs non root dans Docker
Exécuter des applications en tant qu'utilisateur root à l'intérieur de conteneurs Docker présente des risques de sécurité. Si un attaquant compromet un conteneur exécuté en tant que root, il pourrait potentiellement obtenir des privilèges élevés sur le système hôte. Dans cette étape, nous apprendrons à créer et utiliser des utilisateurs non root dans les conteneurs Docker.
Création d'un Dockerfile avec un utilisateur non root
Créons un Dockerfile qui définit un utilisateur non root et le définit comme utilisateur par défaut pour l'exécution des commandes.
Tout d'abord, créons un nouveau répertoire pour notre projet :
mkdir -p ~/project/non-root-user
cd ~/project/non-root-user
Maintenant, créons un Dockerfile en utilisant l'éditeur de texte nano :
nano Dockerfile
Ajoutons le contenu suivant au Dockerfile :
FROM ubuntu:22.04
## Crée un nouvel utilisateur appelé 'appuser' avec l'identifiant utilisateur 1000
RUN useradd -m -u 1000 appuser
## Crée un répertoire pour l'application et définit la propriété
RUN mkdir -p /app && chown -R appuser:appuser /app
## Définit le répertoire de travail sur /app
WORKDIR /app
## Passe à l'utilisateur non root
USER appuser
## Crée un fichier de test
RUN touch test-file.txt
## Commande à exécuter lorsque le conteneur démarre
CMD ["bash", "-c", "echo 'Running as user:' && whoami && echo 'File ownership:' && ls -l test-file.txt && tail -f /dev/null"]
Enregistrez le fichier en appuyant sur Ctrl+O, puis Entrée, et quittez l'éditeur avec Ctrl+X.
Ce Dockerfile effectue les opérations suivantes :
- Crée un nouvel utilisateur appelé
appuseravec l'UID 1000 - Crée un répertoire pour l'application et attribue la propriété à appuser
- Définit le répertoire de travail sur
/app - Passe à l'utilisateur non root pour les commandes suivantes
- Crée un fichier de test qui sera propriété de appuser
- Définit une commande qui affichera les informations sur l'utilisateur et la propriété du fichier
Construction et exécution du conteneur avec un utilisateur non root
Maintenant, construisons l'image Docker à partir de notre Dockerfile :
docker build -t non-root-image .
Vous devriez voir une sortie indiquant que Docker est en train de construire l'image. Une fois la construction terminée, exécutez un conteneur à partir de cette image :
docker run --name non-root-container -d non-root-image
Maintenant, vérifions la sortie de notre conteneur :
docker logs non-root-container
Vous devriez voir une sortie similaire à :
Running as user:
appuser
File ownership:
-rw-r--r-- 1 appuser appuser 0 May 15 12:45 test-file.txt
Cela confirme que le conteneur s'exécute en tant qu'utilisateur appuser et que le fichier de test est propriété de appuser.
Test des autorisations de l'utilisateur non root
Connectons-nous au conteneur en cours d'exécution et explorons les autorisations de notre utilisateur non root :
docker exec -it non-root-container bash
Maintenant, vous devriez être à l'intérieur du conteneur en tant qu'utilisateur appuser. Vérifions cela :
whoami
Vous devriez voir :
appuser
Vérifions l'identifiant utilisateur et l'identifiant de groupe :
id
La sortie devrait être similaire à :
uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)
Maintenant, essayons de créer un fichier dans le répertoire racine :
touch /root-test-file
Vous devriez voir une erreur de permission refusée :
touch: cannot touch '/root-test-file': Permission denied
Cela est dû au fait que l'utilisateur non root n'a pas de droits d'écriture dans le répertoire racine. Cependant, notre utilisateur peut écrire dans le répertoire /app :
touch /app/user-test-file
ls -l /app/user-test-file
Vous devriez voir que le nouveau fichier est propriété de appuser :
-rw-r--r-- 1 appuser appuser 0 May 15 12:50 /app/user-test-file
Quittez le shell du conteneur :
exit
Nettoyons le conteneur avant de passer à l'étape suivante :
docker stop non-root-container
docker rm non-root-container
Cette étape a démontré comment créer et utiliser un utilisateur non root dans un conteneur Docker. L'utilisation d'un utilisateur non root contribue à améliorer la sécurité de vos applications conteneurisées en limitant les autorisations disponibles pour l'application.
Gestion des autorisations de montage de volumes
Les volumes Docker vous permettent de partager des données entre l'hôte et les conteneurs. Cependant, il est important de gérer correctement les autorisations lors de l'utilisation de volumes pour éviter les problèmes. Dans cette étape, nous apprendrons à gérer les autorisations lors de l'utilisation de montages de volumes.
Compréhension des problèmes d'autorisations de montage de volumes
Le principal défi avec les montages de volumes Docker est que les identifiants utilisateurs à l'intérieur du conteneur peuvent ne pas correspondre aux identifiants utilisateurs sur le système hôte. Cela peut entraîner des problèmes d'autorisations lors de l'accès aux fichiers dans les volumes montés.
Démontrons ce problème avec un exemple simple.
Tout d'abord, créez un nouveau répertoire sur l'hôte que nous monterons dans un conteneur :
mkdir -p ~/project/host-data
cd ~/project/host-data
Créez un fichier de test dans ce répertoire :
echo "This is a test file created on the host" > host-file.txt
Vérifiez la propriété de ce fichier :
ls -l host-file.txt
Vous devriez voir que le fichier est propriété de l'utilisateur labex (votre utilisateur actuel sur l'hôte) :
-rw-r--r-- 1 labex labex 39 May 15 13:00 host-file.txt
Maintenant, exécutons un conteneur qui monte ce répertoire et essayons de modifier le fichier :
docker run -it --rm -v ~/project/host-data:/container-data ubuntu:22.04 bash
Vous êtes maintenant à l'intérieur du conteneur. Vérifions la propriété du fichier monté :
ls -l /container-data/host-file.txt
Vous pourriez voir une sortie similaire à :
-rw-r--r-- 1 1000 1000 39 May 15 13:00 /container-data/host-file.txt
Notez que le fichier affiche des identifiants numériques au lieu de noms d'utilisateurs car le conteneur ne connaît pas l'utilisateur labex de l'hôte.
Essayons de créer un nouveau fichier dans le répertoire monté :
echo "This is a test file created in the container" > /container-data/container-file.txt
Maintenant, vérifions la propriété de ce nouveau fichier :
ls -l /container-data/container-file.txt
Vous devriez voir :
-rw-r--r-- 1 root root 47 May 15 13:05 /container-data/container-file.txt
Le fichier est propriété de l'utilisateur root à l'intérieur du conteneur (puisque nous exécutons en tant que root par défaut).
Quittez le conteneur :
exit
Maintenant, vérifiez la propriété des deux fichiers sur l'hôte :
ls -l ~/project/host-data/
Vous verrez que le fichier créé depuis l'intérieur du conteneur est propriété de root sur l'hôte :
-rw-r--r-- 1 root root 47 May 15 13:05 container-file.txt
-rw-r--r-- 1 labex labex 39 May 15 13:00 host-file.txt
Cela peut entraîner des problèmes d'autorisations si un utilisateur non root sur l'hôte a besoin d'accéder ou de modifier ces fichiers.
Résolution des problèmes d'autorisations de volumes
Il existe plusieurs façons de résoudre les problèmes d'autorisations de volumes. Explorons quelques approches courantes.
Approche 1 : Définir l'utilisateur dans le Dockerfile pour correspondre à l'utilisateur de l'hôte
Créez un nouveau répertoire pour cet exemple :
mkdir -p ~/project/volume-permissions
cd ~/project/volume-permissions
Créez un nouveau Dockerfile :
nano Dockerfile
Ajoutez le contenu suivant :
FROM ubuntu:22.04
## Crée un utilisateur avec le même UID que l'utilisateur de l'hôte
RUN useradd -m -u 1000 appuser
## Crée le répertoire de l'application et définit la propriété
RUN mkdir -p /app/data && chown -R appuser:appuser /app
## Définit le répertoire de travail
WORKDIR /app
## Passe à l'utilisateur appuser
USER appuser
## Commande à exécuter
CMD ["bash", "-c", "echo 'I can write to the mounted volume' > /app/data/test.txt && tail -f /dev/null"]
Enregistrez et quittez l'éditeur.
Construisez l'image :
docker build -t volume-permissions-image .
Créez un répertoire hôte pour les tests :
mkdir -p ~/project/volume-permissions/host-data
Exécutez un conteneur avec le volume monté :
docker run -d --name volume-test -v ~/project/volume-permissions/host-data:/app/data volume-permissions-image
Après un moment, vérifiez la propriété du fichier créé sur l'hôte :
ls -l ~/project/volume-permissions/host-data/
Vous devriez voir que le fichier est propriété d'un utilisateur avec l'UID 1000, qui devrait correspondre à l'UID de votre utilisateur hôte :
-rw-r--r-- 1 labex labex 35 May 15 13:15 test.txt
Cette approche fonctionne car nous avons créé un utilisateur dans le conteneur avec le même UID que l'utilisateur de l'hôte.
Approche 2 : Utilisation du flag --user
Une autre approche consiste à utiliser le flag --user pour spécifier l'identifiant utilisateur à utiliser lors de l'exécution du conteneur.
Tout d'abord, nettoyez le conteneur précédent :
docker stop volume-test
docker rm volume-test
Maintenant, exécutez un conteneur avec le flag --user :
docker run -d --name user-flag-test --user "$(id -u):$(id -g)" -v ~/project/volume-permissions/host-data:/data ubuntu:22.04 bash -c "echo 'Created with --user flag' > /data/user-flag-test.txt && sleep 3600"
Cette commande exécute le conteneur avec votre identifiant utilisateur et votre identifiant de groupe actuels.
Vérifiez la propriété du nouveau fichier :
ls -l ~/project/volume-permissions/host-data/user-flag-test.txt
Vous devriez voir que le fichier est propriété de votre utilisateur hôte :
-rw-r--r-- 1 labex labex 23 May 15 13:20 user-flag-test.txt
Nettoyons avant de passer à l'étape suivante :
docker stop user-flag-test
docker rm user-flag-test
Ces approches démontrent comment gérer les autorisations lors de l'utilisation de volumes Docker. En faisant correspondre les identifiants utilisateurs entre le conteneur et l'hôte, vous pouvez éviter les problèmes d'autorisations lors du partage de données entre eux.
Mise en œuvre des meilleures pratiques en matière d'autorisations
Mettons en pratique tout ce que nous avons appris en créant un exemple plus réaliste d'un conteneur Docker qui suit les meilleures pratiques en matière d'autorisations. Nous allons créer un conteneur d'application web simple qui respecte les meilleures pratiques de sécurité en matière d'autorisations.
Création d'un conteneur d'application web sécurisé
Tout d'abord, créez un nouveau répertoire pour notre exemple :
mkdir -p ~/project/secure-app
cd ~/project/secure-app
Créons une application web simple. Tout d'abord, créez un fichier app.py :
nano app.py
Ajoutez le code Python suivant pour créer un serveur web Flask simple :
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello from a secure container!'
@app.route('/whoami')
def whoami():
return os.popen('id').read()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
Enregistrez et quittez l'éditeur.
Maintenant, créez un fichier requirements.txt pour les dépendances Python :
nano requirements.txt
Ajoutez le contenu suivant :
flask==2.0.1
Enregistrez et quittez l'éditeur.
Maintenant, créez un Dockerfile qui suit les meilleures pratiques en matière d'autorisations :
nano Dockerfile
Ajoutez le contenu suivant :
FROM python:3.10-slim
## Crée un utilisateur non root pour exécuter l'application
RUN groupadd -g 1000 appgroup \
&& useradd -u 1000 -g appgroup -s /bin/bash -m appuser
## Définit le répertoire de travail et crée les répertoires nécessaires
WORKDIR /app
## Copie d'abord les dépendances pour tirer parti du cache Docker
COPY requirements.txt .
## Installe les dépendances en tant que root
RUN pip install --no-cache-dir -r requirements.txt
## Copie le code de l'application
COPY app.py .
## Crée un répertoire de données dans lequel l'application peut écrire
RUN mkdir -p /app/data \
&& chown -R appuser:appgroup /app
## Définit les autorisations appropriées
RUN chmod -R 755 /app
## Passe à l'utilisateur non root
USER appuser
## Expose le port sur lequel l'application s'exécutera
EXPOSE 8080
## Commande pour exécuter l'application
CMD ["python", "app.py"]
Enregistrez et quittez l'éditeur.
Construisons l'image Docker :
docker build -t secure-web-app .
Maintenant, exécutons le conteneur :
docker run -d --name secure-app -p 8080:8080 secure-web-app
Testons l'application. Tout d'abord, vérifions si le conteneur est en cours d'exécution :
docker ps
Vous devriez voir votre conteneur secure-app dans la liste. Maintenant, utilisez curl pour tester l'application :
curl http://localhost:8080/
Vous devriez voir :
Hello from a secure container!
Vérifions sous quel utilisateur l'application s'exécute :
curl http://localhost:8080/whoami
Vous devriez voir une sortie similaire à :
uid=1000(appuser) gid=1000(appgroup) groups=1000(appgroup)
Cela confirme que notre application s'exécute en tant que l'utilisateur non root appuser.
Analyse de sécurité
Analysons les améliorations de sécurité dans notre Dockerfile :
Utilisateur non root : Nous avons créé un utilisateur dédié (
appuser) pour exécuter l'application, réduisant ainsi le risque en cas de compromission du conteneur.Autorisations minimales : Nous avons défini uniquement les autorisations nécessaires pour que l'application fonctionne.
Propriété claire : Tous les fichiers et répertoires dans le conteneur ont une propriété clairement définie.
Structure de répertoires appropriée : Nous avons créé une structure de répertoires dédiée pour l'application et ses données.
Ces pratiques contribuent à garantir que même si un attaquant parvient à exploiter une vulnérabilité dans l'application, il aura un accès limité au conteneur et au système hôte.
Mise en œuvre des autorisations de volume avec l'application sécurisée
Ajoutons un volume à notre application sécurisée pour démontrer comment gérer correctement les autorisations avec les volumes.
Tout d'abord, arrêtez et supprimez le conteneur existant :
docker stop secure-app
docker rm secure-app
Créez un répertoire de données sur l'hôte :
mkdir -p ~/project/secure-app/host-data
Définissez les autorisations correctes sur le répertoire hôte :
sudo chown 1000:1000 ~/project/secure-app/host-data
Maintenant, exécutez le conteneur avec le volume monté :
docker run -d --name secure-app-with-volume \
-p 8080:8080 \
-v ~/project/secure-app/host-data:/app/data \
secure-web-app
Connectons-nous au conteneur et créons un fichier dans le volume monté :
docker exec -it secure-app-with-volume bash
Maintenant, à l'intérieur du conteneur, créez un fichier de test dans le volume monté :
echo "Test file created from inside the container" > /app/data/container-file.txt
Vérifiez la propriété du fichier :
ls -l /app/data/container-file.txt
Vous devriez voir que le fichier est propriété de appuser :
-rw-r--r-- 1 appuser appgroup 43 May 15 13:30 /app/data/container-file.txt
Quittez le conteneur :
exit
Maintenant, vérifiez la propriété du fichier sur l'hôte :
ls -l ~/project/secure-app/host-data/container-file.txt
Vous devriez voir que le fichier est propriété de l'UID 1000 (qui correspond à votre utilisateur hôte) :
-rw-r--r-- 1 labex labex 43 May 15 13:30 container-file.txt
Cela démontre qu'avec une configuration d'autorisations appropriée, les fichiers créés à l'intérieur du conteneur dans un volume monté auront la bonne propriété sur l'hôte.
Nettoyons avant de conclure :
docker stop secure-app-with-volume
docker rm secure-app-with-volume
En suivant ces meilleures pratiques en matière d'autorisations Docker, vous pouvez créer des applications conteneurisées sécurisées et fiables qui gèrent correctement les autorisations de fichiers à la fois à l'intérieur du conteneur et lors du partage de données avec le système hôte.
Résumé
Dans ce laboratoire, vous avez appris des techniques essentielles pour gérer les autorisations dans les conteneurs Docker :
Compréhension des autorisations par défaut de Docker : Vous avez exploré comment les conteneurs Docker s'exécutent par défaut en tant que root et comment cela peut entraîner des risques de sécurité potentiels.
Création et utilisation d'utilisateurs non root : Vous avez appris à créer des utilisateurs non root personnalisés dans les conteneurs Docker, ce qui est une pratique de sécurité essentielle.
Gestion des autorisations de montage de volumes : Vous avez découvert comment gérer les autorisations lors du partage de données entre l'hôte et les conteneurs à l'aide de volumes, en résolvant les problèmes d'autorisations courants.
Mise en œuvre des meilleures pratiques en matière d'autorisations : Vous avez appliqué tous ces concepts pour créer un conteneur d'application web sécurisé qui suit les meilleures pratiques en matière d'autorisations Docker.
En appliquant ces techniques dans vos projets Docker, vous pouvez améliorer considérablement la sécurité et la fiabilité de vos applications conteneurisées. N'oubliez pas que l'exécution de conteneurs avec les privilèges minimaux nécessaires est un principe de sécurité fondamental qui doit toujours être respecté.
Voici quelques points clés à retenir :
- Utilisez toujours des utilisateurs non root dans vos conteneurs.
- Faites correspondre les identifiants utilisateurs entre l'hôte et le conteneur lors de l'utilisation de volumes.
- Définissez les autorisations de fichiers et de répertoires appropriées.
- Suivez le principe du privilège minimal.
Ces pratiques vous aideront à construire des conteneurs Docker plus sécurisés et à éviter les problèmes courants liés aux autorisations.



