Docker et sécurisation des mots de passe

J'ai essayé avec Docker récemment sur la construction de certains services pour jouer avec et une chose qui continue à me harceler a été de mettre des mots de passe dans un fichier Docker. Je suis développeur donc stocker les mots de passe dans la source ressemble à un coup de poing dans le visage. Cela doit même être un sujet de préoccupation? Y a-t-il de bonnes conventions sur la façon de gérer les mots de passe dans les fichiers Dockerfiles?

102
demandé sur Mark O'Connor 2014-03-26 08:42:33

11 réponses

C'est certainement une préoccupation. Les fichiers Dockerfiles sont souvent stockés dans des dépôts et partagés avec d'autres personnes. Une alternative est de fournir tous les justificatifs d'identité (noms d'utilisateur, mots de passe, jetons, tout ce qui est sensible) comme variables d'environnement à l'exécution . Ceci est possible via l'argument -e (pour les var individuelles sur le CLI) ou --env-file (pour les variables multiples dans un fichier) à docker run .

utilisant --env-file est certainement une option plus sûre car cela protège contre les secrets apparaissant dans ps ou dans les rondins si on utilise set -x .

cependant, les véhicules env ne sont pas particulièrement sûrs non plus. Ils sont visibles via docker inspect , et sont donc disponibles pour tout utilisateur qui peut exécuter des commandes docker . (Bien sûr, tout utilisateur qui a accès à docker sur l'hôte aussi a root de toute façon.)

mon modèle préféré est d'utiliser un script comme le ENTRYPOINT ou CMD . Le script peut d'abord importer les secrets d'un endroit extérieur dans le récipient au moment de l'exécution, puis exécuter l'application, en fournissant les secrets. La mécanique exacte de ceci varie en fonction de votre environnement de temps de course. Dans AWS, vous pouvez utiliser une combinaison de rôles IAM, le Key Management Service , et S3 pour stocker des secrets cryptés dans un seau S3. Quelque chose comme Hashicorp Vault ou credstash est une autre option.

AFAIK il n'y a pas de modèle optimal pour l'utilisation de données sensibles dans le cadre du processus de construction. En fait, j'ai un alors question sur ce sujet. Vous pouvez utiliser docker-squash pour supprimer les couches d'une image. Mais il n'y a pas de fonctionnalité native dans Docker à cette fin.

Vous trouverez les commentaires de shykes sur la page de config dans les conteneurs utile.

59
répondu Ben Whaley 2018-02-11 17:18:47

notre équipe évite de mettre des justificatifs d'identité dans les dépôts, ce qui signifie qu'ils ne sont pas autorisés dans Dockerfile . Notre meilleure pratique dans les applications est d'utiliser des creds à partir de variables d'environnement.

nous résolvons pour cela en utilisant docker-compose .

dans docker-compose.yml , vous pouvez spécifier un fichier qui contient les variables d'environnement pour le conteneur:

 env_file:
- .env

s'assurer d'ajouter .env à .gitignore , puis définissez les justificatifs d'identité dans le fichier .env comme:

SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd

Magasin .env fichier localement ou dans un endroit sûr où le reste de l'équipe peut s'en emparer.

voir: https://docs.docker.com/compose/environment-variables/#/the-env-file

54
répondu theUtherSide 2016-07-21 04:57:02

maintenant Docker (version 1.13 ou 17.06 et plus) a le soutien pour la gestion de l'information secrète. Voici un aperçu et plus détaillé documentation

"

fonctionnalité Similaire existe dans kubernetes et ACD

24
répondu Heather QC 2017-08-17 07:06:22

vous ne devriez jamais ajouter des justificatifs d'identité à un conteneur à moins que vous ne soyez D'accord de diffuser les creds à quiconque peut télécharger l'image. En particulier, doing et ADD creds et plus tard RUN rm creds ne sont pas sécurisés car le fichier creds reste dans l'image finale dans une couche intermédiaire du système de fichiers. Il est facile pour quiconque ayant accès à l'image de l'extraire.

la solution typique que j'ai vu quand vous avez besoin de creds pour vérifier les dépendances et tel est d'utiliser un conteneur pour en construire un autre. C'est-à-dire: en général, vous avez un environnement de construction dans votre conteneur de base et vous devez l'invoquer pour construire votre conteneur app. Donc la solution simple est d'ajouter votre source app et ensuite RUN les commandes de compilation. Ce n'est pas sûr si vous avez besoin de creds dans ce RUN . Au lieu de cela, ce que vous faites est de mettre votre source dans un répertoire local, exécutez (comme dans docker run ) le conteneur pour effectuer l'étape de construction avec le répertoire source local monté en volume et les creds soit injecté ou monté comme un autre volume. Une fois l'étape de construction terminée, vous construisez votre conteneur final simplement en ADD dans le répertoire source local qui contient maintenant les artefacts construits.

J'espère que Docker ajoute quelques fonctionnalités pour simplifier tout cela!

mise à jour: on dirait que la méthode pour l'avenir sera d'avoir des constructions imbriquées. En bref, le dockerfile décrirait un premier conteneur qui est utilisé pour créer l'environnement d'exécution, puis un deuxième container emboîté qui peut assembler toutes les pièces dans le container final. De cette façon, le truc du temps de construction n'est pas dans le second container. Ceci D'une application Java où vous avez besoin du JDK pour construire l'application, mais seulement le JRE pour l'exécuter. Il ya un certain nombre de propositions en cours de discussion, le meilleur pour commencer à https://github.com/docker/docker/issues/7115 et suivez certains des liens pour d'autres propositions.

8
répondu TvE 2014-10-15 20:40:14

avec Docker v1.9 vous pouvez utiliser l'instruction ARG instruction pour récupérer les arguments passés par ligne de commande à l'image sur build action . Il suffit d'utiliser le drapeau --build-arg . Ainsi, vous pouvez éviter de garder le mot de passe explicite (ou d'autres informations sensées) sur le fichier Dockerfile et de les transmettre à la volée.

