J'ai récemment expérimenté Docker sur la création de services avec lesquels jouer et une chose qui me harcèle toujours est de mettre des mots de passe dans un Dockerfile. Je suis un développeur, donc stocker les mots de passe dans la source ressemble à un coup de poing dans le visage. Cela devrait-il même être un problème? Existe-t-il de bonnes conventions sur la façon de gérer les mots de passe dans Dockerfiles?
162
Réponses:
C'est certainement une préoccupation. Les fichiers Docker sont généralement archivés dans des référentiels et partagés avec d'autres personnes. Une alternative consiste à fournir des informations d'identification (noms d'utilisateur, mots de passe, jetons, tout ce qui est sensible) en tant que variables d'environnement lors de l'exécution . Cela est possible via l'
-e
argument (pour les variables individuelles sur la CLI) ou l'--env-file
argument (pour plusieurs variables dans un fichier) àdocker run
. Lisez ceci pour utiliser l'environnement avec docker-compose.L'utilisation
--env-file
est certainement une option plus sûre car elle protège contre les secrets apparaissant dansps
ou dans les journaux si l'on utiliseset -x
.Cependant, les variables d'environnement ne sont pas non plus particulièrement sécurisées. Ils sont visibles via
docker inspect
, et sont donc disponibles pour tout utilisateur pouvant exécuter desdocker
commandes. (Bien sûr, tout utilisateur qui a accès àdocker
sur l'hôte a également la racine de toute façon.)Mon modèle préféré est d'utiliser un script wrapper comme
ENTRYPOINT
ouCMD
. Le script wrapper peut d'abord importer des secrets d'un emplacement extérieur dans le conteneur au moment de l'exécution, puis exécuter l'application en fournissant les secrets. Les mécanismes exacts de cela varient en fonction de votre environnement d'exécution. Dans AWS, vous pouvez utiliser une combinaison de rôles IAM, du service de gestion de clés et de S3 pour stocker des secrets chiffrés dans un compartiment 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 une question SO sur ce sujet. Vous pouvez utiliser docker-squash pour supprimer des calques d'une image. Mais il n'y a pas de fonctionnalité native dans Docker à cet effet.
Vous pouvez trouver des commentaires timides sur la configuration dans des conteneurs utiles.
la source
.config
fichier.docker inspect
.docker inspect
. Si l'attaquant peut déjà sudo, arracher votre mot de passe de docker inspect est probablement assez bas sur votre liste de choses qui peuvent maintenant mal tourner. Ce détail particulier me semble être un risque acceptable.Notre équipe évite de mettre des informations d'identification dans des référentiels, ce qui signifie qu'elles ne sont pas autorisées
Dockerfile
. Notre meilleure pratique dans les applications consiste à 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 contenant les variables d'environnement du conteneur:Assurez-vous d'ajouter
.env
à.gitignore
, puis définissez les informations d'identification dans le.env
fichier comme:Stockez le
.env
fichier localement ou dans un emplacement sécurisé où le reste de l'équipe peut le récupérer.Voir: https://docs.docker.com/compose/environment-variables/#/the-env-file
la source
.gitignore
afin que le.env
fichier contenant des informations sensibles ne soit pas archivé sur GitHub. Je suis sûr que cela ne fonctionnera pas si vous l'ajoutez.dockerignore
.env
fichier et que je fais un déploiement sur un serveur sur site, suggérez-vous de créer à.env
nouveau le fichier sur le serveur manuellement?Docker maintenant (version 1.13 ou 17.06 et supérieure) prend en charge la gestion des informations secrètes. Voici un aperçu et une documentation plus détaillée
Une fonctionnalité similaire existe dans kubernetes et DCOS
la source
docker secret create
:: créer un secretdocker secret inspect
: afficher des informations détaillées sur un secretdocker secret ls
: afficher tous les secretsdocker secret rm
: supprimer un--secret
indicateur de secret spécifique pourdocker service create
: créer un secret lors de la création du service--secret-add
et des--secret-rm
indicateurs pourdocker service update
: mettre à jour la valeur d'un secret ou supprimer un secret pendant la tâche de mise à jour du service. Les secrets Docker sont protégés au repos sur les nœuds de gestionnaire et fournis aux nœuds de travail lors du démarrage du conteneur.Vous ne devez jamais ajouter d'informations d'identification à un conteneur à moins que vous ne souhaitiez diffuser les informations à quiconque peut télécharger l'image. En particulier, faire et
ADD creds
et plusRUN rm creds
n'est pas sécurisé 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 vue lorsque vous avez besoin de creds pour extraire des dépendances, c'est d'utiliser un conteneur pour en créer un autre. Par exemple, vous avez généralement un environnement de construction dans votre conteneur de base et vous devez l'appeler pour créer votre conteneur d'application. La solution simple consiste donc à ajouter la source de votre application, puis
RUN
les commandes de construction. Ce n'est pas sûr si vous avez besoin de crédits pour celaRUN
. Au lieu de cela, vous placez votre source dans un répertoire local, exécutez (comme dansdocker run
) le conteneur pour effectuer l'étape de construction avec le répertoire source local monté en tant que volume et les creds injectés ou montés en tant qu'un autre volume. Une fois l'étape de construction terminée, vous construisez votre conteneur final en insérant simplementADD
le répertoire source local qui contient maintenant les artefacts générés.J'espère que Docker ajoute quelques fonctionnalités pour simplifier tout cela!
Mise à jour: il semble que la méthode à venir sera d'avoir des versions imbriquées. En bref, le dockerfile décrirait un premier conteneur utilisé pour créer l'environnement d'exécution, puis une deuxième génération de conteneur imbriquée qui peut assembler toutes les pièces dans le conteneur final. De cette façon, les éléments de construction ne sont pas dans le deuxième conteneur. Il s'agit d'une application Java où vous avez besoin du JDK pour créer l'application, mais uniquement du JRE pour l'exécuter. Un certain nombre de propositions sont en cours de discussion, il est préférable de commencer à partir de https://github.com/docker/docker/issues/7115 et de suivre certains des liens pour des propositions alternatives.
la source
Une alternative à l'utilisation de variables d'environnement, qui peut devenir compliquée si vous en avez beaucoup, consiste à utiliser des volumes pour rendre un répertoire sur l'hôte accessible dans le conteneur.
Si vous placez toutes vos informations d'identification sous forme de fichiers dans ce dossier, le conteneur peut lire les fichiers et les utiliser à sa guise.
Par exemple:
De nombreux programmes peuvent lire leurs informations d'identification à partir d'un fichier séparé, vous pouvez donc simplement pointer le programme vers l'un des fichiers.
la source
solution d'exécution uniquement
docker-compose fournit également une solution en mode non-swarm (depuis v1.11: Secrets utilisant des montages de liaison ).
Les secrets sont montés sous forme de fichiers ci
/run/secrets/
- dessous par docker-compose. Cela résout le problème au moment de l'exécution (exécution du conteneur), mais pas au moment de la construction (création de l'image), car il/run/secrets/
n'est pas monté au moment de la construction. De plus, ce comportement dépend de l'exécution du conteneur avec docker-compose.Exemple:
Dockerfile
docker-compose.yml
Pour construire, exécutez:
Lectures complémentaires:
la source
Avec Docker v1.9, vous pouvez utiliser l' instruction ARG pour récupérer les arguments passés par ligne de commande à l'image lors de l' action de construction . Utilisez simplement l' indicateur --build-arg . Ainsi, vous pouvez éviter de conserver un mot de passe explicite (ou d'autres informations sensibles) sur le 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
commande de construction d'image
pendant la construction, il imprime
J'espère que ça aide! Au revoir.
la source
--build-arg var=secret
pour passer une clé privée SSH dans une image, il n'y a aucune justification documentée. Quelqu'un peut-il l'expliquer?docker history
exposebuild-arg
/ARG
variables. On peut extraire n'importe quelle image, l'inspecter et voir tous les secrets passés lors de la construction en tant que paramètrebuild-arg
/ARG
.Mon approche semble fonctionner, mais elle est probablement naïve. Dites-moi pourquoi c'est faux.
Les ARG définis lors de la construction du docker sont exposés par la sous-commande history, donc n'allez pas là-bas. Cependant, lors de l'exécution d'un conteneur, les variables d'environnement données dans la commande d'exécution sont disponibles pour le conteneur, mais ne font pas partie de l'image.
Donc, dans le Dockerfile, effectuez une configuration qui n'implique pas de données secrètes. Définissez un CMD de quelque chose comme
/root/finish.sh
. Dans la commande d'exécution, 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, placez-les dans un fichier chargé par le docker exécuté avec le
--env-file
commutateur. Bien sûr, gardez le fichier secret..gitignore
et autres choses de ce genre.Pour moi,
finish.sh
exécute un programme Python. Il vérifie qu'il n'a pas été exécuté avant, puis termine l'installation (par exemple, copie le nom de la base de données dans Djangosettings.py
).la source
Il existe une nouvelle commande docker pour la gestion des "secrets". Mais cela ne fonctionne que pour les amas d'essaims.
la source
La méthodologie de l'application 12-Factor indique que toute configuration doit être stockée dans des variables d'environnement.
Docker compose pourrait effectuer une substitution de variable dans la configuration, ce qui pourrait être utilisé pour passer des mots de passe d'hôte à docker.
la source
Bien que je sois totalement d'accord, il n'y a pas de solution simple. Il y a toujours un point de défaillance unique. Soit le fichier dockerfile, etcd, etc. Apcera a un plan qui ressemble à un sidekick - une double authentification. En d'autres termes, deux conteneurs ne peuvent pas parler sauf s'il existe une règle de configuration Apcera. Dans leur démo, l'uid / pwd était en clair et ne pouvait pas être réutilisé jusqu'à ce que l'administrateur ait configuré le lien. Pour que cela fonctionne, cependant, cela impliquait probablement de patcher Docker ou au moins le plugin réseau (s'il y a une telle chose).
la source