Moby: Secrets : rédiger les bonnes pratiques, les choses à faire et à ne pas faire, la feuille de route

Créé le 26 mai 2015  ·  203Commentaires  ·  Source: moby/moby

La gestion des secrets (mots de passe, clés et autres) dans Docker est un sujet récurrent. De nombreuses demandes d'extraction ont été « détournées » par des personnes souhaitant (mal) utiliser une fonctionnalité spécifique pour gérer les secrets.

Jusqu'à présent, nous ne faisons que décourager les gens à utiliser ces fonctionnalités, car elles sont soit manifestement peu sûres, soit non conçues pour gérer les secrets, donc "peut-être" peu sûres. Nous _ne_ leur proposons pas de vraies alternatives, du moins, pas pour toutes les situations et _si_, alors sans exemple pratique.

Je pense juste que les "secrets" sont quelque chose qui est resté trop longtemps. Cela a pour conséquence que les utilisateurs utilisent (mal) des fonctionnalités qui ne sont pas conçues pour cela (avec pour effet secondaire que les discussions sont polluées par des demandes de fonctionnalités dans ce domaine) et les font sauter à travers des cerceaux juste pour pouvoir travailler avec des secrets.

Fonctionnalités / hacks qui sont (mal) utilisés pour des secrets

Cette liste est probablement incomplète, mais mérite d'être mentionnée

  • Variables d'environnement . Probablement la plus utilisée, car elle fait partie de la "12 factor app" . Les variables d'environnement sont déconseillées, car elles le sont ;

    • Accessible par n'importe quel processus dans le conteneur, donc facilement "fuite"

    • Conservé dans les couches intermédiaires d'une image et visible dans docker inspect

    • Partagé avec n'importe quel conteneur lié au conteneur

  • Variables d'environnement au moment de la construction (https://github.com/docker/docker/pull/9176, https://github.com/docker/docker/pull/15182). Les variables d'environnement de génération n'ont pas été conçues pour gérer les secrets. Par manque d'autres options, les gens envisagent de les utiliser pour cela. Pour éviter de donner l'_impression_ qu'elles conviennent aux secrets, il a été décidé de ne pas crypter délibérément ces variables dans le processus.
  • Marquez .. Écrasez / Aplatissez les couches . (https://github.com/docker/docker/issues/332, https://github.com/docker/docker/pull/12198, https://github.com/docker/docker/pull/4232, https://github.com/docker/docker/pull/4232, https ://github.com/docker/docker/pull/9591). L'écrasement des couches supprimera les couches intermédiaires de l'image finale, cependant, les secrets utilisés dans ces couches intermédiaires se retrouveront toujours dans le cache de génération.
  • Les tomes . Certaines personnes de l'IIRC ont pu utiliser le fait que les volumes sont recréés pour chaque étape de construction, ce qui leur permet de stocker des secrets. Je ne suis pas sûr que cela fonctionne réellement et je ne trouve pas la référence à la façon dont cela est fait.
  • Construire manuellement des conteneurs . Ignorez l'utilisation d'un Dockerfile et créez manuellement un conteneur, en livrant les résultats à une image
  • Hacks personnalisés . Par exemple, héberger des secrets sur un serveur, curl -ing les secrets et les supprimer par la suite, le tout sur une seule couche. (voir aussi https://github.com/dockito/vault)

Alors, qu'est-ce qu'il faut ?

  • Ajoutez de la documentation sur les « à faire » et les « à ne pas faire » lorsque vous traitez des secrets ; @diogomonica a fait d'excellents points dans https://github.com/docker/docker/pull/9176#issuecomment -99542089
  • Décrivez la manière officiellement « approuvée »/approuvée de gérer les secrets, si possible, en utilisant les fonctionnalités _current_
  • Fournir une feuille de route / une conception pour la gestion officielle des secrets, nous pouvons vouloir rendre cela enfichable, afin que nous n'ayons pas à réinventer la roue et à utiliser les offres existantes dans ce domaine, par exemple, Vault , Keywiz , Sneaker

Ce qui précède doit être écrit/conçu en gardant à l'esprit les secrets de construction et d' exécution

@calavera a créé une preuve de concept rapide et sale sur la façon dont les nouveaux pilotes de volume (https://github.com/docker/docker/pull/13161) pourraient être utilisés pour cela ; https://github.com/calavera/docker-volume-keywhiz-fs

Remarque : Les variables d'environnement sont utilisées comme norme de facto pour transmettre la configuration/les paramètres, y compris les secrets aux conteneurs. Cela inclut les images officielles sur Docker Hub (par exemple MySQL , WordPress , PostgreSQL ). Ces images doivent adopter les nouvelles « meilleures pratiques » lorsqu'elles sont écrites/mises en œuvre.

Dans la bonne tradition, voici quelques anciennes propositions de manipulation des secrets ;

aresecurity statuneeds-attention

Commentaire le plus utile

Je sais que c'est hors sujet, mais quelqu'un d'autre a-t-il remarqué que ce problème est actif depuis près d'un an maintenant ! Demain, c'est son anniversaire. ??

Tous les 203 commentaires

ping @ewindisch @diogomonica @NathanMcCauley Ceci est juste une brève

@dreamcat4, il est prévu de mettre en œuvre une "API secrète" générique, qui vous permettrait d'utiliser soit Vault, soit Keywiz ou vous-même avec Docker, mais tout de la même manière. Il ne s'agit que d'une réflexion préliminaire, elle nécessitera donc des recherches supplémentaires.

@thaJeztah Oui Désolé, je ne veux en aucun cas nuire à ces efforts / discussions. Je pense plutôt que c'est peut-être aussi un exercice utile (dans le cadre de ce processus plus long et pendant que nous attendons) pour voir jusqu'où nous pouvons aller maintenant. Ensuite, il montre plus clairement aux autres les limites et les lacunes du processus actuel. Quel sous-jacent manque et a le plus besoin d'être ajouté pour améliorer les secrets.

Il convient également de considérer les différentes situations des secrets d'exécution et des secrets de construction. Pour laquelle il existe également une zone de chevauchement de zone.

Et peut-être aussi (pour docker) il vaut peut-être la peine de considérer les limitations (pour/contre) entre les solutions qui fournissent un mécanisme pour gérer les secrets "en mémoire". Par opposition à des méthodes secrètes plus fortement basées sur des fichiers ou à des méthodes basées sur le réseau, par exemple un serveur secret local. Quels sont les hacks actuels sur la table (jusqu'à l'API des secrets appropriés). Cela peut nous aider à comprendre une partie de la valeur unique (par exemple, une sécurité renforcée) ajoutée par une API de secrets docker qui ne pourrait pas être obtenue autrement en utilisant des hacks en plus de l'ensemble de fonctionnalités docker actuel. Cependant, je ne suis pas un expert en sécurité. Je ne peux donc pas vraiment commenter ces choses avec une telle certitude.

@ dreamcat4 oui, vous avez raison ; à court terme, ces liens sont en effet utiles.

Il convient également de considérer les différentes situations des secrets d'exécution et des secrets de construction. Pour laquelle il existe également une zone de chevauchement de zone.

Merci! Je pense que j'avais cela dans ma description originale, j'ai dû me perdre dans le processus. je vais ajouter une balle

Cependant, je ne suis pas un expert en sécurité.

Moi non plus, c'est pourquoi j'ai « pingé » les responsables de la sécurité ; OMI, cela devrait être quelque chose d'écrit par eux 😇

@thaJeztah excellent résumé. J'essaierai d'y toucher dès que je trouverai un peu de temps.

@diogomonica bien que n'étant pas _directement_ lié, il existe une longue demande de fonctionnalité ouverte pour le transfert de l'agent de clé SSH pendant la construction ; https://github.com/docker/docker/issues/6396 étant donné le nombre de commentaires, il serait bon d'y réfléchir également. (Si même pour prendre une décision à ce sujet si oui ou non il peut/doit être mis en œuvre)

En supposant que vous puissiez monter des volumes en tant qu'utilisateur autre que root (je sais que c'est impossible, mais faites-moi plaisir), serait-ce une approche favorable pour mettre des secrets dans des conteneurs ?

Si tel est le cas, je préconiserais une alternative à -v host_dir:image_dir qui attend l'utilisation d'un conteneur de données uniquement et pourrait ressembler à -vc host_dir:image_dir (c'est-à-dire une copie de volume) dans laquelle le contenu de host_dir est copié dans le volume image_dir sur le conteneur de données uniquement.

Nous pourrions alors mettre l'accent sur un paradigme secure-data-only containers et permettre à ces volumes d'être chiffrés

J'ai récemment lu un bon article à ce sujet de @jrslv où il propose de créer une image docker spéciale avec des secrets juste pour créer votre application, puis de créer une autre image pour la distribution en utilisant les résultats de l'exécution de l'image de construction.

Vous avez donc deux Dockerfiles :

  • Dockerfile.build (ici vous copiez simplement tous vos secrets)
  • Dockerfile.dist (celui-ci que vous pousserez vers le registre)

Maintenant, nous pouvons construire notre distribution comme ça :

# !/bin/sh
docker build -t hello-world-build -f Dockerfile.build .
docker run hello-world-build >build.tar.gz 
docker build -t hello-world -f Dockerfile.dist ^

Vos secrets sont en sécurité, car vous ne poussez jamais l'image hello-world-build .

Je recommande de lire l'article @jrslv pour plus de détails http://resources.codeship.com/ebooks/continuous-integration-continuous-delivery-with-docker

Merci pour le partage @kepkin !
Je viens de finir de lire l'article. Vraiment concis !

J'aime l'idée d'exporter les fichiers et de les charger via un Dockerfile séparé. On a l'impression d'écraser sans le problème des "couches intermédiaires dans le cache de construction".

Cependant, je crains que cela ne complique le développement et puisse nécessiter un troisième Dockerfile pour plus de simplicité.

@kepkin aucune offense mais cela n'a aucun sens. Les secrets ne sont certainement pas sûrs, car ils sont dans l'archive tar et l'archive tar est ADD ed à l'image de production -- même si vous supprimez l'archive tar, sans écraser, elle fuira dans une couche.

@TomasTomecek si je comprends bien l'exemple, l'archive n'est _pas_ les couches d'image, mais juste le binaire qui a été construit à l'intérieur du conteneur de construction. Voir par exemple ; https://github.com/docker-library/hello-world/blob/master/update.sh (pas de secrets impliqués ici, mais juste un exemple simple d'un conteneur de construction)

@TomasTomecek Je parle des secrets pour créer une image Docker. Par exemple, vous devez transmettre la clé ssh pour extraire le code source de votre référentiel GitHub privé. Et l'archive tar ne contient que des artefacts de build mais ne contient pas de clé GitHub.

@kepkin à droite, maintenant je lis à nouveau votre message et je peux le voir. Désolé pour ça. Malheureusement, cela ne résout pas le problème lorsque vous avez besoin de secrets pendant le déploiement/la création de l'image de distribution (par exemple, la récupération d'artefacts et l'authentification avec le service d'artefact). Mais c'est certainement une bonne solution pour séparer le processus de construction et le processus de publication.

@TomasTomecek c'est exactement comme ça que je récupère les artefacts en fait.

Dans l'image Docker.build, je télécharge des dépendances binaires à partir de l'image Amazon S3 qui nécessitent une clé et un secret AWS. Après avoir récupéré et construit, je crée une archive avec tout ce dont j'ai besoin.

Existe-t-il un article canonique sur les « meilleures pratiques » – les « À faire » et les « À ne pas faire » – que vous recommanderiez tous de lire ?

Il convient de noter (pour quiconque comme moi qui tombe dessus) que Docker Compose prend en charge une option env_file .

https://docs.docker.com/compose/compose-file/#env -file

@afeld docker lui-même a également cette fonctionnalité, voir http://docs.docker.com/engine/reference/commandline/run/#set -environment-variables-e-env-env-file mais ces env-vars seront toujours présentez-vous aux mêmes endroits, alors ne faites pas de différence par rapport à une "fuite"

@kepkin voici comment je passe une clé ssh à docker build :

# serve the ssh private key once over http on a private port.
which ncat
if [ "$?" = "0" ]; then
  ncat -lp 8000 < $HOME/.ssh/id_rsa &
else
  nc -lp 8000 < $HOME/.ssh/id_rsa &
fi
nc_pid=$!
docker build --no-cache -t bob/app .
kill $nc_pid || true

et à l'intérieur du Dockerfile où 172.17.0.1 est l'IP de la passerelle Docker :

RUN \
  mkdir -p /root/.ssh && \
  curl -s http://172.17.0.1:8000 > /root/.ssh/id_rsa && \
  chmod 600 /root/.ssh/id_rsa && chmod 700 /root/.ssh && \
  ssh-keyscan -t rsa,dsa github.com > ~/.ssh/known_hosts && \
  git clone --depth 1 --single-branch --branch prod [email protected]/app.git . && \
  npm i --production && \
  ... && \
  rm -rf /root/.npm /root/.node-gyp /root/.ssh

Si quelqu'un a quelque chose de plus simple, faites-le nous savoir.

Alors, quel est l'état actuel de cela?

Tout l'été, il y a eu de longues chaînes de conversation, indiquant à quel point cette préoccupation est répandue. Cela a été déposé en mai, et il est toujours ouvert. Par exemple, comment définir le mot de passe pour Postgres ?

@thaJeztah Que peut-on faire pour faire avancer cela ? Je suppose que de nombreux yeux à travers différents projets en aval sont sur cette question... ej. https://github.com/rancher/rancher/issues/1269

Je suppose que ce qui est fait ici est gardé _secret_ :D

C'est le plus gros problème pour nous pour l'intégration de Docker dans notre pile de production. Existe-t-il une feuille de route ou un autre document quelque part qui indique des progrès dans ce sens ?

Du contenu pertinent sur ce sujet de

Que pensez-vous de cela comme moyen potentiel d'aborder les secrets d'exécution ?
https://github.com/docker/docker/issues/19508

Je pense que ce problème serait mieux résolu en se concentrant sur quelques scénarios qui doivent être pris en charge et en veillant à ce qu'il y ait un ensemble d'instructions pour chacun. La manière dont elles sont mises en œuvre est moins importante que de savoir si, à la fin du processus, il existe un ensemble cohérent de fonctionnalités pouvant être combinées pour répondre au besoin.

Quelques-uns que j'ai vus mentionnés et qui semblent être des préoccupations assez légitimes incluent :

Informations d'identification d'exécution

  • Informations utilisateur/mot de passe coordonnées entre deux conteneurs qui partagent un link
  • Les informations sont faciles à garder hors de votre référentiel git
  • L'information est facile à garder hors de vos images poussées (et les conteneurs locaux ?)
  • Les informations sont faciles à garder en dehors de .bash_history (peut-être un pont trop éloigné ?)
  • Certaines applications attendent des secrets dans le cadre d'un fichier de configuration contenant d'autres informations
  • Certaines applications attendent des secrets comme variable d'environnement
  • Certaines applications permettent à la fois

Quand je dis « facile », je veux dire qu'il existe une approche ergonomique de la gestion de ces variables qui protège l'utilisateur contre les erreurs accidentelles et le déclenchement d'un bulletin de sécurité. Le stress de l'expérience est souvent associé (lire : blâmé) aux outils impliqués dans l'erreur.

Informations d'identification au moment de la création

  • Le projet est construit à partir d'un ou plusieurs référentiels privés (ex: package.json autorise les URL git)
  • Le constructeur peut être derrière un proxy protégé par mot de passe
  • Le constructeur utilise peut-être un cache protégé par mot de passe
  • L'utilisateur final ne se soucie que d'une image de travail (c'est-à-dire qu'il utilisera pull ou FROM, jamais docker build )
  • L'information est facile à garder hors de vos images poussées

1ère édition :

Documentation de ce qui est et n'est pas « divulgué » dans une image typique, un conteneur

  • Quels fichiers se retrouvent dans l'image (juste la copie et l'ajout ? autre chose ?)
  • Quelle docker-machine conserve après la création d'une image (en particulier boot2docker, mais qu'en est-il des autres ?)
  • Comment les variables d'environnement et de ligne de commande sont capturées dans l'image, et où elles sont capturées
  • Attentes des émetteurs de relations publiques concernant le changement de ces comportements

J'ai l'impression qu'il me manque quelques gros ici. Quelqu'un a quelque chose que j'ai oublié ?

