Moby: Transférer l'agent de clé ssh dans le conteneur

Créé le 13 juin 2014  ·  190Commentaires  ·  Source: moby/moby

Ce serait bien de pouvoir transférer un agent de clé ssh dans un conteneur lors d'un run ou build .
Nous devons souvent créer du code source qui existe dans un référentiel privé où l'accès est contrôlé par la clé ssh.

L'ajout du fichier de clé dans le conteneur est une mauvaise idée car :

  1. Vous venez de perdre le contrôle de votre clé ssh
  2. Votre clé devra peut-être être déverrouillée via une phrase secrète
  3. Votre clé peut ne pas se trouver du tout dans un fichier et n'être accessible que via l'agent de clé.

Vous pourriez faire quelque chose comme :

# docker run -t -i -v "$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" fedora ssh-add -l
2048 82:58:b6:82:c8:89:da:45:ea:9a:1a:13:9c:c3:f9:52 phemmer<strong i="15">@whistler</strong> (RSA)

Mais:

  1. Cela ne fonctionne que pour docker run , pas pour build .
  2. Cela ne fonctionne que si le démon docker s'exécute sur le même hôte que le client.

La solution idéale est que le client transfère le socket de l'agent de clé comme le fait ssh .
Cependant, la difficulté réside dans le fait que cela nécessiterait la construction d'API distantes et les appels d'attachement pour prendre en charge le proxying d'un nombre arbitraire de flux de socket. Faire un seul flux bidirectionnel ne serait pas suffisant car l'agent de clé ssh est un socket de domaine unix et il peut avoir plusieurs connexions simultanées.

aresecurity exintermediate kinfeature

Commentaire le plus utile

@kienpham2000 , pourquoi cette solution ne conserverait-elle pas la clé dans la couche d'image ? Les actions de copie et de suppression de la clé sont effectuées dans des commandes séparées, il y a donc une couche qui devrait avoir la clé.
Notre équipe utilisait la vôtre jusqu'à hier, mais nous découvrons une solution améliorée :

  • Nous générons une URL de pré-signature pour accéder à la clé avec aws s3 cli, et limitons l'accès à environ 5 minutes, nous enregistrons cette URL de pré-signature dans un fichier dans le répertoire repo, puis dans dockerfile nous l'ajoutons à l'image.
  • Dans dockerfile, nous avons une commande RUN qui effectue toutes ces étapes : utilisez l'URL de pré-sing pour obtenir la clé ssh, exécutez npm install et supprimez la clé ssh.
    En faisant cela en une seule commande, la clé ssh ne serait stockée dans aucune couche, mais l'URL de pré-signature sera stockée, et ce n'est pas un problème car l'URL ne sera pas valide après 5 minutes.

Le script de construction ressemble à :

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Dockerfile ressemble à ceci :

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no [email protected] || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

Tous les 190 commentaires

Je me demande si #6075 vous donnera ce dont vous avez besoin

Un conteneur secret peut le rendre un peu plus sûr, mais tous les points mentionnés sont toujours valables.

+1 Je trouverais également cette capacité utile. En particulier lors de la création de conteneurs nécessitant des logiciels provenant de dépôts git privés, par exemple. Je préfère ne pas avoir à partager une clé de dépôt dans le conteneur, et j'aimerais plutôt pouvoir faire en sorte que le "docker build ..." utilise une autre méthode pour accéder aux clés SSH déverrouillées, peut-être via un ssh en cours d'exécution -agent.

+1. Je commence juste à me mouiller les pieds avec Docker et c'est la première barrière que j'ai rencontrée. J'ai passé un certain temps à essayer d'utiliser VOLUME pour monter la chaussette d'authentification avant de réaliser que docker ne peut/ne veut pas monter un volume hôte lors d'une construction.

Je ne veux pas que des copies d'une clé SSH sans mot de passe traînent et que la mécanique consistant à en copier une dans un conteneur puis à la supprimer pendant la construction semble erronée. Je travaille dans EC2 et je ne me sens même pas à l'aise de copier mes clés privées là-haut (sans mot de passe ou non.)

Mon cas d'utilisation consiste à créer un projet erlang avec des barres d'armature. Effectivement, je _pourrais_ cloner le premier dépôt et l'AJOUTER à l'image avec un Dockerfile, mais cela ne fonctionne pas avec les dépendances privées du projet. Je suppose que je pourrais simplement construire le projet sur la machine hôte et AJOUTER le résultat à la nouvelle image Docker, mais j'aimerais le construire dans le bac à sable qu'est Docker.

Voici d'autres personnes qui ont le même cas d'utilisation : https://twitter.com/damncabage/status/453347012184784896

S'il vous plaît, embrassez SSH_AUTH_SOCK, c'est très utile.

Merci

Edit : Maintenant que j'en sais plus sur le fonctionnement de Docker (couches FS), il est impossible de faire ce que j'ai décrit en ce qui concerne l'ajout d'une clé SSH lors d'une construction et sa suppression plus tard. La clé existera toujours dans certaines des couches FS.

+1, pouvoir utiliser SSH_AUTH_SOCK sera super utile !

J'utilise des clés SSH pour m'authentifier avec Github, qu'il s'agisse d'un référentiel privé ou public.

Cela signifie que mes commandes git clone ressemblent à : git clone [email protected]:razic/my-repo.git .

Je peux monter en volume mon répertoire hôte ~/.ssh dans mes conteneurs pendant un docker run et ssh tout va bien. Je ne peux cependant pas monter mon ~/.ssh lors d'un docker build .

:+1: pour le transfert ssh pendant les builds.

Si je comprends bien, c'est une mauvaise façon. La bonne façon est de créer une image docker dans la machine de développement, puis de la copier sur le serveur docker.

@SevaUA - non, ce n'est pas correct. Cette requête est due à une limitation lors de l'exécution de docker build... . Vous ne pouvez pas exporter une variable dans cette étape comme vous le pouvez lorsque vous effectuez un docker run ... . La commande run permet d'exporter des variables dans le conteneur docker pendant l'exécution, alors que la construction ne le permet pas. Cette limitation est partiellement intentionnelle en fonction du fonctionnement de dockerd lors de la construction de conteneurs. Mais il existe des moyens de contourner ce problème et le cas d'utilisation décrit est valable. Cette demande tente donc d'implémenter cette capacité dans build, d'une manière ou d'une autre.

J'aime l'idée de # 6697 (magasin secret / coffre-fort), et cela pourrait fonctionner pour cela une fois qu'il est fusionné. Mais si cela ne fonctionne pas, une alternative consiste à faire des trucs ssh de proxy transparent man-in-the-middle en dehors du démon docker, interceptant le trafic du démon docker (pas en interne). Alternativement, toutes les requêtes git + ssh peuvent être adressées à un hôte défini localement qui constitue un proxy transparent vers github ou tout ce dont vous avez finalement besoin pour vous retrouver.

Cette idée a déjà été évoquée (voir commentaire 2). Cela ne résout pas le problème.

+1 pour le transfert ssh pendant les builds.

+1 sur le transfert d'agent SSH sur docker build

+1 pour le transfert ssh pendant la construction pour l'installation de npm ou similaire.

Est-ce que quelqu'un a fait fonctionner la redirection ssh pendant l'exécution sur OSX ? J'ai posé une question ici : http://stackoverflow.com/questions/27036936/using-ssh-agent-with-docker/27044586?noredirect=1#comment42633776_27044586 il semble que ce ne soit pas possible avec OSX...

+1 =(

Il suffit de frapper ce barrage routier aussi. Essayer d'exécuter npm install pointé sur un dépôt privé. la configuration ressemble à :
host -> vagrant -> docker peut ssh-agent transférer host -> vagrant -! docker

+1
Appuyez simplement sur ceci tout en essayant de comprendre comment faire fonctionner l'agent ssh pendant la « construction de docker ».

+1 comme les gars précédents. Cela semble la meilleure solution à ce problème lorsque vous devez accéder à un ou plusieurs référentiels git privés (pensez à bundle install et npm install par exemple) lors de la création de l'image Docker.

Je peux monter en volume mon répertoire hôte ~/.ssh dans mes conteneurs pendant une exécution de docker et ssh est tout bon.

@razic Pouvez-vous partager comment vous faites fonctionner cela ? Parce que quand j'ai essayé cela avant, il s'est plaint de "Mauvais propriétaire ou autorisations"

À moins que vous ne vous assuriez que tous les conteneurs s'exécutent avec un utilisateur spécifique ou des autorisations vous permettant de le faire ?

+1 à SSH_AUTH_SOCK

@tonivdv jetez un œil à la commande docker run dans le commentaire initial sur ce problème. Il lie le chemin référencé par SSH_AUTH_SOCK à /tmp/ssh_auth_sock à l'intérieur du conteneur, puis définit le SSH_AUTH_SOCK dans le conteneur sur ce chemin.

@md5 Je suppose que @razic et @tonivdv parlent d'un montage comme ceci : -v ~/.ssh:/root/.ssh:ro , mais lorsque vous faites cela, les fichiers .ssh n'appartiennent pas à root et échouent donc aux contrôles de sécurité.

@KyleJamesWalker ouais c'est ce que je comprends de @razic et qui était l'une de mes tentatives il y a quelque temps, alors quand j'ai lu @razic a pu le faire fonctionner, je me demandais comment :)

@tonivdv J'aimerais aussi savoir si c'est possible, je n'ai rien trouvé la dernière fois que j'ai essayé.

+1 Je suis intéressé par la création d'environnements de développement jetables à l'aide de Docker, mais je n'arrive pas à le faire fonctionner. Cela aiderait beaucoup à cet égard.

Pour tous ceux qui recherchent une solution temporaire, j'ai un correctif que j'utilise pour forcer les choses dans :

https://github.com/atrauzzi/docker-laravel/blob/master/images/php-cli/entrypoint.sh

Ce n'est en aucun cas une solution souhaitable car elle nécessite un script de point d'entrée complet, mais fonctionne.

@atrauzzi approche intéressante. Pour notre dev env, nous construisons une image de base et y copions la clé ssh directement. Il a l'avantage de ne pas avoir besoin de le fournir à chaque passage. Et chaque image héritant de cet mage par défaut contient également la clé. Cependant avec notre manière vous ne pouvez pas le partager publiquement évidemment ;p

+1 ce serait super

@tonivdv Le conteneur pour lequel le script est destiné est créé et détruit fréquemment car il ne s'agit que d'un hôte pour les outils CLI. Vous êtes bien entendu libre de ne faire l'opération qu'une seule fois. Mais si quelqu'un modifie ses paramètres et réexécute une commande via le conteneur, il doit s'agir d'une nouvelle copie à chaque fois.

@atrauzzi je comprends. Votre approche doit être adoptée par des images docker qui pourraient nécessiter une clé ssh privée. Par exemple, une image de composition doit inclure votre script de point d'entrée en cas de dépôts privés. Au moins jusqu'à ce que docker propose une solution native.

:+1: pour le transfert ssh via build

Incontournable ici aussi !

@atrauzzi J'utilise actuellement une autre approche que j'aime beaucoup. Il crée un conteneur de volume de données avec les éléments ssh dedans. Lorsque vous souhaitez utiliser vos clés ssh dans un autre conteneur, je peux simplement l'utiliser avec la commande suivante :

docker run -ti --volumes-from ssh-data ...

De cette façon, vous n'avez pas besoin de mettre un point d'entrée sur chaque image et cela peut fonctionner avec toutes les images.

Pour créer ce conteneur, je fais ce qui suit

docker run \
  --name ssh-data \
  -v /root/.ssh \
  -v ${USER_PRIVATE_KEY}:/root/.ssh/id_rsa \
  busybox \
  sh -c 'chown -R root:root ~/.ssh && chmod -R 400 ~/.ssh'

J'espère que cela pourra aider d'autres :)

