web-dev-qa-db-fra.com

Injecter les clés SSH de l'hôte dans Docker Machine avec Docker Compose

J'utilise Docker sur Mac OS X avec Docker Machine (avec la machine boot2docker par défaut) et j'utilise docker-compose pour configurer mon environnement de développement.

Disons que l'un des conteneurs s'appelle "stack". Maintenant, ce que je veux faire, c'est appeler:

docker-composer run stack ssh [email protected]

Ma clé publique (qui a été ajoutée à stackoverflow.com et qui sera utilisée pour m'authentifier) ​​se trouve sur la machine hôte. Je souhaite que cette clé soit disponible dans le conteneur Docker Machine pour que je puisse m'authentifier auprès de stackoverflow en utilisant cette clé à partir du conteneur. De préférence, sans copier physiquement ma clé sur Docker Machine.

Y a-t-il un moyen de faire ça? De plus, si ma clé est protégée par un mot de passe, y a-t-il un moyen de la déverrouiller une fois pour ne pas avoir à saisir manuellement le mot de passe après chaque injection?

15
Ruslan

Vous pouvez ajouter ceci à votre fichier docker-compose.yml (en supposant que votre utilisateur à l'intérieur du conteneur est root):

volumes:
    - ~/.ssh:/root/.ssh

Vous pouvez aussi vérifier une solution plus avancée avec l'agent ssh (je ne l'ai pas essayée moi-même)

32
Anton Serdyuk

Docker a une fonctionnalité appelée secrets, qui peut être utile ici. Pour l'utiliser, vous pouvez ajouter le code suivant à docker-compose.yml:

---
version: '3.1' # Note the minimum file version for this feature to work
services:
  stack:
    ...
    secrets:
      - Host_ssh_key

secrets:
  Host_ssh_key:
    file: ~/.ssh/id_rsa

Ensuite, le nouveau fichier secret peut être consulté dans Dockerfile comme ceci:

RUN mkdir ~/.ssh && ln -s /run/secrets/Host_ssh_key ~/.ssh/id_rsa

Les fichiers secrets ne seront pas copiés dans le conteneur:

Lorsque vous accordez à un service nouvellement créé ou en cours d'accès l'accès à un secret, le secret déchiffré est monté dans le conteneur dans un système de fichiers en mémoire.

Pour plus de détails s'il vous plaît se référer à:

10
Anton Styagun

Vous pouvez transférer l'agent SSH:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent
5
Aistis

Si vous utilisez OS X et des clés cryptées, il s'agira d'un PITA. _ { Voici les étapes } _J'ai passé en revue ceci.

Approche simple

On pourrait penser qu’il n’ya pas de problème. Il suffit de monter votre dossier ssh:

...
volumes:
  - ~/.ssh:/root/.ssh:ro
...

Cela devrait fonctionner, non?

Problème d'utilisateur

La prochaine chose que nous remarquerons est que nous utilisons le mauvais identifiant. Très bien, nous allons écrire un script pour copier et changer le propriétaire des clés ssh. Nous allons également définir ssh user dans config pour que le serveur ssh sache qui se connecte.

...
volumes:
  - ~/.ssh:/root/.ssh-keys:ro
command: sh -c ‘./.ssh-keys.sh && ...’
environment:
  SSH_USER: $USER
...

# ssh-keys.sh
mkdir -p ~/.ssh
cp -r /root/.ssh-keys/* ~/.ssh/
chown -R $(id -u):$(id -g) ~/.ssh

cat <<EOF >> ~/.ssh/config
  User $SSH_USER
EOF

Problème de phrase secrète de clé SSH

Dans notre entreprise, nous protégeons les clés SSH avec une phrase secrète. Cela ne fonctionnerait pas dans docker car il est peu pratique de saisir une phrase secrète à chaque démarrage d’un conteneur .. Nous pourrions supprimer une phrase secrète (voir exemple ci-dessous), mais il existe un problème de sécurité.

openssl rsa -in id_rsa -out id_rsa2
# enter passphrase
# replace passphrase-encrypted key with plaintext key:
mv id_rsa2 id_rsa

Solution d'agent SSH

Vous avez peut-être remarqué qu’au niveau local, vous n’avez pas besoin de saisir de phrase secrète à chaque fois que vous avez besoin d’un accès ssh. Pourquoi cela? C’est l’agent SSH. L'agent SSH est essentiellement un serveur qui écoute un fichier spécial, un socket, appelé «ssh auth sock». Vous pouvez voir son emplacement sur votre système:

echo $SSH_AUTH_SOCK
# /run/user/1000/keyring-AvTfL3/ssh

Le client SSH communique avec l’agent SSH via ce fichier afin que vous ne saisissiez la phrase secrète qu’une seule fois. Une fois qu’il n’a pas été chiffré, l’agent SSH le stockera en mémoire et l’enverra sur demande au client SSH. Peut-on l’utiliser dans Docker? Bien sûr, montez ce fichier spécial et spécifiez une variable d’environnement correspondante:

environment:
  SSH_AUTH_SOCK: $SSH_AUTH_SOCK
  ...
volumes:
  - $SSH_AUTH_SOCK:$SSH_AUTH_SOCK

Dans ce cas, nous n’avons même pas besoin de copier les clés . Pour confirmer que les clés sont disponibles, nous pouvons utiliser l’utilitaire ssh-add:

if [ -z "$SSH_AUTH_SOCK" ]; then
  echo "No ssh agent detected"
else
  echo $SSH_AUTH_SOCK
  ssh-add -l
fi

Le problème de la prise en charge du montage de socket Unix dans Docker pour Mac

Malheureusement pour les utilisateurs d'OS X, Docker pour Mac présente un certain nombre d'inconvénients, notamment son incapacité à partager les sockets Unix entre Mac et Linux. Il y a un numéro ouvert dans Github D4M . En février 2019, il est toujours ouvert.

Alors, est-ce une impasse? Non, il existe une solution de contournement.

Solution de transfert d’agent SSH

Heureusement, ce problème n’est pas nouveau. Bien avant Docker, il existait un moyen d'utiliser les clés ssh locales dans une session ssh distante. Ceci s'appelle le transfert d'agent ssh. L'idée est simple: vous vous connectez à un serveur distant via ssh et vous pouvez utiliser tous les mêmes serveurs distants, partageant ainsi vos clés.

Avec Docker pour Mac, nous pouvons utiliser une astuce intelligente: partager l'agent ssh sur la machine virtuelle docker à l'aide de la connexion TCP ssh et monter ce fichier de la machine virtuelle dans un autre conteneur dans lequel nous avons besoin de la connexion SSH. Voici une photo pour démontrer la solution:

SSH forwarding

Tout d'abord, nous créons une session SSH sur le serveur SSH à l'intérieur d'un conteneur dans un Linux VM via un port TCP. Nous utilisons une vraie chaussette ssh auth ici.

Ensuite, le serveur ssh transmet nos clés ssh à l'agent ssh sur ce conteneur. L'agent SSH dispose d'un socket Unix qui utilise un emplacement monté sur la machine virtuelle Linux. C'est à dire. Le socket Unix fonctionne sous Linux. Le fichier de socket Unix qui ne fonctionne pas sous Mac n'a aucun effet.

Après cela, nous créons notre conteneur utile avec un client SSH. Nous partageons le fichier de socket Unix utilisé par notre session SSH locale.

De nombreux scripts simplifient ce processus: https://github.com/avsm/docker-ssh-agent-forward } _

Conclusion

Faire fonctionner SSH dans Docker aurait pu être plus facile. Mais cela peut être fait. Et ce sera probablement amélioré dans le futur. Les développeurs de Docker au moins sont conscients de ce problème. Et même résolu pour Dockerfiles avec des secrets de construction }. Et il y a une suggestion comment prendre en charge les sockets de domaine Unix.

1
Vanuan