Clés API pour tous les services json.

Par exemple (et c'est mon vrai cas d'utilisation), Docker build compile un programme, la clé API est nécessaire pour m'authentifier et télécharger le(s) produit(s) de build sur Bintray.com.

@dreamcat4 Je pourrais être loin de ce que vous dites, mais voici :

Parlez-vous d'utiliser des images Docker pour les builds de déploiement continu et de transférer les artefacts de build vers une archive à la fin d'une build réussie ? Personnellement, je préfère faire cela plus en amont (par exemple, un script post-build dans Jenkins), mais si vous effectuez une compilation croisée, cela peut être un peu plus délicat.

Dans mon monde, l'agent de construction ne fait que construire des binaires/archives et les conserve en tant qu'« artefacts » du processus de construction, et quelque chose d'autre les pousse vers l'infrastructure, balise le référentiel git, etc. Cela me donne une sauvegarde d'urgence des artefacts si je avez un problème de production et, disons, mon référentiel npm, docker ou Artifactory est en panne pour des mises à niveau, ou le réseau me dérange.

Le point que j'essayais de faire concernait l'utilisation des clés API en général. Il existe de nombreux services JSON/rest en ligne différents et variés avec lesquels un conteneur peut avoir besoin d'interagir (que ce soit au moment de la construction ou de l'exécution)... ce qui nécessite des clés API. N'a pas besoin d'être spécifiquement lié à la construction.

@dreamcat oh, alors jetons d'authentification pour les points de terminaison REST ? Pensez-vous que ceux-ci sont gérés de manière sensiblement différente de, disons, votre mot de passe postgres dans un fichier de configuration, ou les géreriez-vous de la même manière ?

Oui, je pense que ces deux types devraient être considérés différemment en termes d'évaluation de leur niveau minimum de sécurité de base.

Les jetons d'authentification API ont souvent tendance à être :

  • Ne sont pas des mots de passe
  • Peut être révoqué
  • Certains (un sous-ensemble beaucoup moins nombreux) sont à usage unique - jetables. Et essentiellement s'invalider.
  • Souvent, les services d'API sont limités dans leur portée à un sous-ensemble de fonctionnalités. (c'est-à-dire en lecture seule, ou ne peut déclencher qu'une action spécifique).