Acclamations

@tonivdv - J'ai adopté mon approche car si quelqu'un doit ajouter ou mettre à jour des paramètres SSH, ils doivent être réimportés. Le conteneur spécifique que j'utilise est conçu pour exécuter des commandes uniques, donc à chaque fois qu'il s'exécute, il faut la copie pour s'assurer qu'il est à jour.

@atrauzzi Oui, je comprends. Cela étant dit, il appartient à l'utilisateur de maintenir correctement son conteneur de volume ssh. Il peut même en utiliser d'autres si nécessaire. Et en option, il peut être généré à la volée avec un script. Mais je ne pense pas qu'il y ait une seule et unique bonne solution. Tout dépend des besoins. Je voulais juste partager afin que les autres puissent choisir la solution en fonction de leurs besoins. J'espère bloguer à ce sujet bientôt, et je ferai également suivre votre solution! Acclamations

Je ne voudrais pas exiger que les personnes exécutant vos conteneurs maintiennent un conteneur de données uniquement rempli de clés ssh. Semble impliqué.

@atrauzzi Il est vrai que le conteneur de volume doit être là, mais à votre manière, l'utilisateur doit partager sa clé ssh lors de l'exécution trop juste? Donc, en plus d'avoir besoin d'un conteneur de volume ssh, la seule différence entre les deux solutions du point de vue de l'exécution est :

docker run ... --volumes-from ssh-data ... php-cli ...

et

docker run ... -v ~/.ssh:/path/.host-ssh ... php-cli ..

à droite? Ou est-ce que j'ai raté autre chose :)

Mais je comprends tout à fait pourquoi vous le faites à votre façon. Cependant, si vous souhaitez utiliser, par exemple, une image de compositeur de quelqu'un d'autre, la méthode volumes-from fonctionnera immédiatement. Au moins ça évite de créer sa propre image avec le "entrypoint hack".

Comme je l'ai dit, les deux sont une solution de contournement et les deux ont des avantages et des inconvénients.

Acclamations

Ce serait vraiment bien d'obtenir une mise à jour de l'équipe Docker sur l'état de cette fonctionnalité. Plus précisément, l'authentification SSH à partir de docker build .

Cela approche déjà d'un an. Un peu surprenant, étant donné la praticité des cas d'utilisation réels pour cela. Actuellement, nous générons dynamiquement des images en validant des conteneurs en cours d'exécution. Nous ne pouvons pas avoir un Dockerfile dans le référentiel de notre application. Cela interrompt le flux pour pratiquement tout. Je ne peux pas vraiment utiliser mon application avec des services Docker comme Compose ou Swarm jusqu'à ce que ce problème soit résolu.

Une mise à jour serait super appréciée. S'il te plaît et merci.

/cc @phemmer

Ce n'est pas que nous ne voulons pas de cette fonctionnalité ou quoi que ce soit, je vois vraiment un cas d'utilisation pour quelque chose comme ça ou des secrets dans la construction, nous aurions juste besoin d'une proposition de quelqu'un prêt à mettre en œuvre, puis si elle est approuvée la mise en œuvre de la proposition.
Aussi je parle au nom de moi-même pas de tous les mainteneurs.

@jfrazelle

Je sais que vous ne nous ignorez pas :)

Le statut est donc :

C'est quelque chose que nous envisagerions de mettre en œuvre s'il y a une proposition acceptée
et la bande passante d'ingénierie.

Cela vous semble-t-il exact ?

De plus, existe-t-il actuellement des propositions ouvertes qui traitent de cette question ?

Le mardi 7 avril 2015, Jessie Frazelle [email protected] a écrit :

Ce n'est pas que nous ne voulons pas de cette fonctionnalité ou quoi que ce soit, je vois vraiment une utilité
cas pour quelque chose comme ça ou secrets dans la construction, nous aurions juste besoin d'un
proposition de quelqu'un disposé à mettre en œuvre, puis si elle est approuvée, le
mise en œuvre de la proposition.
Aussi je parle au nom de moi-même pas de tous les mainteneurs.

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

C'est quelque chose que nous envisagerions de mettre en œuvre s'il y a une proposition acceptée
et la bande passante d'ingénierie.

Oui

Et je ne pense pas qu'il y ait de propositions ouvertes pour cela.

Le mar 7 avril 2015 à 14:36, Zachary Adam Kaplan <
[email protected]> a écrit :

@jfrazelle

Je sais que vous ne nous ignorez pas :)

Le statut est donc :

C'est quelque chose que nous envisagerions de mettre en œuvre s'il y a une proposition acceptée
et la bande passante d'ingénierie.

Cela vous semble-t-il exact ?

De plus, existe-t-il actuellement des propositions ouvertes qui traitent de cette question ?

Le mardi 7 avril 2015, Jessie Frazelle [email protected]
a écrit:

Ce n'est pas que nous ne voulons pas de cette fonctionnalité ou quoi que ce soit, je vois vraiment une utilité
cas pour quelque chose comme ça ou secrets dans la construction, nous aurions juste besoin d'un
proposition de quelqu'un disposé à mettre en œuvre, puis si elle est approuvée, le
mise en œuvre de la proposition.
Aussi je parle au nom de moi-même pas de tous les mainteneurs.

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

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

Je ne sais pas si je simplifie trop les choses, mais voici ma proposition :

SSHAGENT : transférer # valeurs par défaut à ignorer

Si défini, lors de la construction, le socket et les variables d'environnement associées sont connectés au conteneur, où ils peuvent être utilisés. Les pièces mécaniques de celui-ci existent déjà et fonctionnent, il suffit de les connecter en docker build .

Je n'ai aucune expérience de travail dans la base de code Docker, mais c'est suffisamment important pour moi pour que j'envisage de m'en occuper.

Super. Où puis-je savoir comment soumettre une proposition? y a t-il
directive spécifique ou devrais-je simplement ouvrir un problème?

Le mardi 7 avril 2015, Jessie Frazelle [email protected] a écrit :

C'est quelque chose que nous envisagerions de mettre en œuvre s'il existe une
proposition
et la bande passante d'ingénierie.

Oui

Et je ne pense pas qu'il y ait de propositions ouvertes pour cela.

Le mar 7 avril 2015 à 14:36, Zachary Adam Kaplan <
[email protected]
<_e i="18">

@jfrazelle

Je sais que vous ne nous ignorez pas :)

Le statut est donc :

C'est quelque chose que nous envisagerions de mettre en œuvre s'il existe une
proposition
et la bande passante d'ingénierie.

Cela vous semble-t-il exact ?

De plus, existe-t-il actuellement des propositions ouvertes qui traitent de cette question ?

Le mardi 7 avril 2015, Jessie Frazelle < [email protected]
<_e i="31"/> a écrit :

Ce n'est pas que nous ne voulons pas de cette fonctionnalité ou quoi que ce soit, je vois vraiment un
utiliser
cas pour quelque chose comme ça ou secrets dans la construction, nous aurions juste besoin d'un
proposition de quelqu'un disposé à mettre en œuvre, puis si elle est approuvée, le
mise en œuvre de la proposition.
Aussi je parle au nom de moi-même pas de tous les mainteneurs.

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

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

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

Je veux dire comme une proposition de design
https://docs.docker.com/project/advanced-contributing/#design -proposal

Le mar 7 avril 2015 à 14:39, Daniel Staudigel [email protected]
a écrit:

Je ne sais pas si je simplifie trop les choses, mais voici ma proposition :

SSHAGENT : transférer # valeurs par défaut à ignorer

Si défini, pendant la construction, le socket et les variables d'environnement associées sont
reliés au conteneur, où ils peuvent être utilisés. Les pièces mécaniques
de ceux-ci existent déjà et fonctionnent, c'est juste une question de connexion
eux dans docker build.

Je n'ai aucune expérience de travail dans la base de code Docker, mais ceci
est suffisamment important pour moi pour que j'envisage de l'assumer.

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

C'est une idée de très haut niveau, mais si au lieu de se connecter via l'API distante de docker, docker exécutait un démon d'initialisation, avec un démon ssh fourni, à l'intérieur du conteneur ?