source: https://docs.docker.com/engine/reference/commandline/build / http://docs.docker.com/engine/reference/builder/#arg

exemple:

Dockerfile

FROM busybox
ARG user
RUN echo "user is $user"

construire l'image de la commande

docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .

pendant la construction imprimer

$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
 ---> c51f86c28340
Step 2 : ARG user
 ---> Running in 43a4aa0e421d
 ---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
 ---> Running in 4360fb10d46a
**user is capuccino**
 ---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9

Espère que cela aide! Revoir.

5
répondu NickGnd 2015-11-21 18:09:19

comme une alternative à l'utilisation de variables d'environnement, qui peuvent devenir désordonnées si vous en avez beaucoup, est d'utiliser des volumes pour rendre un répertoire sur l'hôte accessible dans le conteneur.

si vous mettez tous vos justificatifs d'identité sous forme de fichiers dans ce dossier, alors le conteneur peut lire les fichiers et les utiliser comme bon lui semble.

par exemple:

$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...

In the Docker container:

# echo Password is `cat /cfg/password.txt`
Password is secret

de nombreux programmes peuvent lire leurs justificatifs d'identité à partir d'un fichier séparé, de cette façon vous pouvez simplement pointer le programme de l'un des fichiers.

3
répondu Malvineous 2016-08-19 04:57:17

mon approche semble fonctionner, mais est probablement naïve. Dites-moi pourquoi c'est mal.

ARGs mis pendant la construction du docker sont exposés par la sous-commande histoire, donc pas aller là. Cependant, lors de l'exécution d'un conteneur, les variables d'environnement données dans la commande run sont disponibles pour le conteneur, mais ne font pas partie de l'image.

ainsi, dans le fichier Dockerfile, faites une configuration qui n'implique pas de données secrètes. Mettez un CMD de quelque chose comme /root/finish.sh . Dans la course commande, utilisez des variables d'environnement pour envoyer des données secrètes dans le conteneur. finish.sh utilise les variables essentiellement pour terminer les tâches de construction.

pour faciliter la gestion des données secrètes, mettez-les dans un fichier chargé par docker avec le commutateur --env-file . Bien sûr, gardez le dossier secret. .gitignore et autres.

pour moi, finish.sh exécute un programme Python. Il vérifie pour s'assurer qu'il n'a pas fonctionné avant, puis termine la configuration (par exemple, copie le nom de la base de données dans settings.py de Django).

1
répondu Kieran Mathieson 2017-07-29 07:56:50

bien que je sois entièrement d'accord qu'il n'y a pas de solution simple. Il y a toujours un seul point d'échec. Soit le fichier dockerfile, l'etcd, et ainsi de suite. Apcera a un plan qui ressemble à un acolyte-double authentification. En d'autres termes, deux conteneurs ne peuvent pas parler à moins qu'il n'y ait une règle de configuration Apcera. Dans leur démo, l'uid/pwd était clair et ne pouvait pas être réutilisé tant que l'administrateur n'avait pas configuré le lien. Pour que cela fonctionne, cependant, il signifiait probablement correctifs Docker ou au moins le réseau plugin (si une telle chose existe).

0
répondu Richard 2015-07-21 15:01:19

il y a une nouvelle commande docker[1] pour la gestion des" secrets", mais qui ne fonctionne que pour les groupes d'essaims.

docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver 

[1] https://docs.docker.com/engine/swarm/secrets /

0
répondu José Ibañez 2017-12-02 15:56:14

au moment de l'exécution seule solution

docker-composer fournit également une solution sans essaimage (depuis v1.(11): les Secrets à l'aide de montages de type bind ).

les secrets sont montés comme des dossiers ci-dessous /run/secrets/ par docker-composer. Cela résout le problème au moment de l'exécution (lancer le conteneur), mais pas au moment de la construction (construire l'image), parce que /run/secrets/ n'est pas monté au moment de la construction. En outre, ce comportement dépend de l'exécution du conteneur avec docker-composer.


exemple:

fichier Dockerfile

FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity

docker-composer.yml

version: '3.1'
services:
  app:
    build: .
    secrets:
      - password

secrets:
  password:
    file: password.txt

pour construire, exécuter:

docker-compose up -d

autre lecture:

0
répondu Murmel 2018-01-26 11:32:17

la méthodologie de l'application à 12 facteurs indique que toute configuration doit être stockée dans les variables d'environnement.

docker composer pourrait faire substitution variable dans la configuration, de sorte que pourrait être utilisé pour passer des mots de passe de l'hôte au docker.

0
répondu Bunyk 2018-06-07 15:28:38