Les mots de passe ont tendance à être/sont souvent :

  • Pour un accès/contrôle de compte plus complet.
  • Une fois compromis, peut être changé par l'attaquant en quelque chose d'autre (verrouillage). Ou autre porte dérobée insérée (comme la modification de la base de données d'autres comptes détenus dans la base de données, dans le cas de SQL).
  • Le fait d'être un mot de passe présente un risque très élevé de « réutilisation du même mot de passe » parmi d'autres comptes. Alors que les clés API ont tendance à être toujours uniques et non utilisables pour autre chose.

Cela ne signifie donc pas nécessairement que la solution des secrets _doit être différente_ pour ces 2 types. Juste que le niveau de sécurité de base minimum acceptable peut être un peu plus bas pour les clés API.

Ce niveau minimum est important si une sécurité renforcée est plus complexe / problématique à configurer. (ce qui peut être vrai ici dans le cas des secrets de docker, ou non selon la faisabilité / l'élégance de la solution).

Et parfois, les clés API des mots de passe peuvent avoir une sécurité plus forte / plus faible. Juste que si une taille unique n'est pas possible.

Par exemple - ma clé API bintray : qui est conservée dans le même référentiel .git que mon Dockerfile. Donc, pour le garder en sécurité, il est conservé dans un dépôt git PRIVÉ (accessible via SSH). L'accès à la clé API est donc relativement bien protégé là-bas. Cependant, sans que docker n'ait ses propres fonctionnalités/protections secrètes intégrées, l'image docker construite inclut toujours la clé API en texte brut. Par conséquent, l'image de construction Docker résultante doit rester privée comme le référentiel git...

Ce n'est pas idéal à bien des égards. Mais la solution globale est assez simple et fonctionne réellement (comme dans : hier). S'il y avait un meilleur mécanisme à l'avenir, j'envisagerais de passer à celui-ci. Mais pas si ce mécanisme était nettement plus coûteux/complexe à mettre en place que la solution actuelle que j'ai déjà élaborée. Par conséquent, une sécurité extra-forte (bien que bienvenue) peut être excessive dans le cas d'une seule clé api. Ce qui doit simplement être conservé hors du cache des couches d'images de docker avec une sorte de nouvelle option NOCAHCE / commande Dockerfile.

Alors qu'un mot de passe a besoin de quelque chose comme un coffre-fort ou un coffre-fort ansible, et doit être chiffré avec un autre mot de passe ou un autre mécanisme d'authentification fortement sécurisé. (Ce que nous espérons ne pas, mais peut être une chose complexe à configurer).

Je pense qu'un modèle client/serveur (comme dans le coffre-fort ) pour gérer et rationaliser (lire : audit, bris de vitre) tous les trucs liés aux secrets serait une bonne pratique et couvrirait la plupart des cas d'utilisation, si la mise en œuvre était faite de manière réfléchie. Personnellement, je ne suis pas partisan d'adopter une approche non holistique, car c'est l'occasion de hausser la barre des meilleures pratiques.

Cela implique un client de longue durée (responsabilité de la personne qui déploie une image) et/ou un client build-time (responsabilité du constructeur). Peut-être que le premier pourrait être transféré d'une manière ou d'une autre au démon docker qui fournit des secrets autorisés au moment de l'exécution.

En effet - je suis entièrement d'accord avec le commentaire précédent. Non pas que je n'admire pas les manières créatives dont les gens résolvent le problème, mais je ne pense pas que ce soit ainsi que cela doit être - essayons de penser à une solution qui pourrait être utilisée à la fois pendant la CI/D et l'exécution , ainsi que la prise en compte du fait que les conteneurs peuvent être orchestrés par Mesos/Kubernetes, etc.

Eh bien, je pense qu'un peu de documentation serait toujours utile ici, car Docker présente quelques problèmes supplémentaires dans l'espace du problème.

Il semble que les gars de Vault envisagent également cela de leur côté. Je pense que ce billet est celui à surveiller :

https://github.com/hashicorp/vault/issues/165

C'est peut-être quelque chose sur lequel on pourrait collaborer.

@jdmarshall

C'est peut-être quelque chose sur lequel on pourrait collaborer.

+1

+1 Docker + Hashi Corp Vault

Désolé, mais je n'aime pas la complexité des solutions à mesure que de plus en plus de personnes s'y mettent. Hashi Corp Vault, par exemple, est une solution client-serveur complète avec un stockage back-end crypté. Cela ajoute beaucoup plus de pièces mobiles. Je suis sûr que certains cas d'utilisation exigent ce niveau de complexité, mais je doute que la plupart le fassent. Si la solution concurrente consiste à utiliser des variables d'environnement hôte, je suis à peu près sûr de celles qui finiront par être utilisées par la majorité des développeurs.

Je recherche une solution qui couvre le développement (par exemple : clés github) et le déploiement (par exemple : clés de certification nginx, informations d'identification db). Je ne veux pas polluer l'hôte avec des vars env ou des outils de construction et bien sûr, aucun secret ne devrait se retrouver dans github (non crypté) ou dans un répertoire d'images docker, même privé.

@gittycat Je suis d'accord avec vous dans le sens où il existe probablement plusieurs cas d'utilisation distincts. Par conséquent, certaines des solutions devraient être plus simples que d'autres.

Nous devrions certainement éviter de recourir aux vars ENV.

Ma propre préférence penche vers l'idée qu'un simple stockage de clés pourrait être réalisé avec quelque chose qui s'apparente au mécanisme de "voûte" d'ansible. Où vous avez un fichier texte crypté contenu dans le contexte de construction (ou des sources en dehors/à côté du contexte de construction). Ensuite, une clé de déverrouillage peut déverrouiller n'importe quel mot de passe en clair ou clé API, etc. de ce fichier.

Je dis juste cela après avoir utilisé la propre solution de "vault" d'anisible. Ce qui est relativement indolore/simple. Le coffre-fort de Hashicorp est plus sécurisé, mais il est également plus difficile à configurer et généralement plus complexe. Bien que je ne connaisse aucune raison technique pour laquelle vous ne pourriez finalement pas utiliser cela en dessous comme backend (cachez-le / simplifiez-le derrière un outil de ligne de commande orienté docker).

Je suggérerais le stockage de fichiers local car cela évite d'avoir à configurer un serveur de stockage de clés HTTP complexe et potentiellement peu fiable. Le stockage des secrets est une question de sécurité et devrait donc être disponible pour tous les utilisateurs, pas seulement pour les entreprises. Juste mon avis à 2 cents.

+1 à un backend de stockage de fichiers local, pour des cas d'utilisation plus avancés, je préférerais cependant la pleine puissance d'une solution de type Hashicorp Vault. Quand on parle de déploiement, dans une organisation, l'argument est que les personnes qui fournissent et contrôlent les secrets sont d'autres personnes que celles qui les utilisent. Il s'agit d'une mesure de sécurité courante pour limiter le cercle des personnes ayant un pouvoir de contrôle à des ingénieurs de sécurité très fiables...

Je ne sais pas si cela est utile ou fonctionnerait, mais voici une petite suggestion de champ gauche pour résoudre le cas où je veux injecter un secret dans un conteneur au moment de l'exécution (par exemple un mot de passe postgres)

Si je pouvais remplacer à docker run time le point d'entrée et le définir sur un script de mon choix, par exemple /sbin/get_secrets, qui, après avoir obtenu les secrets d'un mécanisme de mon choix (par exemple, KMS), exécuterait le point d'entrée d'origine (devenant ainsi un simple wrapper dont le seul but était de configurer des variables d'environnement avec des secrets à l'intérieur du conteneur. Un tel script pourrait être fourni lors de l'exécution via un montage de volume. Un tel mécanisme n'impliquerait jamais l'écriture de secrets sur le disque ( l'un de mes animaux de compagnie déteste), ou fuite par docker (ne fait pas partie de docker inspect), mais garantirait qu'ils n'existent qu'à l'intérieur de l'environnement du processus 1 à l'intérieur du conteneur, qui conserve le facteur 12.

Vous pouvez déjà le faire (je crois) si le point d'entrée n'est pas utilisé dans les métadonnées de l'image, mais seul cmd l'est, car le point d'entrée encapsule ensuite la commande. Comme mentionné, le wrapper peut ensuite être monté au moment de l'exécution via un volmount. Si le point d'entrée est déjà utilisé dans les métadonnées de l'image, je pense que vous ne pouvez pas le faire pour le moment, à moins qu'il ne soit possible de voir quel était le point d'entrée d'origine depuis l'intérieur du conteneur (pas le remplacement de la ligne de commande) - vous ne savez pas si vous pouvez le faire ou non .

Enfin, je pense qu'il serait même possible de fournir une clé à usage unique cryptée via l'injection traditionnelle de var env avec laquelle les /sbin/get_secrets externes pourraient utiliser pour demander les secrets réels (par exemple le mot de passe postgres), ajoutant ainsi une protection supplémentaire dans docker fuite de la clé à usage unique.

Je ne peux pas déterminer s'il ne s'agit que de couches sur couches, ou si cela résout potentiellement le problème .. excuses si ce n'est que le premier.

@thaJeztah - Je peux confirmer que la solution que je pose ci-dessus fonctionne, les secrets se manifestent sans être divulgués par docker, ils n'existent qu'en mémoire pour le processus 1 via des variables d'environnement qui sont parfaitement conformes à 12 facteurs, mais ils ne s'affichent PAS dans docker api sous docker inspect, ou n'importe où ailleurs car ils sont spécifiques au processus 1. Aucun travail n'est requis dans l'image pour que cela fonctionne. Dans mon cas, j'ai compilé un binaire statique golang pour récupérer les secrets, afin qu'il puisse être monté sur le volume et remplacer le point d'entrée avec cela, le binaire émet un exécutable sys pour transférer le contrôle au point d'entrée défini par l'image une fois terminé.

@gtmtech Intéressant. Serait intéressé de savoir comment vous avez découvert le point d'entrée d'origine à partir de votre binaire get secrets.

Peut-être qu'un exemple de dossier de code rendrait l'approche un peu plus facile à démontrer/comprendre.

Exemple de code et scénarios de travail ici @dreamcat4 @kaos >

https://github.com/gtmtechltd/secret-squirrel

Je me trompe peut-être, mais pourquoi ces méthodes compliquées ? Je m'appuie sur les autorisations de fichiers Unix standard. Transmettez tous les secrets à docker avec -v /etc/secrets/docker1:/etc/secrets lisible uniquement par root, puis un script s'exécute au démarrage du conteneur en tant que root, qui transmet les secrets aux endroits appropriés pour les programmes pertinents (par exemple, la configuration Apache). Ces programmes suppriment les autorisations root au démarrage, donc s'ils sont piratés, ils ne peuvent pas lire le secret appartenant à root plus tard. Cette méthode que j'utilise est-elle en quelque sorte imparfaite?

Merci @gtmtech :)
Malheureusement, nous n'avons pas de point d'entrée standard et je ne suis pas non plus en mesure d'exécuter docker inspect avant l'exécution de docker de manière contrôlée. Mais j'aime votre approche.

Je me trompe peut-être, mais pourquoi ces méthodes compliquées ? Je m'appuie sur les autorisations de fichiers Unix standard. Transmettez tous les secrets à docker avec -v /etc/secrets/docker1:/etc/secrets lisible uniquement par root, puis un script s'exécute au démarrage du conteneur en tant que root, qui transmet les secrets aux endroits appropriés pour les programmes pertinents (par exemple apache configuration). Ces programmes suppriment les autorisations root au démarrage, donc s'ils sont piratés, ils ne peuvent pas lire le secret appartenant à root plus tard. Cette méthode que j'utilise est-elle en quelque sorte imparfaite?

Salut,
Je suis d'accord et pense que cette approche ^^ devrait être généralement recommandée comme meilleur moyen pour les secrets RUNTIME. À moins que quelqu'un d'autre ici ait une forte objection contre cela. Après quoi, vous pouvez ensuite lister également tous les cas de coin restants (au RUNTIME) qui ne sont pas couverts par cela ^^.

Malheureusement, je ne peux pas voir l'écureuil secret décoller car il est tout simplement trop compliqué pour la plupart des personnes non techniques régulières à apprendre et à adopter comme une stratégie populaire.

Alors ça part (vous l'avez probablement déjà deviné)...
Secrets de construction !

Mais je pense que c'est un progrès ! Puisqu'après une longue période sans vraiment arriver à rien, cela réduit peut-être les choses de moitié et résout environ 45 à 50% du problème total.

Et s'il reste encore des problèmes autour des secrets, au moins ils seront plus spécifiques / concentrés et pourront continuer à progresser / s'attaquer par la suite.

Oui, je n'entrerai pas dans trop de détails, mais ces approches ne fonctionneraient jamais pour une situation avec laquelle je travaille actuellement, car j'ai besoin d'un niveau de sécurité plus élevé que celui qu'elles offrent. Par exemple, pas de secrets non cryptés sur le disque, pas de clés de décryptage valides une fois qu'elles ont été décryptées dans le processus cible, rotation de cryptage régulière et référentiel unique pour les secrets cryptés (et non répartis sur les serveurs). C'est donc plus pour les personnes qui doivent faire ce niveau de sécurité que j'ai suggéré une approche possible.

secret_squirrel est de toute façon un hack dans un espace où je ne vois pas encore de solutions viables, autour de docker ne fournissant pas encore d'API secrète, ou un pilote de secrets enfichable, ce qui, espérons-le, ils le feront à un moment donné, mais cela sert peut-être à illustrer ce paramètre ENV vars à l'intérieur du conteneur avant l'exécution du processus, mais pas dans le cadre du processus de création de docker (ou des métadonnées) est un moyen sécurisé d'être conforme à 12 facteurs avec les secrets, et peut-être que la communauté de développement de docker peut utiliser cette idée lorsqu'elle commence à créer un secrets-api/driver s'ils pensent que c'est un bon !

Bon docker !

Nous avons utilisé le type d'approche décrit par @gtmtech , avec un grand succès. Nous injectons des secrets chiffrés KMS via des variables d'environnement, puis laissons le code à l'intérieur du conteneur déchiffrer selon les besoins.

Cela implique généralement un simple point d'entrée de cale, devant l'application. Nous implémentons actuellement cette cale avec une combinaison de shell et un petit binaire Golang (https://github.com/realestate-com-au/shush), mais j'aime le son de l'approche pure-Go.

@gtmtech @mdub Je serais certainement ravi d'en voir plus.
@ dreamcat4 Je pense que la définition de "compliqué" pourrait dépendre du chemin, ce qui est évidemment tout à fait correct. Pourtant, il ne peut probablement pas être un jugement abstrait. Par conséquent, cependant, un wrapper de sécurité dans le conteneur docker ne me semble pas trop compliqué au niveau de la conception. Un autre aspect concerne les meilleures pratiques : celles-ci doivent être examinées non pas uniquement du point de vue du développeur, mais du point de vue de l'exploitation.
mes 2 centimes

Coffre +1

Coffre -1. Vault a certaines caractéristiques opérationnelles (descellage) qui le rendent vraiment indésirable pour beaucoup de gens.

Avoir une API enfichable serait le plus logique.

Il y a aussi le coffre d'ansible. C'est plutôt une bête différente.

@gtmtech merci pour la suggestion, cela m'a inspiré pour écrire ce point d'entrée :

#!/bin/bash

if [ -d "/var/secrets" ]; then
  tmpfile="$(mktemp)"
  for file in /var/secrets/*
  do
    if [ -f $file ]; then
      file_contents=$(cat $file)
      filename=$(basename "$file")
      underscored_filename="${filename//-/_}"
      capitalized_filename=${underscored_filename^^}
      echo "export $capitalized_filename=$file_contents" >> $tmpfile
    fi
  done

  source $tmpfile
  rm -f $tmpfile
fi

exec "$@"

Je viens de l'ajouter dans le Dockerfile comme ceci (n'oubliez pas de chmod + x dessus):

ENTRYPOINT ["/app/docker-entrypoint.sh"]

Et voilà. ENV vars disponibles au moment de l'exécution. Assez bien :)

Si je comprends bien, le /var/secrets doit être monté via les volumes, n'est-ce pas ??
De plus, lorsqu'il y a des commentaires sur les secrets qui ne sont pas écrits sur le disque, à quel point est-ce grave de les écrire sur le disque puis de les supprimer ???

Joli! Vous devez cependant utiliser shred pour supprimer le fichier en toute sécurité.

Le jeudi 3 mars 2016, Juan Ignacio Donoso [email protected]
a écrit:

Si je comprends bien, le répertoire /var/secrets doit être monté via
volumes non ??
De plus, lorsqu'il y a des commentaires sur les secrets qui ne sont pas écrits sur le disque, comment
le mal est de les écrire sur le disque puis de les supprimer ???

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-191887424 .

Rui Marinho

Inspiré du "secret-squirrel" de @gtmtech , j'ai étendu mon outil de gestion des secrets "shush" pour le rendre utilisable comme point d'entrée d'image :

ADD shush_linux_amd64 /usr/local/bin/shush
ENTRYPOINT ["/usr/local/bin/shush", "exec", "--"]

Cela déchiffre tous les envariables KMS_ENCRYPTED_xxx réinjecte les résultats dans l'environnement.

https://github.com/realestate-com-au/shush#use -as-a-command-shim

Le fil commence donc par NE FAITES AUCUNE DE CES CHOSES.....

... mais je ne vois pas VEUILLEZ FAIRE CES CHOSES À LA PLACE... seulement diverses propositions/piratages qui ont pour la plupart été rejetés/fermés.

Quelle EST la meilleure pratique officielle pour le moment ? En tant qu'utilisateur de docker, il est quelque peu frustrant de voir une longue liste de choses que nous ne devrions pas faire, mais qu'aucune alternative officielle n'est proposée. Est-ce que j'ai raté quelque chose ? N'existe-t-il pas ? Je suis sûr que des choses se passent en coulisses et que c'est quelque chose sur lequel l'équipe Docker travaille, mais pour le moment, comment gérer au mieux la gestion des secrets jusqu'à ce qu'une solution canonique soit présentée ?

@alexkolson
D'après ce que j'ai compris, si vous avez besoin de secrets au moment de l'exécution, vous devez utiliser des volumes (secrets du système de fichiers) ou des services comme HashiCorp Vault (secrets réseau).

Pour les secrets de construction, c'est plus compliqué.
Les volumes ne sont pas pris en charge au moment de la construction, vous devez donc utiliser des conteneurs pour exécuter des commandes qui modifient le système de fichiers et utiliser docker commit.

Donc, ce qui manque, c'est une capacité à gérer les secrets sur le temps de construction en utilisant rien d'autre qu'un Dockerfile, sans avoir besoin d'utiliser docker commit .

Certaines personnes disent même que l'utilisation du système de fichiers pour les secrets n'est pas sécurisée et que le démon docker devrait fournir une API pour fournir des secrets en toute sécurité (en utilisant le réseau/le pare-feu/le volume monté automatiquement ?). Mais personne n'a même une idée de ce à quoi cette API ressemblerait et comment on l'utiliserait.

Quand je pense aux lacunes des vars env, je pense à des problèmes non spécifiques à Docker tels que :

  1. Agréger les journaux attrapant toutes les variables d'environnement ou un phpinfo oublié laissé sur un serveur Web de production - soyez donc prudent avec les secrets et la configuration correctement.
  2. Peut-être un cheval de Troie qui expose les variables d'environnement - alors n'exécutez pas de logiciel non fiable.
  3. Attaques qui exploitent des faiblesses telles que l'injection SQL - validez donc l'entrée et utilisez un pare-feu d'application Web.

Les faiblesses présentées en haut de ce fil :

Accessible par n'importe quel processus dans le conteneur, donc facilement "fuyant"

Appliquez en croix 1 et 2 d'en haut. Légitime mais adressé en faisant attention, n'est-ce pas ? De plus, votre conteneur Docker exécute beaucoup moins de processus qu'un serveur Web à pile complète.

Qu'en est-il de la configuration dans env var, mais les env vars secrètes ont des valeurs cryptées et l'application a la clé dans le code ? Il ne s'agit que d'obscurcissement, car la clé est dans le code, mais nécessiterait des exploits pour accéder à la fois à la clé et aux variables d'environnement. Utilisez peut-être la gestion de la configuration pour gérer la clé sur l'hôte docker plutôt que dans le code de l'application. Peut aider avec les processus rouges et les fuites accidentelles, mais évidemment pas les attaques par injection de quelqu'un qui a la clé.

Conservé dans les couches intermédiaires d'une image et visible dans docker inspect

Les gens préparent-ils des vars env dans des images docker plutôt que de les définir au moment de l'exécution ou est-ce que je comprends mal celui-ci. Ne jamais transformer des secrets en artefacts, n'est-ce pas ? Oui, sudo docker inspect container_name donne la var env, mais si vous êtes sur mon serveur de production, iv est déjà perdu. sudo docker inspect image_name n'a pas accès à mes variables d'environnement définies au moment de l'exécution.

Partagé avec n'importe quel conteneur lié au conteneur

Que diriez-vous de ne pas utiliser les liens et le nouveau réseau à la place ?

Le seul problème qui semble être un problème de docker et non universel est celui des liens...

Mettez-moi dans le camp des gens qui ont besoin d'un bon moyen de gérer les secrets pendant docker build . Nous utilisons composer pour certains projets php et référençons certains dépôts github privés pour les dépendances. Cela signifie que si nous voulons tout construire à l'intérieur de conteneurs, il a besoin de clés ssh pour accéder à ces dépôts privés.

Je n'ai pas trouvé de moyen bon et sensé de gérer cette situation sans vaincre certaines des autres choses que je trouve bénéfiques à propos de docker (voir : docker squash ).

J'ai maintenant dû régresser dans la construction de parties de l'application à l'extérieur du conteneur et utiliser COPY pour introduire le produit final dans le conteneur. Meh.

Je pense que docker build besoin de certaines fonctionnalités pour gérer les données éphémères comme les secrets afin qu'elles ne se retrouvent pas dans le conteneur d'expédition final.

Je pense que docker build a besoin de certaines fonctionnalités pour gérer les données éphémères comme les secrets

C'est un problème philosophique plutôt qu'un problème technique. De telles données éphémères iraient à l'encontre de l'avantage essentiel de docker : la reproductibilité.

La philosophie de Docker est que votre Dockerfile avec un contexte est suffisant pour créer une image.
Si vous avez besoin qu'un contexte soit en dehors de l'image résultante, vous devez le récupérer sur le réseau et ignorer l'écriture dans le système de fichiers. Parce que chaque ligne Dockerfile aboutit à un instantané du système de fichiers.

Si les secrets ne doivent pas faire partie d'une image, vous pouvez exécuter un conteneur éphémère, qui mettrait en miroir/proxy toutes vos ressources protégées par des secrets et fournirait un accès sans secret. La mise en miroir, d'ailleurs, a une autre justification : https://developers.slashdot.org/story/16/03/23/0652204/how-one-dev-broke-node-and-thousands-of-projects-in-11-lines -de-javascript

Vous pouvez également partager la clé ssh elle-même, mais vous ne pourrez pas contrôler son utilisation.

@bhamilton-idexx si vous vous assurez que l'authentification à vos référentiels privés fonctionne avec un jeton de courte durée, vous n'avez pas à vous soucier de la persistance du secret dans l'image docker.
Le système de build génère un jeton avec un ttl de 1 heure, rendez-le disponible en tant que variable d'environnement pour la build docker.
Votre build peut récupérer les détails de build requis, mais le secret expire peu de temps après la fin de vos builds, fermant ce vecteur d'attaque.

J'ai lu un tas de ces fils maintenant et une fonctionnalité qui résoudrait certains cas d'utilisation ici et aurait des cas d'utilisation en dehors des secrets est un indicateur --add pour docker run qui copie un fichier dans le conteneur, tout comme l'instruction ADD dans Dockerfiles

C'est en effet un excellent article. Très bonne lecture. Et exactement le genre de chose que nous espérions voir.

D'AILLEURS:

J'ai également trouvé quelques autres outils secrets qui semblent avoir été omis dans l'article. Désolé pour les répétitions/duplications. Je ne les ai pas encore remarqués mentionnés ici non plus :

Construire des secrets de temps :

https://github.com/defunctzombie/docket

Secrets d'exécution :

https://github.com/ehazlett/docker-volume-libsecret

Qu'en pensent les gens ? Merci beaucoup.

Pour moi:

Ces nouveaux outils ^^ ont l'air très bien maintenant. Et ils n'existaient certainement pas lorsque nous avons commencé ce ticket. MAIS la principale chose que je ressens maintenant me manque toujours le plus :

Avoir une meilleure capacité pour les secrets de construction sur le DockerHub. Ce qui est pauvre là-bas et oblige à choisir entre l'un ou l'autre. Nous devons renoncer aux avantages d'une solution pour les avantages de l'autre. Selon l'ensemble global de fonctionnalités qui sont les plus importantes. En tant que bâtiment local, il est définitivement meilleur pour garder les secrets en sécurité, mais naturellement pire que le Dockerhub à d'autres égards.

Nous avons écrit un autre outil, similaire à docket, qui utilise le nouveau format d'image :

https://github.com/AngryBytes/docker-surgery

Notre implémentation crée d'abord une couche contenant des secrets commentés SECRETS , puis crée une copie du Dockerfile avec un FROM modifié, construit et finalement supprime toutes les couches SECRETS de l'image résultante.

Il y a toujours des mises en garde à pirater cela, et ce serait génial si docker avait une fonctionnalité de rebasage ou d'épissage de couche intégrée. Supprimer les couches intermédiaires en ce moment est lent, car toutes les solutions doivent faire une danse docker save / docker load dans les coulisses.

De plus, la mise en cache des builds est cassée. À l'heure actuelle, nous utilisons docker commit pour créer la couche de secrets commentés, mais conserver un cache approprié de ces couches est toujours un travail de longue haleine, ce que nous avons peu de chances de faire. L'utilisation d'un Dockerfile pour créer la couche de secrets peut résoudre ce problème, mais il n'y a aucun moyen de commenter la couche, ce qui rend difficile de déterminer ce qu'il faut supprimer par la suite.

@Vanuan [Dockerfile] ne peut pas avoir de reproductibilité. La commande RUN garantit que vous et moi ne pouvons pas raisonnablement nous attendre à obtenir exactement la même image sur deux exécutions. Pourquoi? Parce que la plupart du temps, les gens utilisent RUN pour accéder aux ressources du réseau. Si vous voulez la même image que moi, vous devez créer votre propre image 'À PARTIR' de la mienne. Aucun autre arrangement ne nous donnera les mêmes images. Aucun autre arrangement ne peut nous donner les mêmes images. Toute reproductibilité durable provient de Docker Hub, pas de Dockerfile.

Si la seule défense pour laquelle nous ne pouvons pas avoir de données éphémères est parce que Docker pense qu'ils peuvent supprimer toutes les données éphémères, alors vous devez déprécier l'instruction RUN.

@stephank J'ai implémenté un outil de création de docker au travail qui adopte une approche légèrement différente. Ma principale préoccupation n'était pas les secrets du temps de construction, mais cela s'occupe également de cela (garder les secrets hors de l'image construite, c'est-à-dire que la façon dont vous obtenez les secrets en premier lieu dépend toujours de vous).

Et c'est en exécutant un "build manager" avec le code du projet dans un VOLUME. Le gestionnaire exécute ensuite un nombre quelconque d'outils de génération dans des conteneurs distincts qui montent le code du projet à l'aide des volumes du gestionnaire. Ainsi, tous les artefacts générés et autres fichiers produits sont conservés dans le volume du gestionnaire et suivent le pipeline de génération pour chaque étape de génération. À la fin, le gestionnaire peut créer une image de production finale à l'aide du résultat de construction produit. Tous les secrets nécessaires en cours de route étaient disponibles dans le gestionnaire et/ou les conteneurs de construction, mais pas dans l'image finale. Aucune magie d'image Docker n'est utilisée et les caches de construction fonctionnent comme prévu.

L'apparence du pipeline de build dépend entièrement du projet à l'aide d'un fichier de spécifications configurant les exigences de build.

En fait, je suis plutôt emballé par cet outil, j'attends juste que nous puissions le sortir en open source (en attendant que les directives de la politique de l'entreprise soient adoptées)..

@kaos D'une part, je ne voulais pas m'écarter de l'outillage Docker de stock. D'un autre côté, je pense qu'il devrait vraiment y avoir plus de concurrence entre les outils de création d'images. Alors ça a l'air intéressant ! ??

@thaJeztah pour les

@alexkolson Je pense que la clé de ce fil est "

Peut-être que certains d'entre vous peuvent m'aider parce que je n'ai pas encore beaucoup d'expérience avec Docker.
J'ai utilisé un Hashicorps Vault pour récupérer mes secrets.

Ce que j'ai fait essentiellement, c'est de passer un jeton en tant qu'argument de construction et le jeton peut être utilisé pour récupérer des informations sensibles à partir de Vault. Cela se produit au moment de la construction et ne peut réussir que si le coffre-fort est à l'état « descellé » (ouvert pour la récupération de données). Après la construction, le jeton utilisé est révoqué.

Mais je pense que je suis toujours confronté à quelques problèmes communs.

  • Je dois créer de nouvelles images si des données sensibles changent
  • Si mon image a été volée / piratée, les données sensibles se trouvent dans l'image.

Il est possible de trouver le token utilisé avec docker inspect mais il ne peut plus être utilisé.
J'ai fait le choix de sceller et de desceller le coffre-fort de hashicorps uniquement au moment de la construction pour limiter autant que possible l'accès au magasin de secrets. Je n'ai pas non plus vu d'option permettant de conserver les secrets lors de la récupération des données au moment de l'exécution.

Alors, à quel point l'ai-je fait (c'est correct de dire si j'ai tout foiré ;) ) est-ce que quelqu'un a des trucs et astuces pour que les choses soient plus sûres ?

@weemen AFAIK stocker des secrets à votre image n'est pas non plus une bonne idée. Votre image ne doit avoir aucune information d'identification intégrée (y compris les jetons Vault). À la place, utilisez le backend d'authentification app-id de Vault pour vos conteneurs afin d'obtenir des secrets sur le temps de chargement. Stockez-les d'une manière ou d'une autre dans la mémoire du conteneur, en fonction de la pile d'applications que vous utilisez.

De plus, Vault travaille sur un backend d'authentification aws qui sera utile à l'avenir si vous utilisez AWS en tant que fournisseur de cloud.

@jaredm4 Pouvez-vous s'il vous plaît clarifier cette déclaration ? :

"Au lieu de cela, utilisez le backend d'authentification app-id de Vault pour vos conteneurs afin d'obtenir des secrets sur le temps de chargement. Stockez-les dans la mémoire du conteneur d'une manière ou d'une autre, en fonction de la pile d'applications que vous utilisez."

Je ne sais pas encore quand/où récupérer les secrets de Vault (ou Keywhiz, etc.). Est-ce que cela est fait avant l'exécution du docker et transmis à la commande run ? Cela se produit-il à un moment donné lors de l'initialisation du conteneur (si oui, des exemples) ? Mon application doit-elle les récupérer en cas de besoin ? Par exemple, mon application rails a besoin de clés API Google, dois-je écrire quelque chose à l'intérieur de rails pour appeler le coffre-fort lorsque les clés sont nécessaires ?

Je pense que je suis clair sur la nécessité d'utiliser quelque chose comme Vault, et clair sur la façon de le configurer, je ne sais tout simplement pas comment utiliser le service et mettre à jour mes fichiers yml et les préparer au démarrage de rails.

Toute orientation ici serait appréciée. Merci

Bien sûr @mcmatthew , bien que je doive

La façon dont j'ai essayé de le coder est que la seule information que vous transmettez au conteneur est nécessaire pour que votre code puisse s'authentifier avec Vault. Si vous utilisez le backend app-id, ce serait le app-id lui-même et l'adresse de votre coffre-fort.

Au démarrage du conteneur, votre application Rails remarquera qu'elle n'a pas encore de secrets et doit les récupérer à partir de Vault. Il a le app-id fourni et devra en quelque sorte le générer user-id . Cette génération d'ID utilisateur devra être déterminée par vous, mais leur documentation indique que "c'est généralement une valeur unique à une machine, telle qu'une adresse MAC ou un ID d'instance, ou une valeur hachée à partir de ces valeurs uniques".

Une fois que votre application Rails dispose de l'identifiant de l'application et de l'identifiant utilisateur, elle peut alors utiliser l'API de Vault pour /login. À partir de là, vous pouvez ensuite effectuer des appels d'API pour obtenir les secrets dont vous avez besoin.

Maintenant, pour clarifier ce que je voulais dire à propos de leur stockage en mémoire - cela varie en fonction du type d'application que vous utilisez, mais avec Rails, il devrait y avoir un moyen de stocker vos secrets dans un cache de variables utilisateur qui permettra à Rails d'accéder au des secrets de mémoire à chaque demande au lieu de les obtenir de Vault encore et encore (ce qui, comme vous pouvez l'imaginer, serait lent). Jetez un œil à ce guide sur la mise en cache dans Rails. À savoir, la section 2.0, mais en s'assurant qu'elle utilise memory_cache et non disk.

Enfin, assurez-vous que, quelle que soit la manière dont vous le codez, que vous le faites dans Rails et non avec un script de point d'entrée Docker spécial ou similaire. Rails doit détecter les secrets en mémoire et, s'ils n'existent pas, les récupérer.

J'espère que ça aide. Je sais, un peu haut niveau, mais c'est comme ça qu'on a prévu de l'aborder.

Ce qui n'est pas clair, c'est ce qui doit être gardé secret, l'identifiant de l'application, l'identifiant de l'utilisateur ou les deux.

Ok, la réponse est à la fois https://www.vaultproject.io/docs/auth/app-id.html
Mais il n'est toujours pas clair pourquoi il est plus sécurisé qu'un simple accès pare-feu.
Peut-être que chaque secret d'hôte doit être lié au secret d'application (politique) ?
C'est-à-dire que si vous avez un accès au secret de l'hôte, vous pourriez accéder à certaines applications si vous connaissez leurs noms secrets ?

Maintenant, nous devons stocker 2 jetons quelque part ?

@Vanuan Ils devraient tous les deux être gardés aussi secrets que possible, oui.

L'objectif principal de l'ID d'application est de restreindre l'accès à certains secrets dans Vault via des politiques. Toute personne ayant accès à l'ID d'application a accès aux secrets des stratégies de cet ID d'application. L'ID d'application doit être fourni par votre stratégie de déploiement. Par exemple, si vous utilisez Chef, vous pouvez le définir dans les sacs de paramètres (ou CustomJSON pour OpsWorks). Cependant, à lui seul, il ne permettra à personne d'accéder à Vault. Ainsi, une personne ayant eu accès à Chef ne pourrait pas accéder à Vault.

L'ID utilisateur n'est PAS fourni par Chef et doit être lié à des machines spécifiques. Si votre application est mise à l'échelle de manière redondante entre les instances, chaque instance doit avoir son propre identifiant utilisateur. L'origine de cet identifiant utilisateur n'a pas vraiment d'importance (bien qu'ils donnent des suggestions), mais il ne devrait pas provenir du même endroit que celui qui a déployé l'identifiant d'application (c'est-à-dire Chef). Comme ils l'ont dit, cela peut être scénarisé, simplement par d'autres moyens. Quel que soit le logiciel que vous utilisez pour mettre à l'échelle les instances, il peut fournir des identifiants d'utilisateur aux instances/conteneurs docker et autoriser l'identifiant d'utilisateur à l'identifiant d'application. Cela peut également être fait à la main si vous ne redimensionnez pas dynamiquement vos instances. Chaque fois qu'un humain ajoute une nouvelle instance, il crée un nouvel identifiant d'utilisateur, l'autorise à l'identifiant d'application et le fournit à l'instance par le moyen qui lui convient le mieux.

Est-ce mieux que les instances de pare-feu ? Je suppose que cela dépend. Le pare-feu ne restreint pas l'accès aux secrets dans Vault (pour autant que je sache), et si quelqu'un accédait à vos instances, il pourrait facilement entrer dans votre Vault.

De cette façon, il leur est difficile d'obtenir toutes les pièces du puzzle. Pour aller plus loin, app-id permet également les blocs CIDR que vous devez utiliser. Si quelqu'un obtient d'une manière ou d'une autre l'ID d'application et l'ID utilisateur, il ne peut toujours pas accéder à Vault sans être sur ce réseau.

(Encore une fois, c'est mon interprétation après avoir parcouru la documentation du mieux que j'ai pu)

@Vanuan @mcmatthew bonnes questions ! @jaredm4 merci vraiment pour cette clarification, cela m'aidera certainement. Ceci est très utile pour tous ceux qui recherchent une mise en œuvre plus pratique !! Si j'ai le temps dans les deux semaines à venir, j'essaierai à nouveau !

@thaJeztah :

Accessible par n'importe quel processus dans le conteneur, donc facilement "fuite"

Pouvez-vous soutenir cette affirmation? Les processus non privilégiés ne peuvent pas accéder aux variables d'environnement des processus non parents. Voir https://help.ubuntu.com/community/EnvironmentVariables#Process_locality.

Les variables d'environnement définies pour le conteneur (via --env ou --env-file ) _sont_ accessibles par n'importe quel processus dans le conteneur.

Bien sûr, puisqu'ils sont les enfants du processus de point d'entrée. C'est le travail de ce processus, ou de vous dans le cas où il s'agit par exemple d'un shell, de désactiver les variables d'environnement secrètes dès que possible.

Ce qui est plus pertinent est de savoir si les processus avec un ID utilisateur différent de 0 peuvent accéder à ces variables d'environnement à l'intérieur et/ou à l'extérieur du conteneur. Cela ne devrait pas être le cas non plus, lorsque le logiciel que vous utilisez à l'intérieur du conteneur supprime correctement les privilèges.

Je sais que c'est hors sujet, mais quelqu'un d'autre a-t-il remarqué que ce problème est actif depuis près d'un an maintenant ! Demain, c'est son anniversaire. ??

Serait-il possible pour un processus conteneur de lire les variables d'environnement dans la mémoire du processus, puis de les désactiver (dans l'environnement) ? Cela résout-il la plupart des problèmes de sécurité à l'exécution ?

@davibe le problème avec cela est que si le conteneur ou ses processus redémarrent, ces vars d'environnement ont alors disparu, sans aucun moyen de les récupérer.

J'ai essayé mais il semble que les vars env soient toujours là après le redémarrage.

dade<strong i="6">@choo</strong>:~/work/grocerest(master)$ cat test.js
console.log("FOO value: " + process.env.FOO);
delete(process.env.FOO);
console.log("FOO value after delete: " + process.env.FOO);

dade<strong i="7">@choo</strong>:~/work/grocerest(master)$ docker run --name test -it -e FOO=BAR -v $(pwd):/data/ node node /data/test.js
FOO value: BAR
FOO value after delete: undefined

dade<strong i="8">@choo</strong>:~/work/grocerest(master)$ docker restart test
test

dade<strong i="9">@choo</strong>:~/work/grocerest(master)$ docker logs test
FOO value: BAR
FOO value after delete: undefined
FOO value: BAR
FOO value after delete: undefined

peut-être que docker-run exécute mon truc en tant qu'enfant de bash ? Je pense que ça ne devrait pas..

@davibe :

unset 'SECRET_ENV_VAR'

Je pense que le principal problème/fonctionnalité dans tout cela est que vous vous connectez à Docker en tant que root , ainsi tout ce que vous mettez dans un conteneur peut être inspecté, que ce soit un jeton, un volume, une variable, une clé de cryptage. .. n'importe quoi.

Une idée serait donc de supprimer sudo et su de votre conteneur et d'ajouter une commande USER avant tout ENTRYPOINT ou CMD . Toute personne exécutant votre conteneur ne devrait désormais plus avoir la possibilité de s'exécuter en tant que root (si je ne me trompe pas) et vous pouvez donc maintenant lui cacher quelque chose.

Une autre idée (la meilleure à mon humble avis) serait d'ajouter la notion d'utilisateurs et de groupes au socket Docker et aux conteneurs, afin que vous puissiez dire que GROUP-A a accès aux conteneurs avec TAG-B, et USER-C appartient à GROUP- A donc il a accès à ces conteneurs. Il peut même s'agir d'une autorisation par opération (GROUP-A a accès à start/stop pour TAG-B, GROUP-B a accès à exec, GROUP-C a accès à rm/inspect, et ainsi de suite).

Après avoir recherché cela pendant quelques heures, je ne peux pas croire qu'il ne semble pas y avoir de solution ou de contournement officiellement recommandé pour les secrets de construction, et quelque chose comme https://github.com/dockito/vault semble être la seule option viable pour secrets de construction (à moins d'écraser toute l'image résultante ou de la construire manuellement en premier lieu). Malheureusement, https://github.com/dockito/vault est assez spécifique aux clés ssh, alors je vais essayer de l'adapter pour héberger également les fichiers de stockage d'informations d'identification git https...

Après ce qui semble être une éternité (à l'origine, j'ai entendu dire qu'il était prévu pour le quatrième trimestre 2015), AWS ECS semble enfin avoir tenu sa promesse d'apporter des rôles IAM aux applications Docker . Voici également l' article du

On dirait que cela, combiné à un peu de bonté KMS, est une solution viable à court terme. En théorie, il vous suffit de rendre les secrets liés à certains rôles principaux/IAM pour empêcher les rôles non autorisés de demander quelque chose qu'ils ne devraient pas et laisser un stockage sûr à KMS.

Je ne l'ai pas encore essayé, mais c'est sur ma courte liste...

Kubernetes semble également avoir une gestion des secrets qui me rappelle beaucoup de sacs de données chiffrés par Chef.

Je comprends que ce n'est pas la manière OSS indépendante de la plate-forme qui est tout l'intérêt de ce fil,
mais je voulais proposer ces deux options aux personnes jouant dans ces espaces d'infrastructure qui ont besoin de quelque chose _MAINTENANT_

Je viens de tomber sur quelque chose qui pourrait aider à cet égard : https://github.com/docker/docker/pull/13587

Cela semble être disponible à partir de docker v1.10.0, mais je ne l'avais pas remarqué jusqu'à présent. Je pense que la solution vers laquelle je me penche à ce stade consiste à utiliser https://www.vaultproject.io/ pour stocker et récupérer les secrets, en les stockant à l'intérieur du conteneur dans un système de fichiers tmpfs monté sur /secrets ou quelque chose de cette nature . Avec la nouvelle fonctionnalité ECS activant les rôles IAM sur les conteneurs, je pense que je devrais pouvoir utiliser l'authentification AWS EC2 du coffre-fort pour sécuriser l'autorisation des secrets eux-mêmes. (Pour les plates-formes indépendantes, je pourrais être enclin à utiliser leur authentification App ID.)

Dans tous les cas, la pièce manquante pour moi était l'endroit où mettre les secrets en toute sécurité une fois qu'ils ont été récupérés. L'option tmpfs me semble bonne. La seule chose qui manque est qu'ECS ne semble pas encore prendre en charge ce paramètre, c'est pourquoi j'ai soumis ceci aujourd'hui : https://github.com/aws/amazon-ecs-agent/issues/469

Tout cela semble être une solution assez complète à mon humble avis.

@CameronGo , merci pour le pointeur. Si je comprends bien, cela ne peut pas être utilisé lors de la construction correctement, ou est-ce possible ?

@NikolausDemmel désolé oui, vous avez raison. Il ne s'agit que d'une solution pour les secrets d'exécution, pas pour le temps de génération. Dans notre environnement, les secrets de génération ne sont utilisés que pour récupérer le code de Git. Jenkins gère cela pour nous et stocke les informations d'identification pour l'accès à Git. Je ne suis pas sûr que la même solution réponde aux besoins de tout le monde ici, mais je ne suis pas clair sur les autres cas d'utilisation des secrets de temps de construction.

Jenkins gère cela pour nous et stocke les informations d'identification pour l'accès à Git.

Comment ça marche avec docker ? Ou n'avez-vous pas git clone à l'intérieur du conteneur lui-même ?

Après avoir lu ce numéro dans son intégralité, je pense qu'il gagnerait énormément à être divisé en problèmes distincts pour les secrets "à la construction" et "à l'exécution", qui ont des exigences très différentes.

Si vous êtes comme moi et que vous venez ici en essayant de décider quoi faire maintenant, alors FWIW je décrirai la solution sur laquelle j'ai opté, jusqu'à ce que quelque chose de mieux se présente.

Pour les secrets d'exécution, j'ai décidé d'utiliser http://kubernetes.io/docs/user-guide/secrets/. Cela ne fonctionne que si vous utilisez kubernetes. Sinon le coffre a l'air ok. Tout ce qui est secret dans l'image générée ou dans le calque temporaire est une mauvaise idée.

En ce qui concerne les secrets de construction - je ne peux pas penser à d'autres cas d'utilisation de secrets de construction autres que la distribution de code privé. À ce stade, je ne vois pas de meilleure solution que de compter sur l'exécution de quelque chose de "secret" du côté de l'hôte et d'AJOUTER le package/jar/wheel/repo/etc généré. à l'image. Enregistrer une LOC générant le package côté hôte ne vaut pas la peine de risquer d'exposer les clés ssh ou la complexité de l'exécution du serveur proxy, comme suggéré dans certains commentaires.

Peut-être que l'ajout d'un indicateur "-v" à la construction de docker, similaire à l'indicateur d'exécution de docker, pourrait bien fonctionner? Il partagerait temporairement un répertoire entre l'hôte et l'image, mais garantirait également qu'il apparaîtrait vide dans le cache ou dans l'image générée.

Je travaille actuellement sur une solution utilisant Vault :

  1. Vault est installé sur la machine Builder et un jeton est enregistré localement
  2. Lorsque la construction démarre, la machine de construction demande un nouveau jeton temporaire valable uniquement pendant quelques minutes (en fonction de la construction, 1h serait même acceptable)
  3. Injecte le jeton en tant que build arg
  4. L'image Docker a également installé Vault (ou l'installe et le supprime pendant la construction) et en utilisant ce jeton, il peut récupérer les vrais secrets

Il est important que les secrets soient supprimés dans la même commande, donc lorsque docker met en cache la couche donnée, il n'y a pas de restes. (Ceci ne s'applique bien sûr qu'à la construction de secrets temporels)

Je ne l'ai pas encore construit, mais j'y travaille.

Un peu lié au commentaire de

Peut-être pas un secret de temps de construction en particulier, mais j'ai besoin d'un cas d'utilisation (sécuriser) un mot de passe pendant le temps de construction dans un Dockerfile afin de permettre le téléchargement d'un artefact déjà construit via une commande RUN curl. Le téléchargement au moment de la construction nécessite des informations d'identification de l'utilisateur pour s'authentifier afin de récupérer l'artefact - nous passons donc le mot de passe en tant que variable d'environnement dans le Dockerfile pour le moment (nous sommes toujours en développement). Les builds se déroulent automatiquement dans les coulisses, car nous utilisons OpenShift, et les variables d'environnement dans le Dockerfile sont sorties dans les journaux pendant la build, comme n'importe quelle commande de build docker. Cela rend le mot de passe visible pour toute personne ayant accès aux journaux, y compris nos développeurs. J'ai désespérément essayé de trouver un moyen d'envoyer le mot de passe afin qu'il puisse être utilisé lors de la construction du docker, mais je n'ai ensuite pas le mot de passe sorti dans les journaux ou je finis par se trouver dans une couche.

Je souscris également à ce que @wpalmer a dit à propos de la

Je pense qu'il pourrait être utile de définir des tests pour tout mécanisme secret (d'exécution) proposé par quiconque. Parce qu'il y a beaucoup de gens sur ce fil qui plaident pour une sécurité très faible.

Pour commencer je propose :

  • Le secret n'apparaît pas dans docker inspect
  • Une fois le processus 1 démarré, le secret n'est disponible dans aucun fichier accessible à partir du conteneur (y compris les fichiers montés sur volume)
  • Le secret n'est pas disponible dans /proc/1/cmdline
  • Le secret est transmis au conteneur sous une forme cryptée

Toute solution suggérée ci-dessus qui enfreint l'une d'entre elles est problématique.

Si nous pouvons nous mettre d'accord sur une définition du comportement qu'un secret doit suivre, alors au moins cela éliminera des solutions sans fin qui ne sont pas adaptées à l'objectif.

@gtmtech excellentes suggestions :)

Une fois le processus 1 démarré, le secret n'est disponible dans aucun fichier accessible à partir du conteneur (y compris les fichiers montés sur volume)

Je ne suis pas sûr d'être d'accord avec ça. Bien que je convienne qu'il ne devrait être accessible qu'à partir du conteneur (en mémoire idéalement), il existe plusieurs cas où une application a besoin de temps pour "démarrer" et ne pas supprimer les fichiers en dessous. Je pense que quelque chose en mémoire pendant la durée de l'exécution du conteneur (supprimé à l'arrêt) est une meilleure approche.

J'ajouterais à la liste des exigences d'exécution :

  • Authentification/autorisation du conteneur lors de l'amorçage du premier secret.

Par exemple, Vault fournit une autorisation avec le backend AppRole, mais est ouvert quant à la façon dont les conteneurs s'identifient.

Nick Sullivan a présenté il y a quelques semaines le projet PAL de Clouflare, promettant de l'ouvrir prochainement, ce qui devrait fournir une réponse potentielle à la question d'authentification à l'aide du notaire docker.

Du point de vue d'une application, il existe trois manières de gérer cela :

  1. Obtenez un secret à partir d'une variable d'environnement.
  2. Obtenez un secret à partir d'un fichier.
  3. Obtenez un secret d'un autre système.

1 et #2 ci-dessus sont généralement les plus courants car la majorité des applications prennent en charge ce mécanisme. #3 est probablement plus idéal car il laisse le moins de "miettes", mais l'application doit être développée spécifiquement pour cela et doit souvent encore avoir une information d'identification pour obtenir le secret.

Docker est synonyme de polyvalence et de prise en charge d'une grande variété de cas d'utilisation. Sur cette base, 1. et 2. sont les plus attrayants du point de vue d'une application, malgré le fait qu'ils laissent tous les deux des « miettes » sur le système.

Une approche courante que j'utilise certainement consiste à injecter des secrets via un script de point d'entrée (par exemple, utiliser un outil comme credstash ou plain KMS dans AWS et combiner avec des rôles IAM). À cet égard, vous faites en fait #3 ci-dessus dans le script du point d'entrée, et faites #1 (définir une variable d'environnement) ou #2 (écrire dans un fichier). Cette approche est dynamique et pour #1 (variables d'environnement), n'expose pas les informations d'identification dans les journaux docker ou docker inspect.

La bonne chose à propos de l'approche du point d'entrée est que vous séparez les préoccupations de la gestion des secrets de l'application.

C'est un domaine où Docker pourrait ajouter des fonctionnalités pour éviter d'avoir à utiliser vos propres scripts de point d'entrée. Docker adore les plugins et pourrait fournir un point d'ancrage dans le cycle de vie du conteneur où il pourrait prendre en charge les plugins de fournisseur "secrets", qui remplissent essentiellement la fonction d'un script de point d'entrée manuel et injectent des secrets dans le conteneur (via une variable d'environnement interne ou un fichier). Ainsi, vous pourriez avoir un fournisseur de secrets Hashicorp Vault, un fournisseur de secrets AWS KMS, etc. Docker pourrait peut-être avoir son propre fournisseur basé sur le cryptage RSA (via des certificats numériques). L'ensemble de ce concept est vaguement similaire au concept de secrets Kubernetes, qui présente des secrets sur le système de fichiers du conteneur.

Bien sûr, il y a la complexité de la façon dont vous autorisez l'accès au fournisseur de secrets, ce qui est un problème auquel vous êtes confronté aujourd'hui malgré tout. Avec Hashicorp, vous pouvez émettre et transmettre un jeton unique/limité dans le temps pour l'authentification, avec AWS, ce sont des rôles IAM, avec l'approche de chiffrement Docker RSA que j'ai mentionnée, il peut simplement transmettre des secrets chiffrés à l'aide du certificat public Docker Engine.

Ce fil est super. J'espère que nous verrons plus de fils de discussion comme celui-ci où des personnes de la communauté et de tous les horizons professionnels pourront partager leurs expériences, leurs réflexions et leurs solutions.

La question du "secret zéro" est délicate. Temps de construction ou temps d'exécution ? Les deux ont leurs avantages et leurs inconvénients, ainsi que des mesures de sécurité et des défauts évidents (ainsi que des piratages et des solutions de contournement !).

Cela dit, j'ai beaucoup réfléchi à la manière dont la gestion d'un pass/clé se résume à l'application et/ou au service.

Une chose sur laquelle nous allons travailler dans les mois à venir est de créer un service de sauvegarde de configuration global partagé via des paires clé/valeur, distribué par Consul et mis à disposition en tant que variable d'environnement (ou injecté si l'utilisation de variables d'environnement n'est pas prise en charge). Cela ne prend en charge que vos valeurs non sécurisées. Pour plus de sécurité, nous allons passer à Vault et le traiter comme un service de support - un peu comme une base de données ou toute autre dépendance.

Le code, la configuration et les secrets seront fournis via un ou plusieurs services de support. Dans ce cas, nous utilisons Stash, Consul et Vault. Tant que la dépendance est en place, la possibilité d'extraire la configuration et les secrets selon les besoins l'est également.

Je n'ai vu cela nulle part comme une solution solide, c'est pourquoi je poste à ce sujet ici. Mais pour revenir au but de ce fil, c'est une approche que nous allons expérimenter pour contourner le problème Docker/secret. Nous allons créer des applications qui prennent en charge cela de manière native, plutôt que de nous appuyer sur les frameworks et les plates-formes qui les entourent dans lesquelles elles s'exécutent.

En ce qui concerne les secrets au moment de la construction, la directive MOUNT Rocker s'est avérée utile pour créer des répertoires et des fichiers transitoires qui n'existent _que_ au moment de la construction. Certaines de leurs fonctionnalités de modélisation peuvent également aider dans cette situation, mais je ne les ai pas encore utilisées à fond.

J'aimerais voir cette fonctionnalité implémentée en tant que plugin Builder dans le noyau Docker (ainsi que certaines des autres fonctionnalités utiles de Rockerfiles) !

Je vois que les 4 propositions actuellement en OP concernent le stockage secret 🙁

Je dirais que les dockers devraient faciliter la transmission d'un secret/mot de passe à une _instance de docker_ mais que le stockage/la gestion de ces secrets est (et devrait être) hors de la portée de docker.

Lors de la transmission d'un secret, je dirais qu'un paramètre d'exécution est presque parfait, sauf qu'il est généralement enregistré. Je réduirais donc cela à une fonctionnalité de paramètre non en clair . Une approche serait d'utiliser le cryptage avec des clés générées par instance de docker.

Quant à _comment gérer les secrets_, je dirais tout ce que l'utilisateur veut, d'un script homebrew bash à l'intégration par un logiciel comme Kubernetes .

Qu'y a-t-il de mal à simplement implémenter MOUNT comme des supports à bascule, comme @agilgur5 l'a fait remarquer plus tôt ? Je ne peux pas croire que ce débat ait duré si longtemps qu'une équipe ait dû recopier efficacement la commande docker build afin de satisfaire ce cas d'utilisation vraiment simple. Avons-nous besoin d'un autre serveur HTTP dans le mix ? EMBRASSER.

J'ai passé tellement d'heures autour de ce sujet...

Pour l'instant, le meilleur moyen que j'ai trouvé pour gérer les secrets pendant la phase de construction consiste à créer en deux étapes, donc deux fichiers docker. Voici un bon exemple .

[Habitus] (http://www.habitus.io/) semble être une autre option, mais dans mon cas, je ne veux pas ajouter d'autres outils principalement parce que je voudrais que le processus de construction sur le serveur CI ET sur l'ordinateur de l'utilisateur reste simple/même.

Et qu'en est-il de la manière docker-in-docker (dind) ?

Voici un exemple de construction en deux étapes avec dind comme je viens de parler ci-dessus : https://github.com/BenoitNorrin/docker-build-with-secrets

N'hésitez pas à commenter...

Intéressant. Un peu me rappelle comment OpenShift construit.

Il me semble que vous passez le mot de passe sur la ligne de commande. Y a-t-il un moyen de contourner cela?

Notez qu'il existe un PR de travail en cours pour les secrets de construction ici ; https://github.com/docker/docker/pull/28079 (les secrets d'exécution pour les services seront dans docker 1.13, voir https://github.com/docker/docker/pull/27794)

@thaJeztah :
Concernant le #28079, je suis un peu pessimiste quand j'ai vu tant de relations publiques autour de ce sujet échouer au cours des deux dernières années...
Je ne veux pas avoir swarm comme dépendance. Une partie de mes clients utilise un autre orchestrateur de cluster.

@cassiussa :
Je ne comprends pas ce que tu veux dire ?
1/ Les mots de passe ont été passés au "container builder" qui n'est pas l'image finale. Ce constructeur fait une construction docker et produit une image basée sur le Dockerfile.realease. Il n'y a aucun secret stocké dans l'histoire de cette image finale.
2/ N'hésitez pas à utiliser docker-compose ( exemple ) si vous ne souhaitez pas passer le mot de passe à la ligne de commande

@BenoitNorrin Je pense que cela pourrait être étendu à un non-essaim à l'avenir, mais @diogomonica peut en savoir plus à ce sujet

Ça y ressemble :

Ceci est actuellement pour le mode Swarm uniquement car le magasin de sauvegarde est Swarm et en tant que tel est uniquement pour Linux. C'est la base de la future prise en charge des secrets dans Docker avec des améliorations potentielles telles que la prise en charge de Windows, différents magasins de sauvegarde, etc.

Ce serait génial s'il était implémenté de la même manière que le rocker, peut être
simple, n'a pas besoin d'être « entreprise ».

Le mar. 29 novembre 2016, 15:53 ​​Michael Warkentin, [email protected]
a écrit:

Ça y ressemble :

Ceci est actuellement pour le mode Swarm uniquement car le magasin de sauvegarde est Swarm et comme
tel est seulement pour Linux. C'est la base d'un futur soutien secret dans
Docker avec des améliorations potentielles telles que la prise en charge de Windows, différents
magasins de soutien, etc.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-263608915 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAZk5vlLwsBHHTTbUS_vvx-qTuwnkp6Oks5rDEpjgaJpZM4Eq021
.

Une solution serait de crypter certaines parties des informations transmises à partir d'un fichier docker-compose .

Par exemple, exécutez docker inspect et les informations chiffrées doivent être affichées/marquées comme _encrypted_. Ensuite, docker inspect --encryption-key some_key_file afficherait toutes les informations cryptées, non cryptées.

D'autre part, à l'intérieur des conteneurs, les applications devraient pouvoir implémenter différents mécanismes pour accéder et décrypter ces informations cryptées pour leur utilisation.

Je pense que le cryptage _est la clé_ :)

Le but est pour mon cas d'utilisation (vraiment, vraiment, vraiment commun) de créer un
projet logiciel d'un serveur git qui nécessite une authentification, à la fois pour
le projet et ses dépendances. Rocker l'a cloué en permettant de monter
un fichier ou un répertoire lors de la construction (dans ce cas un socket d'agent SSH)

Le mardi 3 janvier 2017, 04:14 Hisa, [email protected] a écrit :

Une solution serait de crypter certaines parties des informations transmises
à partir d'un fichier docker-compose.

Par exemple, exécutez docker inspect et les informations chiffrées doivent être
affiché/marqué comme crypté . Ensuite, docker inspecte --encryption-key
some_key_file afficherait toutes les informations cryptées, non cryptées.

D'autre part, à l'intérieur des conteneurs, les applications devraient pouvoir implémenter
mécanisme différent pour accéder et décrypter ces informations cryptées pour leur utilisation.

Je pense que le cryptage est la clé :)

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-270049742 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAZk5qEphZo5SR9vOWVL5dck50EPadpVks5rOcsUgaJpZM4Eq021
.

Comme je ne l'ai pas vu mentionné, voici un autre bon article sur la gestion des secrets dans AWS ECS : https://aws.amazon.com/blogs/security/how-to-manage-secrets-for-amazon-ec2-container- applications-basées-sur-service-en-utilisant-amazon-s3-and-docker/

Il y a une nouvelle commande "docker secret" dans Docker 1.13. Ce problème devrait pouvoir être résolu lorsque la documentation de cette fonctionnalité est adaptée aux cas d'utilisation mentionnés ici.

La commande docker secret semble ne s'appliquer actuellement qu'à Docker Swarm (c'est-à-dire aux services docker) et n'est donc actuellement pas viable pour les conteneurs Docker génériques.

De plus, docker secret ne gère que les secrets d'exécution, pas les secrets de construction.

Wow. C'est comme si personne dans l'équipe de gestion des produits n'avait jamais envisagé
le cas d'utilisation où tout sauf un logiciel open source non authentifié obtient
construit dans un conteneur docker ou dans n'importe quelle langue autre que le golang, où tous
les dépendances sont copiées et collées, désolé, « versionnées » dans le référentiel Git.

Je ne peux tout simplement pas comprendre comment les gens seraient si incroyablement obtus. Seul
l'explication à laquelle je peux penser est que l'équipe de gestion de produit n'est pas
praticiens et n'ont jamais utilisé le produit. je vois souvent ça
caractéristique se manifeste lorsque l'organisation embauche sur la base
jira/compétences agiles.

Je continuerai à utiliser le rocker jusqu'en 2019 ou chaque fois que quelqu'un verra du sens alors.

Le dimanche 22 janvier 2017, 23:47 Shane StClair, [email protected] a écrit :

De plus, les secrets de docker ne gèrent que les secrets d'exécution, pas les secrets de construction.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

Je retire ce dernier commentaire, désolé, je m'évade. Juste frustré que
les cas marginaux simples semblent souvent être une opportunité d'imposer quelque chose
comme consul ou créer quelque chose de vraiment sur-conçu plutôt que juste
implémenter quelque chose d'aussi simple que le montage au moment de la construction.

Le lundi 23 janvier 2017, 09:31 Bryan Hunt, [email protected] a écrit :

Wow. C'est comme si personne dans l'équipe de gestion des produits n'avait jamais envisagé
le cas d'utilisation où tout sauf un logiciel open source non authentifié obtient
construit dans un conteneur docker ou dans n'importe quelle langue autre que le golang, où tous
les dépendances sont copiées et collées, désolé, « versionnées » dans le référentiel Git.

Je ne peux tout simplement pas comprendre comment les gens seraient si incroyablement obtus. Seul
l'explication à laquelle je peux penser est que l'équipe de gestion de produit n'est pas
praticiens et n'ont jamais utilisé le produit. je vois souvent ça
caractéristique se manifeste lorsque l'organisation embauche sur la base
jira/compétences agiles.

Je continuerai à utiliser le rocker jusqu'en 2019 ou chaque fois que quelqu'un verra du sens
alors.

Le dimanche 22 janvier 2017, 23:47 Shane StClair, [email protected]
a écrit:

De plus, les secrets de docker ne gèrent que les secrets d'exécution, pas les secrets de construction.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

@binarytemple Tout le monde veut toutes les fonctionnalités en ce moment. Si les choses ne sont pas prêtes, elles ne sont tout simplement pas prêtes. Limiter la portée d'une nouvelle fonctionnalité n'est certainement pas une mauvaise chose, car même avec une portée limitée, il y a toujours place à l'amélioration.

Si quelqu'un est vraiment enthousiaste à l'idée d'intégrer une fonctionnalité, il devrait alors parler à un ou plusieurs responsables de la façon dont il peut contribuer au travail pour cela.

J'ai pensé la même chose que @mixja en ce secret n'aide que les utilisateurs de l'essaim n'est pas une solution plus générale (comme ils l'ont fait pour attacher des volumes persistants). La façon dont vous gérez vos secrets (ce qu'ils sont et qui y a accès) dépend beaucoup du système et dépend des éléments payants et/ou OSS que vous bricolez pour créer votre "plate-forme". Avec Docker, la société se déplaçant vers la fourniture d'une plate-forme, je ne suis pas surpris que leur première implémentation soit basée sur un essaim, tout comme Hashicorp intègre Vault dans Atlas - c'est logique.

Vraiment, la façon dont les secrets sont transmis tombe en dehors de l'espace de docker run . AWS fait ce genre de chose avec des rôles et des stratégies pour accorder/refuser des autorisations ainsi qu'un SDK. Chef le fait en utilisant des sacs de données cryptés et un « amorçage » cryptographique pour auth. K8S a sa propre version de ce qui vient de sortir en 1.13. Je suis sûr que mesos ajoutera une implémentation similaire dans le temps.

Ces implémentations semblent tomber dans 2 camps.
1) transmettre le secret via le support de volume fourni par la "plate-forme" ou (chef/docker secret/k8s
2) transmettre les informations d'identification pour parler à un service externe pour obtenir les choses au démarrage (iam/credstash/etc)

Je pense que j'espérais voir quelque chose de plus dans le sens de la deuxième option. Dans la première option, je ne pense pas qu'il y ait suffisamment de séparation des préoccupations (la chose qui fait le lancement a également accès à toutes les clés), mais c'est une préférence, et comme tout le reste dans la construction du système, tout le monde aime le faire différemment .

Je suis encouragé par le fait que cette première étape a été franchie par docker et j'espère qu'un mécanisme plus général pour docker run sortira (pour soutenir le camp #2) -- ce qui signifie malheureusement que je ne pense pas que ce fil soit la mission initiale a été remplie et ne devrait pas encore être fermée.

Comme!
design vraiment simple mais très efficace

@bacoboy , @mixja - un essaim à nœud unique et un service de conteneur unique n'est pas si mal
docker swarm init , le service docker crée une réplique = 1

pour moi, il est logique que docker swarm soit désormais la valeur par défaut pour l'exécution des conteneurs/services.

Ai-je raison de penser que cette nouvelle proposition basée sur un essaim n'a d' impact

Les secrets de

Pour injecter des secrets au moment de la construction, nous pouvons maintenant utiliser docker build --squash pour effectuer les opérations suivantes en toute sécurité :

COPY ssh_private_key_rsa /root/.ssh/id_rsa
RUN git pull ...
RUN rm -rf /root/.ssh/id_rsa

Le drapeau --squash produira une seule couche pour l'ensemble du Dockerfile : il n'y aura aucune trace du secret.

--squash est disponible dans docker-1.13 en tant que drapeau expérimental.

@hmalphettes Cela signifie que vous manquez les avantages des couches inférieures partagées entre les versions.

Ce n'est certainement pas l'intention de la courge. Je serais toujours très prudent avant d'ajouter des secrets comme celui-ci.

@zoidbergwill les couches inférieures sont toujours partagées.

Je suis d'accord à 100% avec @cpuguy83. S'appuyer sur un indicateur de temps de construction pour garder les secrets serait assez risqué. Il y avait une proposition PR pour le temps de construction (https://github.com/docker/docker/pull/30637) Je vais travailler sur un rebase pour obtenir plus de retours.

@wpalmer Si vous avez des constructions d'images automatisées, vos outils doivent savoir comment obtenir des secrets de construction.

Par exemple, vous souhaiterez peut-être conserver vos secrets de construction dans un coffre-fort chiffré Ansible intégré dans une image et accorder aux conteneurs exécutés à partir de cette image l'accès au secret d'exécution qui conserve votre mot de passe de coffre-fort.

WDYT ?

Pourquoi confondons-nous toujours les secrets de construction avec les secrets d'exécution ? Il existe déjà de nombreux bons moyens pour docker (ou des outils connexes comme kubernetes) de fournir les secrets d'exécution. La seule chose qui manque vraiment, ce sont les secrets de construction. Ces secrets ne sont pas utilisés lors de l'exécution, ils sont utilisés lors de l'installation, il peut s'agir de référentiels internes par exemple. Le seul moyen de travail que j'ai vu dans ce sujet et dans les sujets connexes (mais également déconseillé), consiste à exposer un serveur http au conteneur pendant le temps de construction. L'approche du serveur http rend les choses assez compliquées pour accéder à ces secrets.

+1 secret de temps de construction != secret de temps d'exécution

Comme le souligne Paul. Il n'est pas souhaitable de faire cuire le référentiel interne
informations d'identification dans l'image.

Pourquoi est-ce si difficile à comprendre ?

Le jeu. 16 février 2017, 14:42 Paul van der Linden, [email protected]
a écrit:

Pourquoi confondons-nous toujours les secrets de construction avec les secrets d'exécution ? Là
existe déjà de nombreux bons moyens pour docker (ou des outils connexes comme kubernetes) de
fournir les secrets d'exécution. La seule chose qui manque vraiment est le temps de construction
secrets. Ces secrets ne sont pas utilisés pendant l'exécution, ils sont utilisés pendant
temps d'installation, il peut s'agir de référentiels internes par exemple. Le seul
méthode de travail que j'ai vue dans ce domaine et dans des sujets connexes (mais aussi conseillé
contre lui), expose un serveur http au conteneur pendant le temps de construction.
L'approche du serveur http rend les choses assez compliquées pour y accéder
ces secrets.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/13490#issuecomment-280348116 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAZk5h0Z2OGwApVnLNEFWKRdOfGxLOmRks5rdGBagaJpZM4Eq021
.

@pvanderlinden Vous pouvez également le faire avec une construction en deux étapes.
Voici un exemple : https://github.com/BenoitNorrin/docker-build-with-secrets

@timka comme mentionné, il n'est pas souhaitable d'intégrer les informations d'identification dans l'image car cela pose un risque de sécurité. Voici une proposition de secrets de temps de construction : https://github.com/docker/docker/pull/30637

@BenoitNorrin Je ne sais pas comment cela se produirait dans mon cas d'utilisation (et d'autres).
Les packages qui doivent être installés sont déjà construits lorsque je démarre le processus de construction de docker. Mais la version docker devra installer ces packages, elle aura besoin d'accéder à un référentiel anaconda interne et/ou à un serveur pypi (python). Les emplacements et les mots de passe sont bien sûr privés.
On dirait que # 30637 est une autre tentative, j'espère que cela finira dans Docker !

@timka la première moitié de votre message semble mentionner les secrets de construction, mais la seconde moitié parle explicitement de secrets d'exécution. Les secrets d'exécution sont simples. Ma "solution" actuelle pour les secrets de construction consiste à pré-exécuter, en tant qu'étape complètement séparée, un conteneur qui récupère des données privées à l'aide d'un secret d'exécution. Une autre étape fusionne ensuite cela dans l'arborescence, avant d'exécuter une commande docker build régulière.

L'alternative, si les secrets de construction étaient une fonctionnalité standard, serait d'exécuter ces étapes dans le Dockerfile.

Mon outillage sait comment exécuter ces étapes automatiquement, mais j'avais besoin de le faire moi-même, ce qui est quelque peu absurde pour un désir aussi commun.

Pour info, j'ai écrit https://github.com/abourget/secrets-bridge pour résoudre le problème des secrets de construction.

Il crée une configuration jetable que vous pouvez passer en tant qu'arguments, pendant le processus de construction, il se connectera à l'hôte et récupérera les secrets, les utilisera, puis vous pourrez tuer le pont hôte. Même si les build-args sont enregistrés quelque part, ils deviennent inutiles au moment où le serveur est tué.

Le serveur prend en charge le transfert d'agent SSH, tunnellisé via une communication Websocket TLS. Cela fonctionne aussi sous Windows !

Alexandre, ce que tu as fait est extrêmement créatif et habile. C'est juste
me rend triste qu'il soit nécessaire de franchir toutes ces étapes juste pour
obtenir le même résultat que si 'docker build' prenait en charge le 'mount'
commande plutôt que l'insistance aveugle pour que tout soit copié dans le
récipient.

Je suis mon cas, je vais abandonner 'docker build' et utiliser à la place rocker ou
quelque chose si ma propre création.

Le jeu. 13 juil. 2017, 16:23 Alexandre Bourget, [email protected]
a écrit:

Pour info, j'ai écrit https://github.com/abourget/secrets-bridge pour répondre au
problème des secrets au moment de la construction.

Il crée une configuration jetable que vous pouvez passer en arguments,
pendant le processus de construction, il se connectera à l'hôte et récupèrera le
secrets, utilisez-les, puis vous pouvez tuer le pont hôte. Même si le
les build-args sont sauvegardés quelque part, ils deviennent inutiles au moment où le serveur
est tué.

Le serveur prend en charge le transfert d'agent SSH, via un tunnel TLS
communication par socket Web. Cela fonctionne aussi sous Windows !

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/13490#issuecomment-315111388 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAZk5hZqTAgPBjS9cFP_IsYNa9wv-yoAks5sNjaBgaJpZM4Eq021
.

Voici la dernière proposition de secrets : https://github.com/moby/moby/issues/33343

Je pense que la nouvelle fonctionnalité de "construction en plusieurs étapes" incluse dans la dernière version de Docker CE résout une grande partie de nos problèmes.

https://docs.docker.com/engine/userguide/eng-image/multistage-build/

Les conteneurs générés pour exécuter les commandes de Dockerfile sont livrés avec des /dev cuits et aucune modification apportée ne doit être enregistrée dans une couche. Docker peut-il fournir des secrets d'utilisateur via ce point de montage ? De la même manière, il fournit /dev/init ?

Ceci est toujours assez important car les builds à plusieurs étapes avec des arguments ne fuient pas dans l'image mais exposent toujours vos secrets dans le cadre des listes de processus sur le système en cours d'exécution, donc ce n'est pas vraiment résolu.

Nous sommes en août 2017. Pendant ce temps, les "anciennes propositions de gestion des secrets" dans le numéro d'origine renvoient aux numéros de 2014.

Il n'y a toujours pas de bonnes solutions pour les secrets de construction. Le PR qui offrait le drapeau --build-time-secret a été fermé sans explication. Rien de présenté dans « Alors, qu'est-ce qu'il faut ? » section est mise en œuvre.

pendant ce temps

Le PDG nouvellement installé, Steve Singh, se concentre sur les clients commerciaux
Dernière ronde de 75 millions de dollars pour aider à former l'équipe de vente et de marketing


UPD. : comme @cpuguy83 l'a correctement et à juste titre souligné ci-dessous, le résumé complet des propositions se trouve au #33343

Je sais que ce n'est pas intégré, mais secrets-bridge fonctionne plutôt bien pour le moment.

@dmitriid Je comprends votre frustration quant à l'absence de cette fonctionnalité. Cependant, ce n'est pas ainsi qu'on s'adresse à une communauté open source (ou à n'importe quelle communauté).

J'ai posté un lien vers une proposition ci-dessus et j'ai vu exactement 0 commentaires à part le mien.

Voici la dernière proposition de secrets : #33343

@cpuguy83 Génial ! J'ai un peu sauté le dernier tiers de cette discussion (et quelques autres) car il y a beaucoup de choses à lire (tout en cherchant une solution), donc j'ai vraiment raté votre commentaire, désolé :(

Ce fil a commencé en 2015.

C'est 2017.

Pourquoi n'y a-t-il pas encore de solution pour les secrets de construction qui ne soit pas bidon et terrible ? C'est très évidemment un gros problème pour beaucoup de gens, mais il n'y a toujours pas vraiment de bonne solution !

@mshappe

Pourquoi n'y a-t-il pas encore de solution pour les secrets de construction qui ne soit pas bidon et terrible ?

Parce que c'est un problème difficile à résoudre correctement et c'est quelque chose qui sera utilisé par des millions de personnes.

S'il vous plaît voir mon commentaire juste au-dessus du vôtre:

J'ai posté un lien vers une proposition ci-dessus et j'ai vu exactement 0 commentaires à part le mien.
Voici la dernière proposition de secrets : #33343

Si vous voulez voir quelque chose implémenté, vous devrez faire plus que vous plaindre que quelque chose n'est pas implémenté. S'il vous plaît commenter la proposition!

C'est si facile à résoudre. Il faut juste quelque chose, tout ce qui n'est pas
cuit dans les images. Et en fait, c'est très facile à résoudre, arrêtez d'utiliser
'docker build' et utilisez l'API python, rocker ou autre.

Le mercredi 23 août 2017 à 21h42, Brian Goff [email protected]
a écrit:

@mshappe https://github.com/mshappe

Pourquoi n'y a-t-il pas de solution pour les secrets de construction qui ne soit pas hackish et
terrible, pourtant ?

Parce que c'est un problème difficile à résoudre correctement et c'est quelque chose qui
sera utilisé par des millions de personnes.

S'il vous plaît voir mon commentaire juste au-dessus du vôtre:

J'ai posté un lien vers une proposition ci-dessus et j'ai vu exactement 0 commentaires sur
elle sauf la mienne.
Voici la dernière proposition de secrets : #33343
https://github.com/moby/moby/issues/33343

Si vous voulez voir quelque chose mis en œuvre, vous devrez faire plus que
se plaindre que quelque chose n'est pas mis en œuvre. S'il vous plaît commenter la proposition!

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/13490#issuecomment-324441280 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAZk5oEpcipmfCji1mXz6MOVt0p6-OA6ks5sbIC0gaJpZM4Eq021
.

@binarytemple J'ai commencé à considérer Rocker comme une alternative, en fait... mais seulement à cause de cet étrange blocage mental que Docker semble avoir sur les secrets de la construction.

C'est étrange. Je parle aux gens et ils font toutes sortes de hacks stupides
comme utiliser un service HTTP - tout jeter (surveillance/granularité
permissions/simplicité) fourni par le combo POSIX/SELinux. je ne fais tout simplement pas
comprendre. Le refus me semble illogique.

Le mer. 23 août 2017, 23:03 Michael Scott Shappe [email protected]
a écrit:

@binarytemple https://github.com/binarytemple J'ai commencé à regarder
Rocker comme alternative, en fait...mais seulement à cause de cet étrange
mental block docker semble avoir des secrets sur le temps de construction.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/13490#issuecomment-324461257 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAZk5ppZYsOhdfvgotCUk5l41Truo_EEks5sbJOLgaJpZM4Eq021
.

Les builds docker en plusieurs étapes résolvent beaucoup de ces problèmes.

Dans sa forme la plus simple, vous pouvez injecter des secrets en tant qu'arguments de construction, et ils ne feront qu'une partie de l'historique des images qui indiquent explicitement qu'elles ont besoin de l'argument. Comme le souligne neclimdul , les secrets seront disponibles dans la liste des processus lors de la construction. L'OMI n'est pas un gros problème, mais nous avons adopté une autre approche.

Notre serveur de build s'exécute avec certains secrets montés en tant que volumes, donc notre copie CI dans f.ex. /mnt/secrets/.npmrc dans le répertoire de travail courant. Ensuite, nous utilisons un Dockerfile similaire à celui ci-dessous.

FROM node:latest
WORKDIR /usr/src/app
COPY .npmrc .
RUN echo '{ "dependencies": [ "lodash" ] }' > package.json
RUN npm install
RUN ls -lah

FROM alpine:latest
WORKDIR /usr/src/app
COPY --from=0 /usr/src/app/node_modules ./node_modules
RUN ls -lah
CMD ["ls", "./node_modules"]

L'image résultante aura les dépendances installées, mais pas le .npmrc ni aucune trace de son contenu.

L'utilisation de builds à plusieurs étapes vous donne un contrôle total sur la façon d'exposer les secrets de temps de build au processus de build. Vous pouvez obtenir des secrets à partir de magasins externes comme Vault, via des volumes (que nous montons à partir du magasin Secrets dans Kubernetes), en les faisant crypter gpg dans le référentiel, les secrets Travis, etc.

Lorsque vous utilisez des builds en plusieurs étapes pour ce cas d'utilisation, assurez-vous que les données secrètes resteront dans une image non étiquetée dans le démon local jusqu'à ce que cette image soit supprimée afin que ces données puissent être utilisées pour le cache de build dans les builds suivants. Mais il n'est pas poussé vers le registre lors du transfert de l'image étiquetée finale.

@androa J'aime cette solution mais je ne sais pas ce que je pense des secrets copiés dans le répertoire de travail. C'est probablement bien sur un serveur CI privé, mais ce n'est pas si génial pour un bâtiment local où vous copieriez des fichiers que vous ne devriez pas sortir d'emplacements protégés (sans parler du fait que la copie elle-même est à la fois ennuyeuse et dangereuse dans la mesure où ils pourraient accidentellement se terminer dans le contrôle de source). L'autre option serait d'utiliser un contexte de construction Docker plus large, mais pour de nombreux secrets communs, cela pourrait signifier l'ensemble du volume racine. Des suggestions sur la façon de rendre cela agréable pour les locaux et CI ?

C'est épouvantable. L'autoproclamée « première plate-forme de conteneurs de logiciels au monde » ne peut pas se soucier de transmettre en toute sécurité les secrets de construction dans les conteneurs depuis 3 ans maintenant.

Par l'approche « nous savons mieux » et « ne pas faire de logiciels permettant des erreurs » et ce qui peut être au mieux décrit comme une omission malheureuse lors de la phase de conception, il n'y a aucun support et aucun progrès visible vers l'une des fonctionnalités requises du logiciel DevOps. Toutes les améliorations suggérées par la communauté et parfois même développées au point d'être prêtes à être fusionnées sont fermées de peur que quelqu'un en abuse. À la suite de cet échec de cluster, toutes les façons de transmettre les clés privées nécessaires uniquement pour la phase de construction du conteneur docker nécessitent de sauvegarder ces secrets dans l'historique de construction ou d'être visibles dans la liste des processus avec l'espoir que, respectivement, l'historique de construction ne quitte jamais le machine de confiance ou personne qui n'est pas censé voir la liste des processus. Les deux échoueront même les audits de sécurité les plus permissifs.

Ce numéro est ouvert depuis plus de 2 ans maintenant pour résumer ce qui était alors connu sur le problème et ce qu'il faut faire à ce sujet. Il n'y a toujours pas de solution. Par là, je ne veux pas dire une solution complète qui prendra en charge les schémas de gestion des secrets les plus complexes prêts à l'emploi. Il n'y a PAS DE solution DU TOUT, pas de variables d'environnement hôte, pas de secrets de chargement du chemin de fichier en dehors du contexte de construction. Rien qui puisse être considéré comme sûr, même dans les termes les moins stricts.

@OJezu Comme je l'ai déclaré à plusieurs reprises sur cette question, il existe une proposition ouverte avec essentiellement 0 commentaire à ce sujet.
Si vous voulez voir les secrets avancés, veuillez prendre le temps de commenter la proposition.

Au lieu d'attaquer les gens qui y travaillent tous les jours, essayez la prochaine fois de poser des questions et de lire au moins les derniers commentaires sur le problème que vous commentez.

Les choses peuvent souvent sembler bloquées alors qu'en réalité, il n'y a que des gens qui travaillent dur.
Pour la construction, voir github.com/moby/buildkit où la plupart de ce travail se déroule aujourd'hui.

Merci.

Je suis un peu éméché, car aujourd'hui j'ai passé 9 heures à essayer de trouver une solution à quelque chose qui ne devrait pas être un problème, surtout dans un projet qui est travaillé à temps plein et qui se positionne comme standard de facto et soultion incontournable . J'essayais très fort de ne pas jurer et d'arrêter de m'automutiler en écrivant ces commentaires.

J'ai examiné ce problème et j'ai vu des références à deux solutions, l'une bloquée depuis avril, l'autre déjà fermée. Je ne peux pas m'empêcher de remarquer que la proposition 0 commentaires a 4 participants, le même nombre de commentaires, et mentionne une discussion interne apparente, je suppose par des personnes plus familières avec les subtilités de . Mais si vous souhaitez des commentaires supplémentaires de la part de quelqu'un qui ne programme même pas en go, je peux vous fournir plus de réflexions sur les problèmes que j'ai abordés dans le commentaire précédent.

@OJezu

Il existe au moins une solution simple : utiliser un service dédié (par exemple exécuté sur Jenkins) pour créer des artefacts.
Ce service disposera en toute sécurité de toutes les clés requises pour accéder aux artefacts dont dépend votre image.
À la fin, les artefacts seront placés dans un endroit sûr (par exemple, Jenkins). Ces artefacts ne contiendraient aucun secret, juste un répertoire avec binaires/sources/etc.
Ensuite, un autre service (par exemple, un autre travail Jenkins) accédera à ces artefacts prédéfinis et les transformera en une image pouvant être transférée en toute sécurité vers un registre d'images, qui à son tour est protégé de manière sécurisée à l'aide de rbac/keys pour y accéder à partir des machines de développement/production.

C'est-à-dire que le processus de construction d'image docker n'est pas différent de tout autre système de construction : vous devez avoir un pipeline de construction en place.

Build pipeline

@Vanuan toutes les langues ne sont pas aussi simples avec l'emballage et l'installation, à installer simplement avec un artefact.

Exemples?

Les projets Python intègrent leurs exigences au moment de l'installation, pas au moment de la construction. Dans notre cas, depuis un dépôt privé pypi/conda (protégé par mot de passe)

Donc? Intégrez l'installation à votre processus de génération, puis copiez les packages installés dans une nouvelle image.

Vous devez juste vous assurer que votre image de construction et votre image de production sont basées sur la même image de base Python.

Vous pouvez en effet simplement tout copier dans une nouvelle image en effet. Cela supprime cependant tout l'intérêt d'un Dockerfile. Pourquoi avoir un Dockerfile si la seule chose que vous pouvez l'utiliser est juste pour copier un ensemble de répertoires ?

Donc, je ne peux pas avoir un flux simple dans lequel j'exécute simplement docker build . n'importe où - que ce soit sur la machine de développement ou sur CI, mais je dois dépendre de CI pour créer des packages. Pourquoi même s'embêter avec docker alors ? Je peux écrire un fichier travis, ou configurer le flux en bambou.

Ne pouvez-vous pas simplement pip install requirements.txt dans votre première étape de construction avec des secrets disponibles à extraire de vos référentiels privés. Ensuite, la génération de l'étape suivante copie simplement les packages de site de la première étape.

Pourquoi avoir un Dockerfile si la seule chose que vous pouvez l'utiliser est juste pour copier un ensemble de répertoires ?

Pourquoi pas? L'utilisation d'un Dockerfile pour construire est cohérente.

La spécification de l'image est plus qu'un simple tas de fichiers compressés. Il existe des variables d'environnement, des arguments de ligne de commande, des volumes, etc.

Lisez la référence Dockerfile :
https://docs.docker.com/engine/reference/builder/

Il semble que vous vous soyez principalement concentré sur l'instruction RUN , pensant que Dockerfile est un remplacement pour votre Makefile. Ce n'est pas. Dockerfile n'est destiné qu'à une seule chose : créer une image à partir d'un certain matériel source. Ce que serait ce matériel source - un binaire téléchargé sur http ou un référentiel git - n'a pas d'importance. Docker n'a pas besoin d'être votre système CI, même si vous pouvez l'utiliser comme tel sous certaines conditions.

Je peux écrire un fichier travis, ou configurer le flux en bambou.

Si vous pouvez obtenir le résultat de votre processus de génération, puis l'exécuter dans un autre environnement, sans images ni conteneurs, vous n'avez certainement pas besoin de vous soucier de docker. Pourquoi voudrais-tu?

Environnement séparé et strictement contrôlé qui obtient des réinitialisations garanties entre les builds, mais uniquement si les étapes de build ont changé. Possibilité de l'exécuter n'importe où, pas seulement sur les serveurs CI (comme avec Travis), en liant les instructions de construction au code, ce qui, je pense, est bien si la construction change pour différentes branches de code (par exemple, changer la version de l'environnement d'exécution sur une seule branche). Possibilité d'exécuter un conteneur de construction sur des machines de développeur, permettant d'expédier l'intégralité de l'environnement aux développeurs qui, autrement, n'ont aucune idée de la façon de mettre à niveau leur propre système, mais pourront créer une application avec leurs modifications localement avec le même environnement que tout le monde.

Si je ne voulais pas de tout ça, je m'en tiendrais à lxc + ansible, pas besoin de docker alors.

Vous n'avez pas besoin de docker build pour cela.

Vous n'avez pas besoin de docker build pour cela.

Bien sûr, vous pouvez également fournir un Makefile ou un build_image.sh script pour chaque projet au lieu d'un seul Dockerfile autonome, mais cela présente de multiples inconvénients :

  • Compatibilité multiplateforme : en fournissant un fichier Dockerfile, je sais que tout système pouvant exécuter docker build pourra créer l'image. En fournissant un Makefile ou un build_image.sh , je dois m'assurer manuellement qu'ils fonctionnent sur toutes les plates-formes que je souhaite prendre en charge.
  • Interface connue pour les utilisateurs : Si vous connaissez docker, vous connaissez une partie du comportement de docker build pour n'importe quel projet, même sans regarder le Dockerfile (par exemple en ce qui concerne la mise en cache, etc...). Si j'ai un Makefile ou build_image.sh , pour chaque projet, je dois d'abord savoir quelles sont les commandes à construire, à nettoyer, où et sous quelle forme est le résultat, s'il y a est une mise en cache et sous quelle forme, ...

Oh, Dockerfile est loin d'être autosuffisant. Surtout pour l'environnement de développement.
Considère ceci:

  • la plupart des développeurs ne connaissent pas toutes les différentes options de docker build , mais presque tout le monde sait comment exécuter des scripts bash
  • docker build dépend du répertoire de contexte . Ainsi, à moins que vous ne souhaitiez attendre que des gigaoctets de données (votre code source avec les dépendances) se déplacent d'un emplacement à un autre pour chaque changement de ligne source, vous ne l'utiliserez pas pour le développement.
  • à moins que vous ne construisiez TOUT à partir de zéro, vous avez une dépendance sur le registre Docker
  • il est probable que vous dépendez des référentiels du système d'
  • à moins que vous ne validiez tout dans git, vous aurez des dépendances au niveau du projet, que ce soit npm, l'index de package python, rubygems ou autre chose. Vous dépendrez donc d'un registre de packages externe ou de son miroir
  • comme la plupart des gens l'ont remarqué ici, vous dépendez d'un emplacement de package secret pour vos dépendances privées que vous ne pouvez pas publier dans un référentiel public, vous dépendez donc de cela
  • le provisionnement des secrets est requis pour accéder à cet emplacement sécurisé, vous dépendrez donc d'un système qui distribuera les secrets aux développeurs
  • en plus de Dockefile, vous aurez besoin de docker-compose.yml, et ce n'est pas multiplateforme : vous dépendez toujours des différences de barre oblique inverse/antislash .

Compatibilité multiplateforme : en fournissant un fichier Dockerfile, je sais que tout système pouvant exécuter docker build sera capable de générer l'image.

Dockerfile ne garantit pas la compatibilité multiplateforme. Vous devez toujours fournir plusieurs Dockerfiles pour plusieurs plates-formes. "Peut exécuter docker build" ne veut plus dire "Utilise Linux". Docker prend également en charge les images natives Windows. Vous devez toujours utiliser Cygwin + Linux VM si vous souhaitez exécuter quelque chose spécifiquement destiné aux machines Linux sur un hôte Windows.

Oh, et je n'ai même pas mentionné x86 contre ARM...

Interface connue des utilisateurs : si vous connaissez docker, vous connaissez une partie du comportement de la construction de docker pour n'importe quel projet, même sans regarder le Dockerfile

À moins que vous ne le fassiez pas. Tout le monde sait comment exécuter un script bash sans paramètres ou une seule commande make . Peu de gens savent comment spécifier correctement toutes les différentes options de ligne de commande pour docker build , docker run ou docker-compose . Il est inévitable que vous ayez un script wrapper bash ou cmd.


Avec tout le respect que je dois à ce que les gens de Docker ont fait, je pense que vous en demandez trop. Je crains que le Mobyproject n'ait pas une portée assez large pour prendre en charge tous les workflows de développement imaginables.

Je ne vais pas réfuter tous vos points individuellement. Tout d'abord, vous pouvez bien sûr toujours trouver des situations où l'approche "single Dockerfile" ne fonctionne pas du tout. Cependant, je dirais que pour presque tous les points que vous avez soulevés (qui sont tous valides et pertinents), l'approche "script personnalisé ou makefile" est tout aussi mauvaise ou pire. Juste à titre d'exemple un point :

la plupart des développeurs ne connaissent pas toutes les différentes options de construction de docker, mais presque tout le monde sait comment exécuter des scripts bash

Si je suis impliqué dans 10 projets et qu'ils utilisent tous un Dockerfile, je n'ai besoin d'en apprendre plus sur docker qu'une seule fois, mais avec votre suggestion, j'ai besoin d'apprendre 10 scripts de construction totalement différents. Comment effacer le cache et recommencer à zéro pour le build_image.sh du projet Foo ? Ce n'est pas clair. Si la construction de l'image se fait avec docker build , c'est clair (ofc j'ai besoin de savoir comment fonctionne docker, mais j'ai aussi besoin de le faire pour utiliser l'image qui sort de build_image.sh ).

Dans l'ensemble, je suppose que le point que moi et d'autres essayons de faire est que pour de nombreux scénarios, l'approche "Dockerfile unique" semble très bien fonctionner pour les gens (ce qui est une raison pour laquelle docker est si populaire), en particulier dans le monde open source où généralement toutes les ressources sont accessibles sans secrets. Mais si vous essayez d'appliquer le même modèle que vous avez appris à aimer dans un contexte où une partie de vos ressources a besoin d'informations d'identification pour accéder, l'approche échoue. Il y a eu un certain nombre de suggestions (et de mises en œuvre) de moyens technologiquement pas trop complexes pour le faire fonctionner, mais rien n'est devenu depuis longtemps (cela a été exposé à plusieurs reprises ci-dessus). D'où la frustration.

J'apprécie que les gens fassent des efforts là-dessus, par exemple avec la proposition liée dans #33343. Mon message vise à motiver ce que certaines personnes font et pourquoi elles reviennent sans cesse le demander ici.

Avec tout le respect que je dois à ce que les gens de Docker ont fait, je pense que vous en demandez trop. Je crains que le Mobyproject n'ait pas une portée assez large pour prendre en charge tous les workflows de développement imaginables.

Il me semble que ce que la plupart des gens demandent ici n'est rien de tel, mais seulement un moyen simple d'utiliser les secrets dans docker build d'une manière qui n'est pas moins sécurisée que de les utiliser dans votre build_image.sh personnalisé

Je suis désolé, mais chaque personne dans ce ticket a un cas d'utilisation légèrement différent. Ce sont des cas extrêmes et nécessitent des solutions différentes.

  1. Je souhaite exécuter des images de production sur des machines de développement. Utiliser le registre Docker
  2. Je veux un système CI distribué, afin que chaque développeur ait une version reproductible. Utilisez docker run pour construire votre projet, utilisez docker prune pour nettoyer
  3. Je veux créer des images Docker pour pouvoir les distribuer. Utilisez un serveur CI dédié sur lequel vous pouvez exécuter des builds en plusieurs étapes.

@Vanuan , donc je suppose que votre approche est essentiellement la suivante: n'utilisez pas de build docker, pour autre chose que l'environnement de base. C'est un problème créé pour changer cela. « Vous devez le faire différemment » EST le problème, pas la solution.

Les personnes qui poussent le problème veulent avoir des approches plus simples et plus directes avec les images de docker, sans avoir à contourner les limitations de docker.

Pour toute personne intéressée : j'avais essayé d'exploiter des arguments de construction "masqués par défaut" comme FTP_PROXY pour créer des contextes. C'est sûr en ce qui concerne le fait que docker-build n'expose pas ces arguments masqués aux métadonnées d'image ni aux couches d'image.

36443 était une tentative de l'étendre à un argument de construction nommé SECRET afin que nous puissions encourager les utilisateurs à l'utiliser comme une simple solution de contournement au problème de gestion des secrets.

Cependant, le travail a été raisonnablement rejeté, car la nature masquée de ces arguments de construction n'est pas garantie à l'avenir.

Mon meilleur pari après cela est de suivre les conseils de @AkihiroSuda , d'utiliser docker build --network ou un outil comme habitus pour stocker/transmettre des secrets via un serveur tcp temporaire. Seuls les contextes de construction visibles vivent dans un seul démon docker, au plus large.

Commentant partiellement, je reçois donc une notification dans 5 ans, lorsque Docker décidera enfin de nous faire un petit pas dans la direction d'une bonne gestion des informations d'identification... et aussi, pour donner un aperçu du piratage que j'utilise en ce moment , pour aider les autres, ou pour y faire des trous dont je ne suis pas au courant.

En suivant le numéro de @mumoshu , j'ai finalement eu l'idée d'utiliser les

Donc, essentiellement, je peux utiliser docker-compose, avec un mappage comme celui-ci :

  myProject:
    build:
      context: ../myProject/
      args: 
        - HTTPS_PROXY=${NEXUS_USERNAME}
        - NO_PROXY=${NEXUS_PASSWORD}

Et puis, dans le dossier avec le fichier docker-compose.yml, créez un fichier nommé ".env" avec des paires clé-valeur de NEXUS_USERNAME et NEXUS_PASSWORD - et les valeurs appropriées là-bas.

Enfin, dans le Dockerfile lui-même, nous spécifions notre commande run comme suit :
RUN wget --user $HTTPS_PROXY --password $NO_PROXY

Et ne les déclarez PAS comme ARG dans le DockerFile.

Je n'ai pas encore trouvé mes informations d'identification flottant dans la version résultante n'importe où... mais je ne sais pas si je cherche partout..... Et pour le reste des développeurs de mon projet, ils doivent chacun créez le fichier .env avec les valeurs appropriées pour eux.

@darmbrust J'ai essayé votre solution mais je n'ai pas
Voici ma composition yml :
version : "3.3"
prestations de service:

  buildToolsImage:
    image: vsbuildtools2017:web-v6

    build:
      context: .
      dockerfile: ./vsbuild-web-v6-optimized.dockerfile
      args:
        - CONTAINER_USER_PWD=${CONTAINER_USER_CREDS}

Voici le fichier .env assis à côté du fichier yml :

CONTAINER_USER_CREDS=secretpassword

Et voici mon fichier docker :

# escape=`
FROM microsoft/dotnet-framework:4.7.2-sdk
# Add non-root user
CMD ["sh", "-c", "echo ${CONTAINER_USER_PWD}"] 
RUN net user userone ${CONTAINER_USER_PWD} /add /Y

Et enfin, la commande pour lancer ceci est comme ceci :

docker-compose -f docker-compose.buildImage.yml build

Il construit l'image mais sans utiliser le mot de passe stocké dans le fichier .env.

[Avertissement] Un ou plusieurs build-args [CONTAINER_USER_PWD] n'ont pas été consommés

Qu'est-ce que j'oublie ici?
Merci!

Vous devez utiliser l'un des https://docs.docker.com/engine/reference/builder/#predefined -args dans le fichier docker. Vous ne pouvez pas utiliser vos propres noms d'argument comme CONTAINER_USER_PWD.

C'est ainsi que l'astuce fonctionne, car docker a un comportement spécial pour les arguments prédéfinis, en ce sens que vous pouvez les utiliser sans les déclarer. Et en les utilisant sans les déclarer, ils ne semblent être enregistrés nulle part.

Avec le fichier docker-compose, vous pouvez mapper ces arguments prédéfinis à quelque chose de plus raisonnablement nommé.

@darmbrust Oui, cela a fait l'affaire.
Cependant, ne pensez-vous pas que ça sent mauvais? De meilleures recommandations ?
Merci!

Ce n'est probablement pas aussi malodorant que d'exposer vos informations d'identification ssh-agent sur tcp
via socat pour tout processus local à voler, mais en effet, comme pour tout
lié aux secrets, 'docker build' est en effet assez malodorant.

En fait, j'avais oublié que Docker pour Mac ne peut pas exposer le domaine Unix
sockets sur l'hôte osx aux conteneurs, ce qui ouvre encore plus de
boîte de vers.

Ma solution actuelle, exécuter un compte d'utilisateur de machine Centos VM, GitHub
les informations d'identification y vont, construisez à l'aide de l'outil "Rocker" (obsolète).

Le jeu. 26 juillet 2018, 21:49 Sameer Kumar, [email protected] a écrit :

@darmbrust https://github.com/darmbrust Oui, cela a fait l'affaire.
Cependant, ne pensez-vous pas que ça sent mauvais? De meilleures recommandations ?
Merci!

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/13490#issuecomment-408230125 , ou en sourdine
le fil
https://github.com/notifications/unsubscribe-auth/AAZk5iz1kvCpZ0s65ng4TwL7LmHa9zZvks5uKitDgaJpZM4Eq021
.

Tout ce bug est malodorant. Je n'ai pas trouvé de meilleur moyen... il existe plusieurs autres approches ci-dessus, mais je pense que toutes les autres approches sécurisées nécessitent la mise en place d'un petit serveur http pour alimenter l'image en informations. peut-être moins malodorant, mais plus complexe, plus d'outils, plus de pièces mobiles.

Pas sûr que quelqu'un ait trouvé une "bonne" solution... nous sommes tous coincés à attendre que les dockers fassent quelque chose... ne retenez pas votre souffle, puisque ce bug a été écrit en 2015, et ils l'ont fait. Je n'ai même pas encore proposé une feuille de route, encore moins une solution.

C'est tellement simple et évident, permettre le montage de volumes, (fichiers ou
répertoires) dans le conteneur pendant la construction.

Ce n'est pas une limitation technique, c'est une décision de ne pas autoriser les secrets dans
afin de préserver le comportement de - extraire, exécuter la construction, mêmes entrées, même
sortie, modifiez un argument de construction si vous souhaitez invalider le cache ...

Le problème est que l'abstraction est de plus en plus fuyante
avec des personnes utilisant toutes sortes de hacks maladroits et peu sûrs pour obtenir un "secret"
dans un conteneur.

Newsflash, exposant votre trousseau de clés SSH via TCP, même sur localhost n'est pas
sécurisé, la transmission des informations d'identification via des variables d'environnement n'est pas non plus (astuce, exécution
ps, ou jeter un coup d'œil dans le système de fichiers /proc), les arguments de commande et les variables d'environnement sont tous là, nus, à la vue du monde.

Pour les développeurs de code golang, cela n'a traditionnellement pas été un problème car ils copient-collent
leurs dépendances dans leurs projets plutôt que d'utiliser un outil de gestion des dépendances, les développeurs de golang appellent cette pratique « vendeur ».

Pour toute personne travaillant dans d'autres écosystèmes où le système de build
récupère les dépendances de Git, ou les référentiels qui nécessitent une authentification, c'est un gros problème.

Je suis à peu près sûr qu'il existe une règle de démarrage quelque part dans le sens de,
« ne présumez pas que vous savez comment ou pourquoi vos utilisateurs utilisent le produit ».

Le jeu. 26 juillet 2018, à 22h00, Dan Armbrust, [email protected] a écrit :

Tout ce bug est malodorant. Je n'ai pas trouvé de meilleur moyen... il y a
plusieurs autres approches ci-dessus, mais je pense que toutes les autres sont sécurisées
nécessitent de mettre en place un petit serveur http pour alimenter les informations dans le
image. peut-être moins malodorant, mais plus complexe, plus d'outils, plus émouvant
les pièces.

Pas sûr que quelqu'un ait trouvé une "bonne" solution... nous sommes tous bloqués
attendre que les dockers fassent quelque chose... ne retiens pas ton
souffle, depuis que ce bug a été écrit en 2015, et ils n'ont même pas proposé
une feuille de route encore, encore moins une solution.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/13490#issuecomment-408233258 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAZk5nvbBTj4BAv5TtELNIHhJN8mU0Ctks5uKi38gaJpZM4Eq021
.

@binarytemple Tous ceux qui ont déjà travaillé sur Docker/moby (comme les ingénieurs derrière) savent exactement quel est le problème et l'ont même rencontré.

Volumes est une solution elle-même incroyablement fuyante.
Il existe une proposition, mentionnée un peu dans le flux de commentaires, qui tente de résoudre ce problème de manière raisonnable (https://github.com/moby/moby/issues/33343)

L'essentiel ici est de fournir la "bonne" abstraction plutôt que "toute abstraction qui fonctionne"... nous savons bien sûr que c'est douloureux pour beaucoup dans plus que ce cas.

Beaucoup de travail a été fait sur le constructeur ces derniers temps, ce qui n'est pas encore nécessairement visible, mais les fruits de cet effort commenceront à se manifester dans les mois à venir.
Pour commencer, Docker 18.06 est livré avec une implémentation de générateur alternative soutenue par https://github.com/moby/buildkit.
Vous pouvez penser "en quoi cela m'aide-t-il ?". Buildkit fournit de nombreuses primitives de bas niveau qui nous permettent d'être beaucoup plus flexibles dans le constructeur Docker. Même jusqu'à pouvoir fournir votre propre analyseur de build (qui peut être n'importe quoi d'un analyseur Dockerfile amélioré à quelque chose de complètement différent). Les analyseurs sont spécifiés en haut du "Dockerfile" et sont n'importe quelle image que vous souhaitez utiliser pour analyser le fichier.

Si vous voulez vraiment voir quelque chose maintenant, vous pouvez utiliser le buildkit lui-même et l'exécuter aujourd'hui, il se trouve au-dessus de containerd, vous pouvez créer une intégration personnalisée assez rapidement.

La prise en charge des montages secrets a été ajoutée au buildkit dans https://github.com/moby/buildkit/pull/522 . Ils apparaissent strictement sur tmpfs, sont exclus du cache de construction et peuvent utiliser une source de données configurable. Pas encore de PR qui l'expose dans une syntaxe de fichier docker mais devrait être un simple ajout.

Il existe 2 solutions pour construire des images avec des secrets.

Construction en plusieurs étapes :

FROM ubuntu as intermediate
ARG USERNAME
ARG PASSWORD
RUN git clone https://${USERNAME}:${PASSWORD}@github.com/username/repository.git

FROM ubuntu
# copy the repository form the previous image
COPY --from=intermediate /your-repo /srv/your-repo

Ensuite : docker build --build-arg USERNAME=username --build-arg PASSWORD=password my-image .

Utiliser un générateur d'images : docker-build-with-secrets

@BenoitNorrin désolé, mais vous avez exposé ce mot de passe à chaque processus du système hôte. Unix security 101 - ne mettez pas de secrets comme arguments de commande.

Oui mais il y a des usages où la sécurité compte un peu moins :

  • vous voulez construire sur votre propre ordinateur
  • vous construisez sur votre serveur CI d'entreprise (comme jenkins). La plupart du temps, il s'agit d'avoir accès à un référentiel privé (nexus, git, npm, etc.), donc votre CI peut avoir ses propres informations d'identification pour cela.
  • vous pouvez utiliser une machine virtuelle créée à partir de docker-machine et la supprimer après.

Si c'est le seul problème, @binarytemple , alors simplement ajouter le drapeau docker image build --args-file ./my-secret-file devrait être une solution assez simple pour tout ce problème, n'est-ce pas ? :pensée:

@yajo pourrait être, oui, c'est au moins une solution de contournement jusqu'à ce que le kit de construction soit livré avec le montage des secrets. Bonne suggestion. Merci. B

Malheureusement, la plupart des solutions de contournement mentionnées dans ceux-ci et les nombreux autres tickets exposent toujours les secrets de l'image résultante, ou ne fonctionnent qu'avec des langages spécifiques pour lesquels vous n'avez besoin de dépendances que pendant la compilation et non pendant l'installation.

@binarytemple qui n'arrivera jamais, les mainteneurs de docker ont déjà tué au moins un PR entièrement documenté et entièrement implémenté d'une fonction secrète sûre. Compte tenu du reste de l'histoire (ce billet de 3 ans n'est pas le plus ancien et certainement pas le seul billet/RP sur ce sujet), je pense qu'il est prudent de dire que les responsables des dockers ne comprennent pas le besoin de sécurité, ce qui est un gros problème. problème.

Le plus gros problème, ce sont les rotations secrètes pour moi

vous devez maintenir un graphique des dépendances secrètes des services et mettre à jour deux fois chaque service (pour revenir au nom secret d'origine)

répertorier les secrets des services ne semble pas être facile (j'ai abandonné après quelques tentatives autour de docker service inspect --format='{{.Spec.TaskTemplate.ContainerSpec.Secrets}}' <some_service> ), répertorier les dépendances des services à partir de docker secret inspect <secret_name> serait également utile. Je maintiens donc ce graphique (approximatif) manuellement pour le moment.

Vous devez également spécifier la destination secrète, quand ce n'est pas la valeur par défaut /run/secrets/<secret_name> dans la commande de mise à jour du service docker

J'espère juste un moyen plus simple de faire pivoter les secrets

@caub voici de l'aide CLI :

Les documents Docker pour l' aide au

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName}}{{end}}'

Cela listera tous les noms secrets d'un service. Si vous vouliez à la fois un nom et une pièce d'identité, vous pourriez :

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName .SecretID}}{{end}}' nginx

J'ai toujours mon CI/CD (commandes de mise à jour de service) ou des fichiers de pile qui codent en dur le chemin afin que vous n'ayez pas ce problème lors de la rotation.

Avec les étiquettes, vous pouvez faire en sorte que l'automatisation CI/CD identifie le bon secret si vous n'utilisez pas de fichiers de pile (sans avoir besoin du nom du secret, qui serait différent à chaque fois).

docker build --secret est enfin disponible dans Docker 18.09 https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

@thaJeztah Sommes-nous prêts à clore ce problème ?

Pour les anciennes versions de docker, l'utilisation de la construction en plusieurs étapes avec copie des secrets avant la commande de construction est une option viable, n'est-ce pas ?

```
DE debian en tant que build
COPIER ./secret.conf /chemin/sur/image/
EXÉCUTER build.sh
...

DE debian
COPIER --de=construire...

@andriy-f oui, cela fonctionne, tant que vous;

  • (évidemment) ne copiez pas le secret à l'étape finale 😉, ou :
  • utiliser le build stage / stage dans lequel un secret est présent en tant que "parent" pour l'image finale
  • ne jamais _pousser_ l'étape de construction vers un registre
  • faites confiance à l'hôte sur lequel votre démon s'exécute ; c'est-à-dire en tenant compte du fait que votre étape de « construction » est conservée sous forme d'image ; quelqu'un ayant accès à cette image pourrait avoir accès à votre secret.

Les secrets au moment de la construction sont désormais possibles lors de l'utilisation du kit de construction en tant que constructeur ; voir le billet de blog ici https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

et la documentation ; https://docs.docker.com/develop/develop-images/build_enhancements/

l'option RUN --mount utilisée pour les secrets passera bientôt à la syntaxe Dockerfile par défaut (stable)

Merci @thaJeztah J'ai juste creusé un peu plus et j'ai trouvé cet article peu de temps après sa publication (le message précédent est maintenant supprimé). Merci encore!

Frais. Cela met fin à la question des secrets du temps de construction. Quelque chose pour runtime/devtime (ssh sous OS X) ?

Cette page vous a été utile?
0 / 5 - 0 notes