Cela pourrait être utilisé pour résoudre un certain nombre de problèmes.

  • Ce démon serait PID 1, et le processus de conteneur principal serait PID 2. Cela résoudrait tous les problèmes avec PID 1 ignorant les signaux et les conteneurs ne s'arrêtant pas correctement. (#3793)
  • Cela permettrait de transférer proprement l'agent de clé SSH. (#6396)
  • Ce démon pourrait garder les espaces de noms ouverts (#12035)
  • Un ATS serait créé par le démon (#11462)
  • ... et probablement de nombreux autres problèmes que j'oublie.

vous voudrez peut-être voir https://github.com/docker/docker/issues/11529 à propos du
premier point

Le Mar 7 Avr 2015 à 14:46, Patrick Hemmer [email protected]
a écrit:

C'est une idée de très haut niveau, mais et si au lieu de s'attacher à travers
l'API distante de docker, docker a exécuté un démon d'initialisation, avec un ssh fourni
démon, à l'intérieur du conteneur?

Cela pourrait être utilisé pour résoudre un certain nombre de problèmes.

  • Ce démon serait PID 1, et le processus de conteneur principal serait
    PID 2. Cela résoudrait tous les problèmes avec PID 1 ignorant les signaux et
    les conteneurs ne se ferment pas correctement. (#3793
    https://github.com/docker/docker/issues/3793)
  • Cela permettrait de transférer proprement l'agent de clé SSH. (#6396
    https://github.com/docker/docker/issues/6396)
  • Ce démon pourrait maintenir les espaces de noms ouverts (#12035
    https://github.com/docker/docker/issues/12035)
  • Un ATS serait créé par le démon (#11462
    https://github.com/docker/docker/issues/11462)
  • ... et probablement de nombreux autres problèmes que j'oublie.

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

11529 n'a aucun rapport avec le problème PID 1.

shoot effing copier coller, maintenant je dois retrouver l'autre

non, c'est celui-là, il corrige les choses zombies PID 1, ce à quoi je pensais que vous faisiez référence, mais peu importe, je publiais juste car tout est intéressant

@phemmer Il semble que vous ayez l'expertise pour nous guider dans une proposition intelligente de mise en œuvre.

Cela ressemble également à @dts et je suis prêt à passer du temps à travailler là-dessus.

@phemmer et @dts y a-t-il un moyen possible d'intégrer cette discussion dans un client de discussion légèrement plus en temps réel pour une communication plus facile ? Je suis disponible via Slack, Google Chat/Hangout, IRC et je téléchargerai autre chose si besoin est.

@phemmer Il semble que vous ayez l'expertise pour nous guider dans une proposition intelligente de mise en œuvre

Malheureusement pas vraiment :-)
Je peux lancer des idées de conception, mais je ne connais que de petites parties de la base de code Docker. Ce type de changement est susceptible d'être à grande échelle.

Il y a déjà eu quelques propositions ici :

@phemmer suggéré

et si au lieu de se connecter via l'API distante de docker, docker exécutait un démon d'initialisation, avec un démon ssh fourni, à l'intérieur du conteneur ?

@dts suggéré

SSHAGENT : transférer # valeurs par défaut à ignorer
Si défini, lors de la construction, le socket et les variables d'environnement associées sont connectés au conteneur, où ils peuvent être utilisés. Les pièces mécaniques existent déjà et fonctionnent, il suffit de les connecter dans la construction de docker.

@razic suggéré

Activez la liaison de volume pour docker build .

Ce dont nous avons vraiment besoin à ce stade, c'est que quelqu'un accepte l'un d'entre eux afin que nous puissions commencer à travailler dessus.

@jfrazelle Une idée sur la façon dont nous pouvons passer à l'étape suivante ? Vraiment, j'essaie juste de faire ça. Il est clair qu'il y a beaucoup d'intérêt pour cela. Je suis prêt à défendre la fonctionnalité, à la mener à terme.

Je peux être disponible pour une réunion slack/irc/Gchat/etc, je pense que cela facilitera un peu les choses, au moins pour rassembler les exigences et décider d'une ligne de conduite raisonnable.

@dts suggéré

SSHAGENT : transférer # valeurs par défaut à ignorer

C'est juste une idée sur la façon dont il serait consommé, pas mis en œuvre. Le "démon init/ssh" est une idée de la façon dont il serait implémenté. Les deux pourraient exister tous les deux.

@razic suggéré

Activez la liaison de volume pour l'exécution de docker.

Malheureusement, cela ne fonctionnerait pas. En supposant que cela signifie docker build , et non docker run , qui prend déjà en charge les montages de volume, le client peut être distant (boot2docker est un exemple frappant). Les liaisons de volume ne fonctionnent que lorsque le client se trouve sur le même hôte que le démon docker.

@razic s'il vous plaît voir ce lien sur la proposition de conception... ce ne sont pas des propositions https://docs.docker.com/project/advanced-contributing/#design -proposal

@phemmer

Je ne comprends pas exactement pourquoi cela ne peut pas fonctionner. docker-compose fonctionne avec des montages de volume sur un cluster swarm . Si le fichier/dossier n'est pas sur le système hôte, il exerce le même comportement que si vous exécutiez -v avec un chemin qui n'existe pas.

@jfrazelle Compris .

Si le fichier/dossier ne se trouve pas sur le système hôte, il exerce le même comportement que si vous exécutiez -v avec un chemin qui n'existe pas sur un docker local.

Je ne suis pas sûr de suivre votre point. Comment ce comportement aide-t-il ce problème ?
Si j'ai un agent de clé ssh à l'écoute de /tmp/ssh-UPg6h0 sur ma machine locale et que docker s'exécute sur une machine distante et que j'appelle docker build , cet agent de clé ssh local n'est pas accessible au démon docker. Le montage de volume ne l'obtiendra pas et les conteneurs docker build n'auront pas accès à la clé ssh.

À un niveau élevé, je ne vois que 2 façons de résoudre ce problème :

1. Proxy le socket de l'agent de clé ssh :

Le démon docker crée un socket de domaine Unix à l'intérieur du conteneur et chaque fois que quelque chose s'y connecte, il renvoie cette connexion au client qui exécute réellement la commande docker build .

Cela peut être difficile à implémenter car il peut y avoir un nombre arbitraire de connexions à ce socket de domaine Unix à l'intérieur du conteneur. Cela signifierait que le démon et le client docker doivent proxy un nombre arbitraire de connexions, ou le démon doit être capable de parler du protocole de l'agent ssh et de multiplexer les requêtes.

Cependant, maintenant que l'API distante Docker prend en charge les Websockets (ce n'était pas le cas au moment où ce problème a été créé), cela pourrait ne pas être trop difficile.

2. Démarrez un véritable démon SSH

Au lieu de pirater l'agent ssh, utilisez une connexion ssh réelle du client vers le conteneur. Le client docker aurait soit un client ssh intégré, soit invoquerait ssh dans le conteneur distant.
Ce serait un changement à plus grande échelle car il remplacerait la façon dont la fixation aux conteneurs est mise en œuvre. Mais cela éviterait également à docker d'avoir à gérer cela et de migrer vers des protocoles standard.
Cela a également le potentiel de résoudre d'autres problèmes (comme mentionné ici ).

Donc, en fin de compte, un changement à beaucoup plus grande échelle, mais pourrait être une solution plus appropriée.
Bien que de manière réaliste, en raison de l'échelle, je doute que cela se produise.

@phemmer

Je ne suis pas sûr de suivre votre point. Comment ce comportement aide-t-il ce problème ?

Parce que le cas d'utilisation le plus courant est celui des personnes qui créent des images avec des dépendances hébergées dans des référentiels privés nécessitant une authentification SSH.

Vous créez l'image sur une machine qui a une clé SSH. C'est simple.

Si j'ai un agent de clé ssh qui écoute sur /tmp/ssh-UPg6h0 sur ma machine locale et que docker s'exécute sur une machine distante et que j'appelle docker build, cet agent de clé ssh local n'est pas accessible au démon docker.

Je sais. On s'en fout? Je vais exécuter docker build sur une machine qui a accès au socket d'authentification.

Ce que j'essaie de dire, c'est que... docker-compose vous permet d'utiliser la commande de volume contre un cluster swarm , que le fichier soit réellement sur l'hôte ou non ! .

Nous devrions faire la même chose pour les montages de volume sur les builds docker.

| Le fichier est sur le système | Action |
| :-- | :-- |
| Oui | Monter |
| Non | Aucun (en fait, il essaie en quelque sorte de monter mais crée un dossier vide si le fichier/dossier n'existe pas, vous pouvez le vérifier en exécutant docker run -v /DOES_NOT_EXIST:/DOES_NOT_EXIST ubuntu ls -la /DOES_NOT_EXIST ) |

L'un des concepts derrière swarm est de rendre le modèle multi-hôte transparent.

C'est bien que nous pensions à un docker distant, mais cela ne devrait pas vraiment avoir d'importance.

Nous devrions simplement copier le comportement du montage de volume pour docker build de la même manière que nous le faisons pour docker run .

Depuis https://github.com/docker/compose/blob/master/SWARM.md :

La principale chose qui empêche les applications multi-conteneurs de fonctionner de manière transparente sur Swarm est de les amener à se parler : l'activation de la communication privée entre les conteneurs sur différents hôtes n'a pas été résolue de manière non piratée.

À long terme, la mise en réseau est en train d'être remaniée de manière à mieux s'adapter au modèle multi-hôtes. Pour l'instant, les conteneurs liés sont automatiquement planifiés sur le même hôte.

@phemmer Je pense que les gens réfléchissent probablement à une solution au problème que vous avez décrit. Le problème que vous décrivez ressemble à https://github.com/docker/docker/issues/7249 qui est séparé.

Si nous adoptons mon approche : autoriser simplement le montage de volume dans docker build (peu importe si le fichier que vous essayez de monter est réellement sur le système , alors nous pouvons fermer ce problème. et commencer à travailler sur https://github.com/ docker/docker/issues/7249 qui étendrait le comportement de cette fonctionnalité au travail avec des démons docker distants qui n'ont pas le fichier local.

@ cpuguy83 Avant de créer une proposition, je regardais #7133 et j'ai remarqué qu'il semblait directement lié.

Pourriez-vous simplement ajouter quelques mots ici ? Est-ce que #7133 est en fait lié à ma suggestion pour résoudre ce problème, qui consiste à permettre à docker build de prendre en charge les volumes.

@razic C'est en relation avec le fait que VOLUME /foo crée en fait un volume et le monte dans le conteneur pendant la construction, ce qui n'est généralement pas souhaitable.

Je dirais également qu'une proposition basée sur l'utilisation de montages de liaison pour obtenir des fichiers dans des conteneurs de construction ne fonctionnera probablement pas.
Voir #6697

L'exécution de -v avec docker build peut avoir un chemin d'exécution de code différent.
Au lieu de créer un volume et de le monter pendant la construction, nous pouvons conserver le
comportement actuel selon lequel les volumes dans les fichiers docker ne sont pas référencés. Et
à la place, n'agissez que sur -v lors de l'exécution à l'aide d'arguments de la CLI.

Le mercredi 8 avril 2015, Brian Goff [email protected] a écrit :

@razic https://github.com/razic C'est par rapport au fait que VOLUME
/foo crée en fait un volume et le monte dans le conteneur pendant
build, ce qui est généralement indésirable.

Je dirais aussi une proposition basée sur l'utilisation de bind-mounts pour obtenir des fichiers dans
construire des conteneurs ne va probablement pas voler.
Voir #6697 https://github.com/docker/docker/pull/6697

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

@ cpuguy83 Merci pour les éclaircissements.

Le 6697 ne va pas non plus voler car il est déjà fermé et le #10310 est pratiquement une dupe du #6697.

+1, je viens d'appuyer dessus aujourd'hui en essayant de créer une image pour une application Rails qui utilise Bower pour installer les dépendances côté client. Il arrive que l'une des dépendances pointe vers [email protected]:angular/bower-angular-i18n.git et puisque git échoue là-bas, bower échoue, et la construction de l'image échoue également.

J'aime vraiment ce que fait le vagabond. Avec une seule configuration forward_agent dans le fichier Vagrant, cela est résolu pour les invités vagabonds. Docker pourrait-il implémenter quelque chose comme ça?

De plus, comme note supplémentaire, cela se produit lors de la construction de l'image. Quelqu'un connaît-il des solutions de contournement existantes?

Ma solution de contournement consistait à générer une nouvelle paire de clés RSA, à configurer la clé de pub sur github (ajouter l'empreinte digitale) et à ajouter la clé privée à l'image Docker :

ADD keys/docker_rsa /srv/.ssh/id_rsa

J'aimerais éviter cela, mais je suppose que c'est acceptable pour le moment. Toutes autres suggestions appréciées !

Je ne sais pas qui a tué plus de chiots. Vous pour l'avoir fait, ou Docker pour ne pas vous avoir fourni de meilleur moyen pour l'instant.

En tout cas je vais faire une proposition ce week-end probablement. @ cpuguy83 a raison de dire que les gens réfléchissent au moins à cela et discutent des solutions possibles. Donc, à ce stade, il s'agit simplement de nous mettre d'accord sur quelque chose et de faire travailler quelqu'un dessus. Je suis totalement prêt à y travailler car c'est en fait l'un de mes plus gros problèmes avec Docker actuellement.

@razic C'est un cas d'utilisation assez courant, alors merci de vous y pencher également. Quant à la solution de contournement, elle fonctionne. Peut-être que la clé pourrait être supprimée de l'image après avoir été utilisée, après tout, elle n'est utilisée que pour obtenir le code de l'application à partir de github.

@fullofcaffeine Je ne suis pas sûr à 100% du fonctionnement interne de Docker, mais je pense que, à moins que cela ne soit fait dans une seule commande RUN (ce qui est impossible avec votre solution de contournement), l'historique de l'image conserve la clé SSH.

@razic bon point.

Pour contourner cette limitation, nous avons joué avec l'idée de télécharger les clés privées (à partir d'un serveur HTTP local), d'exécuter une commande qui nécessite les clés et de les supprimer ensuite.

Puisque nous faisons tout cela dans un seul RUN , rien n'est mis en cache dans l'image. Voici à quoi cela ressemble dans le Dockerfile :

RUN ONVAULT npm install --unsafe-perm

Notre première implémentation autour de ce concept est disponible sur https://github.com/dockito/vault

Le seul inconvénient est de nécessiter l'exécution du serveur HTTP, donc aucun hub Docker n'est construit.

Laissez-moi savoir ce que vous pensez :)

+1
j'adorerais voir cela mis en œuvre, cela aiderait à configurer des conteneurs pour l'environnement de développement

+1, il suffit de transférer l'agent ssh avec boot2dock

Nous avons fini par suivre un processus en 3 étapes pour contourner cette limitation :

  1. construire un conteneur docker sans dépendances requises par SSH, en ajoutant la source à l'étape finale
  2. monter la source via un volume partagé, plus SSH_AUTH_SOCK via un volume partagé et exécuter l'étape de construction, en écrivant la sortie nécessitant ssh (disons, github hébergé ruby ​​gems) dans le volume partagé
  3. relancez docker build, ce qui relancera l'ajout de la source, car les gemmes se trouvent maintenant dans le répertoire source

Le résultat est une image docker avec des dépendances extraites via SSH-auth qui n'a jamais eu de clé SSH.

J'ai créé un script pour activer le transfert d'agent ssh pour docker run dans un environnement boot2docker sur OSX avec un minimum de tracas. Je sais que cela ne résout pas le problème de construction, mais pourrait être utile pour certains :

https://gist.github.com/rcoup/53e8dee9f5ea27a51855

L'agent de clé Forward ssh fonctionne-t-il avec des services tels que le service de conteneur Amazon EC 2 ? Il me semble que cela nécessitera un logiciel spécifique qui peut ne pas être disponible sur toutes les plateformes ou PaaS que vous utilisez pour déployer vos conteneurs.

Une solution plus générique, adaptée à tous, est requise.

Actuellement, j'utilise des variables d'environnement. Un script bash obtient la variable de clé privée (et les hôtes connus) et l'imprime dans les fichiers id_rsa etknown_hosts. Cela fonctionne, mais je n'ai pas encore évalué les implications de sécurité d'une telle solution.

FWIW, j'ai découvert qu'un agent ssh conteneurisé et un partage de volume fonctionnaient bien avec un minimum de gaffes :

https://github.com/whilp/ssh-agent

Ce serait formidable d'avoir un support de première classe pour cela, cependant.

Il est important de distinguer ce qui fonctionne dans _run_ vs _build_. La solution « @whilp fonctionne à merveille dans _run_ mais ne fonctionne pas dans _build_ parce que vous ne pouvez pas accéder aux volumes d'autres docker au cours _build_. C'est pourquoi ce ticket est toujours une plaie ouverte et douloureuse.

@rvowles oui , d'accord. J'ai mis en place quelque chose pour générer des conteneurs via une séquence d'appels run/commit (c'est-à-dire sans Dockerfiles); cela avait du sens pour mon cas d'utilisation particulier, mais une prise en charge généralisée (y compris le temps de construction) pour quelque chose comme la redirection d'agent serait très utile.

Les adresses IP pour l'exécution des conteneurs sont-elles incluses dans /etc/hosts lors de la construction ? Si tel est le cas, une solution peut être de démarrer un conteneur qui a servi les clés, puis de s'y connecter pendant la construction.

Vous serez peut-être tous intéressé de savoir que j'ai blogué sur un moyen d'utiliser votre agent SSH pendant docker build - http://aidanhs.com/blog/post/2015-10-07-dockerfiles-reproducibility- supercherie/#_streamlining_your_experience_using_an_ssh_agent

Vous avez juste besoin de démarrer un seul conteneur. Une fois démarré, l'accès de l'agent SSH devrait fonctionner parfaitement avec seulement 3 lignes supplémentaires dans votre Dockerfile - plus besoin d'exposer vos clés au conteneur.

Quelques mises en garde : vous avez besoin de Docker >= 1.8, et cela ne fonctionnera pas sur une version automatisée Docker Hub (évidemment). Veuillez également lire la note sur la sécurité! N'hésitez pas à soulever des problèmes dans le référentiel sshagent github auquel je suis lié dans le message si vous rencontrez des problèmes.

J'ai également résolu ce problème de la même manière que @aidanhs - en extrayant le secret requis sur le sous-réseau docker local, puis en le supprimant avant que l'instantané du système de fichiers ne se produise. Un conteneur en cours d'exécution sert le secret, qui est découvert par le client à l'aide de la diffusion UDP.
https://github.com/mdsol/docker-ssh-exec

Y a-t-il eu des progrès pour rendre cela possible? Je ne parviens pas à lier le répertoire ~/.ssh l'hôte car les autorisations et la propriété sont perturbées.

Cela ne pourrait-il pas être résolu en autorisant les montages de liaison à forcer des uid/gid et des autorisations spécifiques ?

@atrauzzi bind-mounts ne peut pas forcer uid/gid/permissions.
Peut le faire via FUSE (par exemple bindfs), mais pas avec des montages de liaison normaux.

@ cpuguy83 Cela commence vraiment à me conduire sur des routes avec

N'y a-t-il pas d'option conviviale ici ? J'ai l'impression qu'il y a un problème ici qui vient d'être reporté.

@atrauzzi En effet, ce n'est pas un problème facile à résoudre dans l'immédiat (pas de manière transparente en tout cas).

+1 c'est un gros bloqueur pour une application Dockerfile Node.js par ailleurs simple. J'ai travaillé sur de nombreuses applications Node et j'en ai rarement vu une qui n'avait pas de référentiel Github privé en tant que dépendance NPM.

Comme solution de contournement @apeace , vous pouvez essayer de les ajouter en tant que sous-modules git à votre référentiel git. De cette façon, ils sont dans le contexte et vous pouvez simplement les ajouter pendant la construction et si vous voulez être vraiment propre, supprimez ou ignorez le fichier .git dans chacun d'eux. Dans la version docker, ils peuvent simplement être installés à l'aide du répertoire local. S'ils doivent être des dépôts git à part entière pour une raison quelconque, assurez-vous que le fichier .git n'est pas présent dans la construction du docker et ajoutez .git/modules/<repo> tant que <path>/<repo>/.git . Cela garantira qu'ils sont des dépôts normaux comme s'ils étaient clonés.

Merci pour cette suggestion @jakirkham , mais nous utilisons des dépôts privés comme dépendance NPM depuis si longtemps, je ne veux pas casser le flux npm install travail normal

Pour l'instant, nous avons une solution qui fonctionne mais qui est tout simplement dégueulasse. On a:

  • Création d'un utilisateur et d'une équipe Github qui a un accès en lecture seule aux dépôts que nous utilisons comme dépendances NPM
  • Engagé la clé privée de cet utilisateur dans notre référentiel où nous avons notre Dockerfile
  • Dans le Dockerfile, au lieu de RUN npm install nous faisons RUN GIT_SSH='/code/.docker/git_ssh.sh' npm install

git_ssh.sh est un script comme celui-ci :

#!/bin/sh
ssh -o StrictHostKeyChecking=no -i /code/.docker/deploy_rsa "$@"

Cela fonctionne, mais la transmission de l'agent de clé ssh serait tellement plus agréable et beaucoup moins de travail de configuration !

:+1:
Je ne peux pas croire que cette demande de fonctionnalité n'est toujours pas implémentée car il y a beaucoup de cas d'utilisation où les gens ont besoin d'accéder à partir de dépôts privés pendant la construction.

J'essaie de créer des conteneurs pour divers environnements de développement de systèmes intégrés, qui nécessitent l'accès à des référentiels privés. L'ajout de la prise en charge des clés ssh de l'hôte serait une excellente fonctionnalité. Les méthodes les plus populaires volant sur SO et d'autres pages ne sont pas sécurisées et tant qu'il n'y aura pas de prise en charge de cette fonctionnalité, les couches avec des clés privées se répandront.

:+1:

:+1: J'en ai besoin depuis toujours.

Salut @apeace , je ne sais pas si vous l'avez vu, mais j'ai commenté plus tôt notre solution de contournement à ce problème.

C'est une combinaison d'un script et d'un serveur Web. Qu'en pensez-vous https://github.com/dockito/vault ?

@pirelenito ne

@apeace le ONVAULT télécharge les clés, exécutez votre commande, puis supprime immédiatement les clés. Comme tout se passe dans la même commande, la couche finale ne contiendra pas la clé.

@apeace Chez Medidata, nous utilisons un petit outil que nous avons construit appelé docker-ssh-exec . Il ne laisse que le binaire docker-ssh-exec dans l'image de construction résultante - pas de secrets. Et cela ne nécessite qu'une modification d'un mot pour le Dockerfile , donc c'est très "à faible encombrement".

Mais si vous avez _vraiment_ besoin d'utiliser une solution uniquement native pour docker, il existe désormais un moyen intégré de le faire, comme indiqué dans le billet de blog de l' --build-arg pour transmettre des valeurs éphémères au processus de génération. Vous devriez pouvoir transmettre une clé SSH privée en tant que ARG , l'écrire dans le système de fichiers, effectuer un git checkout , puis _supprimer_ la clé, le tout dans le cadre d'un RUN directive. (c'est ce que fait le client docker-ssh-exec ). Cela fera un Dockerfile moche, mais ne devrait nécessiter aucun outillage externe.

J'espère que cela t'aides.

@benton Nous avons trouvé une solution similaire. :)

Merci @pirelenito et @benton , je vais vérifier toutes vos suggestions !

EDIT : ce qui suit n'est _PAS_ sécurisé, en fait :

Pour mémoire, voici comment extraire un dépôt privé de Github sans laisser votre clé SSH dans l'image résultante.

Tout d'abord, remplacez user/repo-name dans le Dockerfile par le chemin d'accès à votre dépôt privé (assurez-vous de conserver le préfixe [email protected] afin que ssh soit utilisé pour le paiement) :

FROM ubuntu:latest

ARG SSH_KEY
ENV MY_REPO [email protected]:user/repo-name.git

RUN apt-get update && apt-get -y install openssh-client git-core &&\
    mkdir -p /root/.ssh && chmod 0700 /root/.ssh && \
    ssh-keyscan github.com >/root/.ssh/known_hosts

RUN echo "$SSH_KEY" >/root/.ssh/id_rsa &&\
    chmod 0600 /root/.ssh/id_rsa &&\
    git clone "${MY_REPO}" &&\
    rm -f /root/.ssh/id_rsa

Ensuite, construisez avec la commande

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

en passant le chemin correct à votre clé SSH privée.

^ avec Docker 1.9

@benton Vous voudrez peut-être examiner de près la sortie de docker inspect sshtest et docker history sshtest . Je pense que vous constaterez que les métadonnées de l'image finale ont votre secret même si elles ne sont pas disponibles dans le contexte du conteneur lui-même...

@ljrittle Bon repérage. La clé est bien là si vous utilisez un VAR . Je suppose qu'une solution de contournement externe est toujours nécessaire ici.

Peut-être que l'une des raisons pour lesquelles une solution native n'a pas encore été développée est que plusieurs solutions de contournement sont en place. Mais je suis d'accord avec la plupart des autres ici qu'une solution intégrée servirait mieux les utilisateurs et correspondrait à la philosophie "batteries incluses" de Docker.

De la doc...

Remarque : il n'est pas recommandé d'utiliser des variables de génération pour transmettre des secrets tels que des clés github, des informations d'identification d'utilisateur, etc.

( https://docs.docker.com/engine/reference/builder/#arg )

Je ne pense pas qu'un chemin d'accès à un fichier s'applique à cela, la note concerne le fait de laisser un mot de passe / jeton clairement visible dans le journal de votre console.

Je ne suis pas @jcrombez. L'exemple consistait à passer la clé ssh en tant que variable via ARG . Donc, ça s'applique.

En terme de risque de sécurité c'est très différent :

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

que ça :

docker build --tag=sshtest --build-arg SSH_KEY="mykeyisthis" .

si quelqu'un trouve votre journal de terminal, les conséquences ne sont pas les mêmes.
mais je ne suis pas un expert en sécurité, cela peut toujours être dangereux pour d'autres raisons que je ne connais pas.

Sur la ligne de commande, je suppose.

Cependant, comme @ljrittle l'a souligné et @benton l'a concédé, toute manière que vous utilisez --build-arg / ARG sera validée dans la construction. Donc, l'inspecter révélera des informations sur la clé. Les deux laissent l'état dans le conteneur docker final et souffrent tous deux de la même vulnérabilité à cette extrémité. Par conséquent, pourquoi docker recommande de ne pas le faire.

_SONDAGE UTILISATEUR_

_La meilleure façon d'être informé des mises à jour est d'utiliser le bouton _S'abonner_ sur cette page._

Veuillez ne pas utiliser de commentaires « +1 » ou « J'ai ça aussi » sur les problèmes. Nous automatiquement
recueillir ces commentaires pour garder le fil court.

Les personnes répertoriées ci-dessous ont voté pour ce problème en laissant un commentaire +1 :

@fletcher91
@benlemasurier
@dmuso
@probepark
@saada
@ianAndrewClark
@jakirkham
@galindro
@luisguilherme
@akurkin
@allardhoeve
@SevaUA
@sankethkatta
@kouk
@cliffxuan
@kotlas92
@taion

_SONDAGE UTILISATEUR_

_La meilleure façon d'être informé des mises à jour est d'utiliser le bouton _S'abonner_ sur cette page._

Veuillez ne pas utiliser de commentaires « +1 » ou « J'ai ça aussi » sur les problèmes. Nous automatiquement
recueillir ces commentaires pour garder le fil court.

Les personnes répertoriées ci-dessous ont voté pour ce problème en laissant un commentaire +1 :

@parknicker
@dursk
@adambiggs

En terme de risque de sécurité c'est très différent :

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

à part votre historique de bash, ils sont exactement les mêmes ; il y a beaucoup d'endroits où cette information peut se retrouver.

Par exemple, considérez que les requêtes API peuvent être enregistrées sur le serveur ;

Voici un journal de démon pour docker build --tag=sshtest --build-arg SSH_KEY="fooobar" .

DEBU[0090] Calling POST /v1.22/build
DEBU[0090] POST /v1.22/build?buildargs=%7B%22SSH_KEY%22%3A%22fooobar%22%7D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&memory=0&memswap=0&rm=1&shmsize=0&t=sshtest&ulimits=null
DEBU[0090] [BUILDER] Cache miss: &{[/bin/sh -c #(nop) ARG SSH_KEY]}
DEBU[0090] container mounted via layerStore: /var/lib/docker/aufs/mnt/de3530a82a1a141d77c445959e4780a7e1f36ee65de3bf9e2994611513790b8c
DEBU[0090] container mounted via layerStore: /var/lib/docker/aufs/mnt/de3530a82a1a141d77c445959e4780a7e1f36ee65de3bf9e2994611513790b8c
DEBU[0090] Skipping excluded path: .wh..wh.aufs
DEBU[0090] Skipping excluded path: .wh..wh.orph
DEBU[0090] Applied tar sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef to 91f79150f57d6945351b21c9d5519809e2d1584fd6e29a75349b5f1fe257777e, size: 0
INFO[0090] Layer sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef cleaned up

_SONDAGE UTILISATEUR_

_La meilleure façon d'être informé des mises à jour est d'utiliser le bouton _S'abonner_ sur cette page._

Veuillez ne pas utiliser de commentaires « +1 » ou « J'ai ça aussi » sur les problèmes. Nous automatiquement
recueillir ces commentaires pour garder le fil court.

Les personnes répertoriées ci-dessous ont voté pour ce problème en laissant un commentaire +1 :

@cj2

J'essaie de conteneuriser une simple application ruby/rack. Le Gemfile fait référence à plusieurs gemmes privées. Au moment où bundle install démarre et essaie d'accéder aux dépôts privés, je commence à recevoir cette erreur

Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

J'ai pu le contourner, mais pas sans exposer ma clé privée. Cela ne fera pas. Veuillez activer le transfert d'authentification ssh.

+1 pour le transfert ssh pendant les builds. Impossible d'utiliser go get avec des dépôts privés à cause de cela ;(

+1 pour activer ce cas d'utilisation de manière sécurisée

_SONDAGE UTILISATEUR_

_La meilleure façon d'être informé des mises à jour est d'utiliser le bouton _S'abonner_ sur cette page._

Veuillez ne pas utiliser de commentaires « +1 » ou « J'ai ça aussi » sur les problèmes. Nous automatiquement
recueillir ces commentaires pour garder le fil court.

Les personnes répertoriées ci-dessous ont voté pour ce problème en laissant un commentaire +1 :

@lukad

Juste en lisant cette discussion très intéressante, je me demande si une solution simple pourrait résoudre ces problèmes. Du haut de ma tête, je pense, une option dans le Dockerfile pour simplement pouvoir exclure/ignorer des répertoires/fichiers internes spécifiques lors de la prise d'instantanés. À quel point cela pourrait-il être difficile?

c'est à dire

EXCLURE .ssh

Je pense que cela s'appliquerait à toutes les étapes qui suivent, donc si vous le placez après FROM, vous pouvez ajouter vos clés autant que vous le souhaitez et construire comme d'habitude et ne jamais avoir à vous soucier des clés qui se retrouvent accidentellement dans votre image (accordé vous devrez peut-être les ajouter à chaque étape qui les nécessite, mais vous n'aurez pas à vous soucier qu'ils se retrouvent dans une image)

La suggestion de @benton fonctionne bien et le démon docker ne consignera la clé id_rsa que s'il est en mode débogage.

Une façon encore plus mignonne d'exposer votre clé pendant la construction est :

# Dockerfile
ARG SSH_KEY
RUN eval `ssh-agent -s` > /dev/null \
    && echo "$SSH_KEY" | ssh-add - \
    && git clone [email protected]:private/repository.git

docker build -t my_tag --build-arg SSH_KEY="$(< ~/.ssh/id_rsa)" .

Ha, bien qu'il soit en effet juste assis là si vous regardez docker inspect my_tag .. donc pas sûr de la valeur réelle de boot-arg, à part être légèrement plus ordonné que ENV.

Et, si vous avez un mot de passe sur la clé id_rsa, je suppose que vous pourriez être un mauvais humain et faire :

# Dockerfile
ARG SSH_KEY
ARG SSH_PASS
RUN eval `ssh-agent -s` > /dev/null \
    && echo "echo $SSH_PASS" > /tmp/echo_ps && chmod 700 /tmp/echo_ps \
    && echo "$SSH_KEY" | SSH_ASKPASS=/tmp/echo_ps DISPLAY= ssh-add - \
    && git clone [email protected]:private/repository.git
    && rm /tmp/echo_ps

docker build -t my_tag --build-arg SSH_KEY="$(< ~/.ssh/id_rsa)" --build-arg SSH_PASS=<bad_idea> .

Il est, bien sûr, difficile de rationaliser que ce soit, même de loin, une bonne idée… mais nous sommes tous humains, je suppose.

Certes, toutes les principales raisons de le faire semblent être pour les personnes qui effectuent une « installation groupée » ou « allez chercher » contre des référentiels privés pendant une construction.

Je dirais simplement que vous vendez vos dépendances et AJOUTEZ l'ensemble du projet.. mais, parfois, les choses doivent être faites maintenant.

@SvenDowideit @thaJeztah Existe-t-il une solution à ce problème ? J'ai essayé de suivre le fil mais entre la fermeture et l'ouverture d'un autre fil et beaucoup d'opinions, je n'ai aucune idée de ce que l'équipe Docker fera ni quand.

Le meilleur, mais a besoin d'être mis en œuvre ?

La construction de Docker utilise ssh-agent dans la construction pour créer un proxy vers le ssh de votre hôte, puis utilisez vos clés sans avoir à les connaître !

Pour tous ceux qui découvrent le proxy ssh-agent : github à la rescousse

L' idée originale de

@yordis Je ne pense pas qu'il y ait une "excellente" solution dans le fil qui soit encore disponible gratuitement.

Ce commentaire de docker/docker-py#980 semble indiquer que si vous copiez vos clés ssh dans le répertoire de clés de votre utilisateur root sur votre système hôte, le démon utilisera ces clés. Je suis cependant novice en la matière, donc quelqu'un d'autre pourra peut-être clarifier.


D'accord, mais pas le meilleur

Passer la clé avec les arguments de construction de docker 1.8.
Mises en garde .

Certainement une mauvaise idée

De nombreuses personnes ont également recommandé ici d'ajouter temporairement la clé au contexte de génération, puis de la supprimer rapidement. Cela semble vraiment dangereux, car si la clé se glisse dans l'un des commits, toute personne utilisant le conteneur peut accéder à cette clé en vérifiant un commit particulier.


Pourquoi cela n'est-il encore allé nulle part ?

Il a besoin d'une proposition de conception, ce problème est _cah_- _luttered_ et les idées ne sont que vagues pour le moment. Les détails de mise en œuvre réels sont perdus dans une brume de "et si nous faisions x" et +1. Pour s'organiser et se déplacer sur cette fonctionnalité indispensable, ceux qui ont des solutions possibles doivent créer un fichier . . .

Proposition de conception

puis référencer ce problème.

J'ai des nouvelles à ce sujet.

À DockerCon la semaine dernière, nous avons été encouragés à poser nos questions les plus difficiles au pavillon « Ask the Experts » de Docker, alors je suis allé discuter avec un ingénieur intelligent et sympathique avec le titre encourageant de Solutions Architect. Je lui ai fait un bref résumé de ce problème, que j'espère avoir bien transmis, car il m'a assuré que cela pouvait être fait avec _only_ docker-compose ! Les détails de ce qu'il proposait impliquaient une version en plusieurs étapes – peut-être pour accumuler les dépendances dans un contexte différent de celui de la version finale de l'application – et semblaient impliquer l'utilisation de volumes de données au moment de la construction.

Malheureusement, je n'ai pas d'expérience avec docker-compose, donc je n'ai pas pu suivre tous les détails, mais il m'a assuré que si je lui écrivais avec le problème exact, il me répondrait avec une solution. J'ai donc écrit ce que j'espère être un e -

Je suis sûr qu'il est très occupé, donc je ne m'attendrais à rien dans l'immédiat, mais je trouve cela encourageant, dans la mesure où il a compris le problème et est prêt à l'attaquer avec uniquement l'ensemble d'outils natif de docker.

@benton J'utilise la configuration suivante de docker-compose.yaml pour faire les choses décrites dans ce sujet :

version: '2'
services:
  serviceName:
     volumes:
      - "${SSH_AUTH_SOCK}:/tmp/ssh-agent"
    environment:
      SSH_AUTH_SOCK: /tmp/ssh-agent

Assurez-vous que ssh-agent a démarré sur la machine hôte et connaît la clé (vous pouvez le vérifier avec la commande ssh-add -L).

Veuillez noter que vous devrez peut-être ajouter

Host *
  StrictHostKeyChecking no

au .ssh/config du conteneur.

Salut @WoZ ! merci pour ta réponse, ça a l'air assez simple donc je vais essayer :)

J'ai une question cependant, comment pouvez-vous l'utiliser avec des versions automatisées dans docker hub? En ce qui me concerne maintenant, il n'y a aucun moyen d'utiliser un fichier de composition là-bas :(

@garcianavalon fonctionne bien, mais ce n'est que pour run , pas pour build . Ne fonctionne pas encore avec Docker pour Mac non plus, bien qu'il soit apparemment sur la liste des choses à faire.

Modifier : https://github.com/docker/for-mac/issues/410

Nous avons proposé 2 autres solutions de contournement pour nos besoins spécifiques :

1) Configurez notre propre miroir de package pour npm, pypi, etc. derrière notre VPN, de cette façon nous n'avons pas besoin de SSH.

2) Toute la machine hôte que nous avons déjà accès aux dépôts privés, nous clonons/téléchargeons donc le package privé localement sur la machine hôte, exécutons l'installation de son package pour le télécharger, puis utilisons -v pour mapper le volume sur docker, puis construisons docker.

Nous utilisons actuellement l'option 2).

En ce qui concerne docker run , docker-ssh-agent-forward semble fournir une solution élégante et fonctionne sur Docker pour Mac/Linux.

Il peut toujours être judicieux de COPIER le fichier known_hosts de l'hôte au lieu de le créer dans le conteneur (moins sécurisé), car ssh-agent ne semble pas transmettre les hôtes connus.

Mais le problème fondamental de l'extraction des dépendances privées lors d'une étape d'exécution de docker est de contourner le cache de construction de docker, ce qui peut être très important en termes de temps de construction.

Une approche pour contourner cette limitation consiste à md5/dater vos déclarations de dépendances de construction (par exemple package.json ), à envoyer le résultat dans une image et à réutiliser la même image si le fichier n'a pas changé. L'utilisation du hachage dans le nom de l'image permettra de mettre en cache plusieurs états. Il devrait également être combiné avec le condensé d'image de pré-installation.

Cela devrait être plus robuste que la solution de @aidanhs pour les serveurs de build, même si je dois encore la tester à grande échelle.

Cela devrait être plus robuste que la solution de @aidanhs pour les serveurs de build, même si je dois encore la tester à grande échelle.

Ma solution spécifique n'a pas fonctionné depuis la 1.9.0 - il s'est avéré que la fonctionnalité introduite dans la 1.8.0 sur laquelle je comptais n'était pas intentionnelle et elle a donc été supprimée.

Bien que le principe de ma solution reste correct (il suffit que vous ayez un serveur DNS sur votre machine que a) votre machine utilise et b) que vous puissiez ajouter des entrées aux emplacements appropriés), je ne peux pas vraiment dire que je serais enthousiaste le recommande plus.

Merci pour l'info supplémentaire @aidanhs !

Quelques mises à jour concernant ma solution proposée : les hachages n'ont pas besoin d'être combinés car le hachage de l'image de base juste après l'ajout du fichier de déclaration des dépendances peut simplement être utilisé. De plus, il est préférable de simplement monter le fichierknown_host en tant que volume, car ssh-agent ne peut de toute façon être utilisé qu'à l'exécution - et plus sûr car il contient une liste de tous les hôtes auxquels vous vous connectez.

J'ai implémenté la solution complète pour node/npm et elle peut être trouvée ici avec une documentation détaillée et des exemples : https://github.com/iheartradio/docker-node

Bien entendu, les principes peuvent être étendus à d'autres frameworks.

Même problème ici, comment construire quelque chose, où ce quelque chose nécessite des informations d'identification SSH afin de vérifier et de générer un certain nombre de projets au moment de la construction, dans un conteneur Docker, sans écrire d'informations d'identification sur l'image ou une image de base.

Nous contournons cela en ayant un processus de construction en 2 étapes. Une image "build" contenant les dépendances source/clés/build est créée. Une fois que cela est construit, il est exécuté afin d'extraire les résultats de la construction dans un fichier tar qui est ensuite ajouté à une image de "déploiement". L'image de build est ensuite supprimée et tout ce qui est publié est l'image "deploy". Cela a pour effet secondaire de réduire la taille des conteneurs/couches.

@binarytemple-bet365 voir https://github.com/iheartradio/docker-node pour un exemple de bout en bout faisant exactement cela. J'utilise plus de deux étapes car j'utilise un conteneur de service ssh, la pré-installation (image de base jusqu'à avant l'installation des dépendances privées), l'installation (état du conteneur après l'installation de l'exécution des dépendances privées) et la post-installation (ajoute les commandes que vous aviez après l'installation des dépendances privées) pour optimiser la vitesse et la séparation des préoccupations.

Découvrez Rocker , c'est une solution propre.

@Sodki j'ai suivi ton conseil. Oui, le rocker est une solution propre et bien pensée. C'est plus dommage que l'équipe de dockers ne prenne pas ce projet sous son aile et ne désapprouve pas docker build . Merci.

Toujours pas de meilleur moyen ? :(

Quelqu'un a-t-il essayé cette nouvelle chose de squash? https://github.com/docker/docker/pull/22641 Peut-être la solution native de docker que nous recherchons. Je vais l'essayer maintenant et faire un rapport pour voir comment ça se passe.

Après plus de 2 ans, ce n'est pas encore résolu 😞 S'il vous plaît, l'équipe Docker fait quelque chose à ce sujet

On dirait que la nouvelle option --squash dans 1.13 fonctionne pour moi :
http://g.recordit.co/oSuMulfelK.gif

Je le construis avec : docker build -t report-server --squash --build-arg SSH_KEY="$(cat ~/.ssh/github_private_key)" .

Donc, quand je fais docker history ou docker inspect , la clé ne s'affiche pas.

Mon Dockerfile ressemble à ceci :

FROM node:6.9.2-alpine

ARG SSH_KEY

RUN apk add --update git openssh-client && rm -rf /tmp/* /var/cache/apk/* &&\
  mkdir -p /root/.ssh && chmod 0700 /root/.ssh && \
  ssh-keyscan github.com > /root/.ssh/known_hosts

RUN echo "$SSH_KEY" > /root/.ssh/id_rsa &&\
  chmod 0600 /root/.ssh/id_rsa

COPY package.json .

RUN npm install
RUN rm -f /root/.ssh/id_rsa

# Bundle app source
COPY . .

EXPOSE 3000

CMD ["npm","start"]

@kienpham2000 , votre capture d'écran semble contenir toujours les clés - pourriez-vous s'il vous plaît vérifier la sortie de docker history avec le drapeau --no-trunc et rapporter ici si les clés privées sont affichées ou non dans docker l'histoire?

@ryanschwartz tu as raison, le --no-trunc montre tout, ça ne vole pas.

@kienpham2000
Une autre chose qu'ils ont introduite dans la version 1.13 est :

Construire des secrets
• active les secrets de temps de construction à l'aide de l'indicateur —build-secret
• crée des tmpfs pendant la construction et expose les secrets au
conteneurs de construction, à utiliser pendant la construction.
https://github.com/docker/docker/pull/28079

Peut-être que cela pourrait fonctionner ?

Les secrets de construction n'ont pas été intégrés à la 1.13, mais, espérons-le, le feront à la 1.14.

Le 15 décembre 2016 à 9h45, "Alex" [email protected] a écrit :

@kienpham2000 https://github.com/kienpham2000
Une autre chose qu'ils ont introduite dans la version 1.13 est :

Construire des secrets
• active les secrets de temps de construction à l'aide de l'indicateur —build-secret
• crée des tmpfs pendant la construction et expose les secrets au
conteneurs de construction, à utiliser pendant la construction.
• #28079 https://github.com/docker/docker/pull/28079

Peut-être que cela pourrait fonctionner ?

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/6396#issuecomment-267393020 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAdcPDxrctBP2TlCtXen-Y_uY8Y8B09Sks5rIXy2gaJpZM4CD4SM
.

Donc un an plus tard : Non, c'est une mauvaise idée. Vous NE DEVRIEZ PAS faire ça. Il existe diverses autres solutions. Par exemple, Github peut fournir des jetons d'accès. Vous pouvez les utiliser dans des fichiers de configuration/variables d'environnement avec moins de risques car vous pouvez spécifier les actions autorisées pour chaque jeton.

La solution consiste à implémenter le transfert SSH. Comme Vagrant le fait par exemple.

Quelqu'un peut-il m'expliquer pourquoi est-ce si compliqué de mettre cela en œuvre ?

@omarabid -

Quant à votre suggestion d'utiliser des jetons d'accès, ils finiraient par être stockés dans une couche et peuvent être tout aussi dangereux à laisser traîner qu'une clé SSH. Même s'il n'a qu'un accès en lecture seule, la plupart des gens ne voudraient pas que les autres aient un accès en lecture seule à leurs dépôts. De plus, des révocations/rotations/distributions fréquentes devraient avoir lieu ; c'est un peu plus facile à gérer pour chaque développeur, etc. plutôt qu'avec des jetons d'accès "maîtres".

La solution des secrets de construction mentionnée quelques commentaires en arrière semble être un pas dans la bonne direction, mais la possibilité d'utiliser un agent SSH est la meilleure. Peut-être qu'on pourrait utiliser un agent SSH en combinaison avec des secrets de construction, je ne suis pas sûr.

Il est naturel pour les développeurs/systèmes CI d'utiliser un agent SSH pendant les opérations git/build. C'est beaucoup plus sûr que d'avoir une clé privée sans mot de passe en clair qui doit être révoquée/remplacée en masse sur une variété de systèmes. De plus, avec les agents SSH, il n'y a aucune possibilité que les données de la clé privée soient affectées à une image. Au pire, une variable d'environnement/un reste SSH_AUTH_SOCK sera laissé dans l'image.

J'ai obtenu cette dernière solution de contournement sans afficher le contenu de la clé secrète ou utiliser un outil docker tiers supplémentaire (espérons que le coffre-fort secret lors de la construction des relations publiques sera bientôt fusionné).

J'utilise aws cli pour télécharger la clé privée partagée de S3 dans le référentiel actuel de l'hôte. Cette clé est chiffrée au repos à l'aide de KMS. Une fois la clé téléchargée, Dockerfile va simplement COPIER cette clé pendant le processus de construction et la supprimer par la suite, le contenu ne s'affiche pas à docker inspect ou docker history --no-trunc

Téléchargez d'abord la clé privée github de S3 sur la machine hôte :

# build.sh
s3_key="s3://my-company/shared-github-private-key"
aws configure set s3.signature_version s3v4
aws s3 cp $s3_key id_rsa --region us-west-2 && chmod 0600 id_rsa

docker build -t app_name .

Dockerfile ressemble à ceci :

FROM node:6.9.2-alpine

ENV id_rsa /root/.ssh/id_rsa
ENV app_dir /usr/src/app

RUN mkdir -p $app_dir
RUN apk add --update git openssh-client && rm -rf /tmp/* /var/cache/apk/* && mkdir -p /root/.ssh && ssh-keyscan github.com > /root/.ssh/known_hosts

WORKDIR $app_dir

COPY package.json .
COPY id_rsa $id_rsa
RUN npm install && npm install -g gulp && rm -rf $id_rsa

COPY . $app_dir
RUN rm -rf $app_dir/id_rsa

CMD ["start"]

ENTRYPOINT ["npm"]

@kienpham2000 , pourquoi cette solution ne conserverait-elle pas la clé dans la couche d'image ? Les actions de copie et de suppression de la clé sont effectuées dans des commandes séparées, il y a donc une couche qui devrait avoir la clé.
Notre équipe utilisait la vôtre jusqu'à hier, mais nous découvrons une solution améliorée :

  • Nous générons une URL de pré-signature pour accéder à la clé avec aws s3 cli, et limitons l'accès à environ 5 minutes, nous enregistrons cette URL de pré-signature dans un fichier dans le répertoire repo, puis dans dockerfile nous l'ajoutons à l'image.
  • Dans dockerfile, nous avons une commande RUN qui effectue toutes ces étapes : utilisez l'URL de pré-sing pour obtenir la clé ssh, exécutez npm install et supprimez la clé ssh.
    En faisant cela en une seule commande, la clé ssh ne serait stockée dans aucune couche, mais l'URL de pré-signature sera stockée, et ce n'est pas un problème car l'URL ne sera pas valide après 5 minutes.

Le script de construction ressemble à :

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Dockerfile ressemble à ceci :

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no [email protected] || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

@diegocsandrim merci de l'avoir signalé, j'aime vraiment votre solution, je vais mettre à jour nos trucs ici. Merci d'avoir partagé!

Je suis un peu nouveau sur le fil, mais fondamentalement, il semble que les gens essaient de résoudre un problème mieux résolu par PKI. Tout le monde n'essaie pas nécessairement de sauver le même problème où PKI serait la meilleure solution, mais suffisamment de références semblent indiquer que cela pourrait être quelque chose qui devrait être pris en compte.

Cela semble ennuyeux, mais fondamentalement possible de

  • créer une autorité de certification locale
  • avoir un processus pour générer un cert
  • avoir un processus pour délivrer le cert
  • avoir un processus pour révoquer ledit cert
  • faire en sorte que les démons ssh utilisent PKI

Et si les gens pensent que c'est faisable, alors s'il vous plaît, créez-le et ouvrez-le en source, après tout, le travail doit être fait une fois bien. Je n'ai aucune idée si la construction de roumen petrov est sécurisée et n'a noté aucun code source (je n'ai pas vérifié le tar), donc je n'ai aucune idée de sa sécurité.

https://security.stackexchange.com/questions/30396/how-to-set-up-openssh-to-use-x509-pki-for-authentication

https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html

@mehmetcodes : Avoir une PKI ne résout pas vraiment le problème. Pour que l'authentification SSH basée sur PKI fonctionne, vous devrez toujours charger la clé privée dans l'image.

À moins que votre autorité de certification locale ne délivre des certificats de très courte durée (par exemple moins d'une heure) et que vous révoquez le certificat immédiatement après une génération réussie, cela n'est pas sûr.

Si vous parvenez à créer un processus de certificat de courte durée, ce n'est pas très différent de la simple utilisation d'une nouvelle clé SSH que vous révoquez immédiatement après la fin d'une génération.

Oh c'est encore plus ennuyeux que ça, mais je dois être sur quelque chose ou pourquoi existerait-il dans la nature ?

https://blog.cloudflare.com/red-october-cloudflares-open-source-implementation-of-the-two-man-rule/
https://blog.cloudflare.com/how-to-build-your-own-public-key-infrastructure/

Je ne sais pas, une clé temporaire SSH est probablement bien meilleure pour la plupart des cas d'utilisation, mais il y a quelque chose de troublant dans chaque recours, y compris celui que j'ai suggéré, en particulier dans ce contexte.

Vous ne feriez normalement que monter un volume avec la clé, mais cela ne résout pas le besoin de la solution docker pour Mac / moby.

c'est qui moby ?

@couleur blanche
Image of Moby

J'en ai jusqu'ici sur MacOS :

bash-3.2$ docker run -t -i -v "$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" python:3.6 ssh-add -l
docker: Error response from daemon: Mounts denied:
The path /var/folders/yb/880w03m501z89p0bx7nsxt580000gn/T//ssh-DcwJrLqQ0Vu1/agent.10466
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
.

/var/ est un alias avec lequel Docker semble avoir du mal. Mais si je préfixe le chemin $SSH_AUTH_SOCK avec /private (c'est-à-dire le chemin d'alias résolu), alors Docker peut lire le fichier, mais j'obtiens :

bash-3.2$ docker run -t -i -v "/private$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" python:3.6 ssh-add -l
Could not open a connection to your authentication agent.

À ce stade, je me demande à quel point c'est mal de juste…

docker run -v ~/.ssh:/root/.ssh python:3.6 bash

?

docker build  --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa_no_pass)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .

Et puis dans le fichier Docker :

ARG ssh_prv_key
ARG ssh_pub_key

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
    chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa.pub

Et n'oubliez pas d'inclure

RUN rm -f /root/.ssh/id_rsa /root/.ssh/id_rsa.pub

comme étape finale.

Le hic ici est que votre clé privée ne doit pas être protégée par un mot de passe.

Le problème avec le commentaire précédent est que les clés se retrouvent dans les calques... rm ne sera pas supprimé d'un calque précédent, car chaque ligne d'un fichier docker correspond à un calque.

docker secret résout-il pas ce problème ?
WDYT @thaJeztah

docker secret n'est pas (encore) disponible lors de la construction, et uniquement disponible dans les services (donc pas encore pour docker run )

Lorsque vous utilisez des versions en plusieurs étapes, quelque chose comme celui-ci pourrait fonctionner (en tapant sur mon téléphone, laissez-moi donc lier un élément que j'ai créé il y a quelque temps); https://gist.github.com/thaJeztah/836c4220ec024cf6dd48ffa850f07770

Je ne suis plus impliqué dans Docker, mais comment est-il possible que ce problème existe depuis si longtemps. Je n'essaie pas d'appeler, mais plutôt de comprendre quels sont les efforts nécessaires pour résoudre ce problème, car à l'époque où je m'occupais de cela, cela semblait un problème vraiment très courant pour toute entreprise qui extrait des packages privés comme ruby gems d'un dépôt privé.

Le Moby soucie-t-il de ce problème ? Pourquoi ça doit être si difficile pour quelque chose qui ne semble pas si grave, je suppose.

Cela fait presque 3 ans 😢

@yordis docker builder a été gelé pendant un an ou deux. L'équipe Docker a déclaré que le constructeur est assez bon et qu'ils concentrent leurs efforts ailleurs. Mais cela a disparu et il y a eu deux changements dans le constructeur depuis. Constructions de scènes de courges et de mustli. Ainsi, des secrets de construction peuvent être en route.

Pour le transfert d'exécution de ssh-agent, je recommanderais https://github.com/uber-common/docker-ssh-agent-forward

Pourquoi ça doit être si difficile pour quelque chose qui ne semble pas si grave, je suppose.

@yordis lisant la description supérieure de ce problème, la mise en œuvre est loin d'être triviale; Cela dit, si quelqu'un a une proposition de conception technique pour cela, n'hésitez pas à ouvrir un problème ou un PR pour discussion. Notez également que pour la partie _build_, un projet buildkit a été lancé pour les futures améliorations du constructeur ; https://github.com/moby/buildkit

@thaJeztah J'aimerais pouvoir avoir les compétences requises mais ce n'est pas le cas.

@villlem connaissez-vous une feuille de route de l'équipe Docker ?

Les rapports hebdomadaires pour le constructeur peuvent être trouvés ici; https://github.com/moby/moby/tree/master/reports/builder build time secrets est toujours répertorié dans le dernier rapport, mais pourrait utiliser de l'aide

Nous utilisons la solution de

Cette étape supplémentaire signifie que la clé ne peut pas être récupérée à partir de l'image Docker (l'URL pour la télécharger expire après cinq minutes) et ne peut pas être récupérée à partir d'AWS (car elle est chiffrée avec un mot de passe rotatif connu uniquement de l'image docker) .

Dans build.sh :

BUCKET_NAME=my_bucket
KEY_FILE=my_unencrypted_key
openssl rand -base64 -out passfile 64
openssl enc -aes-256-cbc -salt -in $KEY_FILE -kfile passfile | aws s3 cp - s3://$BUCKET_NAME/$(hostname).enc_key
aws s3 presign s3://$BUCKET_NAME/$(hostname).enc_key --expires-in 300 > ./pre_sign_url
docker build -t my_service

Et dans le Dockerfile :

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - | openssl enc -aes-256-cbc -d -kfile passfile > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    mkdir /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts && \
    [commands that require SSH access to Github] && \
    rm ./my_key && \
    rm ./passfile && \
    rm -rf /root/.ssh/

si vous utilisez docker run vous devez monter votre .ssh avec --mount type=bind,source="${HOME}/.ssh/",target="/root/.ssh/",readonly . La lecture seule est la magie, elle masque les autorisations normales et ssh voit essentiellement les autorisations 0600 dont il est satisfait. Vous pouvez également jouer avec -u root:$(id -u $USER) pour que l'utilisateur root dans le conteneur écrive tous les fichiers qu'il crée avec le même groupe que votre utilisateur, donc j'espère que vous pourrez au moins les lire sinon les écrire complètement sans avoir à chmod/chown .

Enfin.

Je pense que ce problème peut maintenant être résolu en utilisant seulement docker build , en utilisant des builds en plusieurs étapes .
Juste COPY ou ADD la clé SSH ou un autre secret partout où vous en avez besoin, et utilisez-la dans les instructions RUN comme bon vous semble.

Ensuite, utilisez une deuxième instruction FROM pour démarrer un nouveau système de fichiers, et COPY --from=builder pour importer un sous-ensemble de répertoires qui n'incluent pas le secret .

(Je n'ai pas encore essayé cela, mais si la fonctionnalité fonctionne comme décrit...)

Les constructions en plusieurs étapes

J'ai vérifié la technique suivante :

  1. Transmettez l'_emplacement d'une clé privée_ en tant qu'argument de génération, tel que GITHUB_SSH_KEY , à la première étape d'une génération à plusieurs étapes
  2. Utilisez ADD ou COPY pour écrire la clé là où elle est nécessaire pour l'authentification. Notez que si l'emplacement de la clé est un chemin d'accès au système de fichiers local (et non une URL), il ne doit _pas_ se trouver dans le fichier .dockerignore , sinon la directive COPY ne fonctionnera pas. Cela a des implications pour l'image finale, comme vous le verrez à l'étape 4...
  3. Utilisez la clé au besoin. Dans l'exemple ci-dessous, la clé est utilisée pour s'authentifier auprès de GitHub. Cela fonctionne également pour les bundler de Ruby et les dépôts Gem privés. Selon la quantité de code que vous devez inclure à ce stade, vous pouvez finir par ajouter à nouveau la clé comme effet secondaire de l'utilisation de COPY . ou ADD . .
  4. RETIREZ LA CLÉ SI NÉCESSAIRE . Si l'emplacement de la clé est un chemin d'accès au système de fichiers local (et non une URL), il est probable qu'il a été ajouté à côté de la base de code lorsque vous avez fait ADD . ou COPY . C'est probablement _précisément le répertoire_ qui est va être copié dans l'image d'exécution finale, donc vous voudrez probablement aussi inclure une instruction RUN rm -vf ${GITHUB_SSH_KEY} une fois que vous avez fini d'utiliser la clé.
  5. Une fois que votre application est complètement intégrée dans son WORKDIR , démarrez la deuxième étape de construction avec une nouvelle instruction FROM , indiquant l'image d'exécution souhaitée. Installez toutes les dépendances d'exécution nécessaires, puis COPY --from=builder contre les WORKDIR de la première étape.

Voici un exemple Dockerfile qui démontre la technique ci-dessus. Fournir un argument de construction GITHUB_SSH_KEY testera l'authentification GitHub lors de la construction, mais les données clés ne seront _pas_ incluses dans l'image d'exécution finale. Le GITHUB_SSH_KEY peut être un chemin de système de fichiers (dans le répertoire de construction Docker) ou une URL qui sert les données de clé, mais la clé elle-même ne doit pas être chiffrée dans cet exemple.

########################################################################
# BUILD STAGE 1 - Start with the same image that will be used at runtime
FROM ubuntu:latest as builder

# ssh is used to test GitHub access
RUN apt-get update && apt-get -y install ssh

# The GITHUB_SSH_KEY Build Argument must be a path or URL
# If it's a path, it MUST be in the docker build dir, and NOT in .dockerignore!
ARG GITHUB_SSH_KEY=/path/to/.ssh/key

  # Set up root user SSH access for GitHub
ADD ${GITHUB_SSH_KEY} /root/.ssh/id_rsa

# Add the full application codebase dir, minus the .dockerignore contents...
# WARNING! - if the GITHUB_SSH_KEY is a file and not a URL, it will be added!
COPY . /app
WORKDIR /app

# Build app dependencies that require SSH access here (bundle install, etc.)
# Test SSH access (this returns false even when successful, but prints results)
RUN ssh -o StrictHostKeyChecking=no -vT [email protected] 2>&1 | grep -i auth

# Finally, remove the $GITHUB_SSH_KEY if it was a file, so it's not in /app!
# It can also be removed from /root/.ssh/id_rsa, but you're probably not going
# to COPY that directory into the runtime image.
RUN rm -vf ${GITHUB_SSH_KEY} /root/.ssh/id*

########################################################################
# BUILD STAGE 2 - copy the compiled app dir into a fresh runtime image
FROM ubuntu:latest as runtime
COPY --from=builder /app /app

Il _pourrait_ être plus sûr de transmettre les données clés elles-mêmes dans l'argument de construction GITHUB_SSH_KEY , plutôt que l'_emplacement_ des données clés. Cela empêcherait l'inclusion accidentelle des données clés si elles sont stockées dans un fichier local, puis ajoutées avec COPY . . Cependant, cela nécessiterait l'utilisation de echo et la redirection du shell pour écrire les données dans le système de fichiers, ce qui pourrait ne pas fonctionner dans toutes les images de base. Utilisez la technique la plus sûre et la plus réalisable pour votre ensemble d'images de base.

@jbiel Une autre année, et la solution que j'ai trouvée est d'utiliser quelque chose comme Vault.

Voici un lien avec 2 méthodes (courge et conteneur intermédiaire décrit précédemment par @benton)

J'ajoute juste une note pour dire qu'aucune des approches actuelles ne fonctionnera si vous avez une phrase secrète sur la clé ssh que vous utilisez, car l'agent vous demandera la phrase secrète chaque fois que vous effectuerez l'action qui nécessite un accès. Je ne pense pas qu'il y ait un moyen de contourner cela sans passer la phrase clé (ce qui est indésirable pour un certain nombre de raisons)

Résoudre.
Créez un script bash (~/bin/docker-compose ou similaire):

#!/bin/bash

trap 'kill $(jobs -p)' EXIT
socat TCP-LISTEN:56789,reuseaddr,fork UNIX-CLIENT:${SSH_AUTH_SOCK} &

/usr/bin/docker-compose $@

Et dans Dockerfile en utilisant socat :

...
ENV SSH_AUTH_SOCK /tmp/auth.sock
...
  && apk add --no-cache socat openssh \
  && /bin/sh -c "socat -v UNIX-LISTEN:${SSH_AUTH_SOCK},unlink-early,mode=777,fork TCP:172.22.1.11:56789 &> /dev/null &" \
  && bundle install \
...
or any other ssh commands will works

Ensuite, exécutez docker-compose build

@benton pourquoi tu utilises RUN rm -vf ${GITHUB_SSH_KEY} /root/.ssh/id* ? Ne devrait-il pas s'agir de RUN rm -vf /root/.ssh/id* ? Ou peut-être que j'ai mal compris l'intention ici.

@benton Et aussi ce n'est pas sûr à faire :

RUN ssh -o StrictHostKeyChecking=no -vT [email protected] 2>&1

Vous devez vérifier l'empreinte digitale

J'ai résolu ce problème de cette façon

ARGS USERNAME
ARGS PASSWORD
RUN git config --global url."https://${USERNAME}:${PASSWORD}@github.com".insteadOf "ssh://[email protected]"

puis construire avec

docker build --build-arg USERNAME=use --build-arg PASSWORD=pwd. -t service

Mais au début, votre serveur git privé doit prendre en charge le dépôt de clone username:password .

Commande @zeayes RUN stockée dans l'historique du conteneur. Ainsi, votre mot de passe est visible par les autres.

Correct; lors de l'utilisation de --build-arg / ARG , ces valeurs apparaîtront dans l'historique de construction. Il _est_ possible d'utiliser cette technique si vous utilisez des builds en plusieurs étapes _et_ faites confiance à l'hôte sur lequel les images sont construites (c'est-à-dire qu'aucun utilisateur non fiable n'a accès à l'historique de build local), _et_ les étapes de build intermédiaires ne sont pas poussées vers un registre.

Par exemple, dans l'exemple suivant, USERNAME et PASSWORD apparaîtront uniquement dans l'historique de la première étape (« constructeur »), mais ne figureront pas dans l'historique de l'étape finale ;

FROM something AS builder
ARG USERNAME
ARG PASSWORD
RUN something that uses $USERNAME and $PASSWORD

FROM something AS finalstage
COPY --from= builder /the/build-artefacts /usr/bin/something

Si seule l'image finale (produite par "finalstage") est poussée vers un registre, alors USERNAME et PASSWORD ne seront pas dans cette image.

_Cependant_, dans l'historique du cache de construction local, ces variables seront toujours là (et stockées sur le disque en texte brut).

Le constructeur de prochaine génération (utilisant BuildKit ) aura plus de fonctionnalités, également liées à la transmission de secrets au moment de la construction ; il est disponible dans Docker 18.06 en tant que fonctionnalité expérimentale, mais sortira de l'expérimentation dans une future version, et d'autres fonctionnalités seront ajoutées (je devrais vérifier si les secrets/les informations d'identification sont déjà possibles dans la version actuelle)

@kinnalru @thaJeztah merci , j'utilise des builds en plusieurs étapes, mais le mot de passe peut être vu dans l'historique du conteneur de cache, merci !

@zeayes Oh ! Je vois que j'ai fait une erreur de copier/coller ; la dernière étape ne doit pas utiliser FROM builder .. . Voici un exemple complet ; https://gist.github.com/thaJeztah/af1c1e3da76d7ad6ce2abab891506e50

Ce commentaire de @kinnalru est la bonne façon de le faire https://github.com/moby/moby/issues/6396#issuecomment -348103398

Avec cette méthode, docker ne gère jamais vos clés privées. Et cela fonctionne également aujourd'hui, sans qu'aucune nouvelle fonctionnalité ne soit ajoutée.

Il m'a fallu un certain temps pour le comprendre, alors voici une explication plus claire et améliorée. J'ai modifié le code @kinnalru pour utiliser --network=host et localhost , vous n'avez donc pas besoin de connaître votre adresse IP. ( essentiel ici )

Il s'agit de docker_with_host_ssh.sh , il encapsule docker et transfère SSH_AUTH_SOCK vers un port sur localhost :

#!/usr/bin/env bash

# ensure the processes get killed when we're done
trap 'kill $(jobs -p)' EXIT

# create a connection from port 56789 to the unix socket SSH_AUTH_SOCK (which is used by ssh-agent)
socat TCP-LISTEN:56789,reuseaddr,fork UNIX-CLIENT:${SSH_AUTH_SOCK} &
# Run docker
# Pass it all the command line args ($@)
# set the network to "host" so docker can talk to localhost
docker $@ --network='host'

Dans le Dockerfile, nous nous connectons via localhost aux hôtes ssh-agent :

FROM python:3-stretch

COPY . /app
WORKDIR /app

RUN mkdir -p /tmp

# install socat and ssh to talk to the host ssh-agent
RUN  apt-get update && apt-get install git socat openssh-client \
  # create variable called SSH_AUTH_SOCK, ssh will use this automatically
  && export SSH_AUTH_SOCK=/tmp/auth.sock \
  # make SSH_AUTH_SOCK useful by connecting it to hosts ssh-agent over localhost:56789
  && /bin/sh -c "socat UNIX-LISTEN:${SSH_AUTH_SOCK},unlink-early,mode=777,fork TCP:localhost:56789 &" \
  # stuff I needed my ssh keys for
  && mkdir -p ~/.ssh \
  && ssh-keyscan gitlab.com > ~/.ssh/known_hosts \
  && pip install -r requirements.txt

Ensuite, vous pouvez construire votre image en appelant le script :

$ docker_with_host_ssh.sh build -f ../docker/Dockerfile .

@cowlicks, vous pourriez être intéressé par cette pull request, qui ajoute la prise en charge de docker build --ssh pour transmettre l'agent SSH pendant la construction ; https://github.com/docker/cli/pull/1419. La syntaxe Dockerfile n'est toujours pas dans les spécifications officielles, mais vous pouvez utiliser une directive syntax=.. dans votre Dockerfile pour utiliser une interface qui la prend en charge (voir l'exemple/les instructions dans la pull request).

Cette pull request fera partie de la prochaine version 18.09.

Il semble que cela soit maintenant disponible dans la version 18.09. Étant donné que ce fil apparaît avant les notes de version et le message moyen, je vais publier ici.

Notes de version:
https://docs.docker.com/develop/develop-images/build_enhancements/#using -ssh-to-access-private-data-in-builds

Message moyen :
https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

Très excitant.

Je pense que nous pouvons fermer ceci parce que nous avons docker build --ssh maintenant

Problème de composition connexe ici : docker/compose#6865. Fonctionnalité pour utiliser Compose et exposer le socket de l'agent SSH aux conteneurs qui devraient atterrir dans la prochaine version candidate, 1.25.0-rc3 ( releases ).

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