Secrets de la construction et de la transmission de SSH à Docker 09/18

image

En utilisant Dockerfile, il a toujours été difficile d'accéder aux ressources privées. Il n'y avait tout simplement pas de bonne solution. Il n'est pas bon d'utiliser des variables d'environnement ou simplement de supprimer des fichiers secrets après utilisation: ils restent dans les métadonnées de l'image. Les utilisateurs ont parfois recours à des astuces: ils ont créé des assemblys à plusieurs étapes, cependant, une extrême prudence a dû être prise pour qu'il n'y ait pas de valeurs secrètes à l'étape finale, et les fichiers secrets ont été stockés dans le cache de l'assembly local jusqu'à l'écrêtage.


L'équipe de construction Docker du 18 septembre inclut de nombreuses mises à jour. La principale caractéristique est qu'une toute nouvelle version de l'implémentation côté serveur est apparue; elle est offerte dans le cadre du projet Moby BuildKit. L'application serveur BuildKit a acquis de nouvelles fonctionnalités, notamment la prise en charge des secrets de génération Dockerfile.


Utilisation des secrets


Tout d'abord, vous devez activer le côté serveur BuildKit. BuildKit dans la version 18.09 est une fonction de sélection qui peut être activée à l'aide de la variable d'environnement DOCKER_BUILDKIT=1 avant de lancer la docker build . Dans la prochaine version, il est prévu de faire de BuildKit la partie serveur par défaut.


 export DOCKER_BUILDKIT=1 

L'implémentation des secrets de construction est basée sur deux nouvelles fonctionnalités de BuildKit. L'un d'eux est la possibilité d'utiliser une interface utilisateur chargée à partir d'images dans le registre; la seconde est la possibilité d'utiliser des points de montage dans les commandes RUN pour le Dockerfile. Pour utiliser une fonction d'implémentation qui prend en charge les secrets (au lieu de la norme), définissez l'image de l'éditeur de liens à l'aide de la directive de syntaxe dans la première ligne du Dockerfile - indiquant l'image du conteneur que vous souhaitez utiliser. Jusqu'à présent, les secrets du canal stable des Dockerfiles externes ne sont pas disponibles: vous aurez besoin d'une des versions du canal expérimental, par exemple, docker/dockerfile:experimental ou docker/dockerfile/1.0.0-experimental .


 # syntax=docker/dockerfile:1.0.0-experimental 

Si vous, en tant qu'auteur du Dockerfile, savez que la commande RUN installée dans le Dockerfile nécessite une valeur secrète, utilisez l'étiquette --mount pour cela, indiquant de quel secret la commande a besoin et où la monter. L'étiquette --mount accepte une structure séparée par des virgules comme dans --mount pour un docker run .


 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key command-to-run 

Cette étiquette indique que pendant l'opération, la commande a accès au fichier secret le long du chemin /run/secrets/mysite.key . Le secret n'est disponible que pour l'équipe avec l'étiquette de montage et non pour les autres parties de l'assemblage. Les données de ce fichier sont téléchargées depuis la boutique secrète sur la base de l'identifiant spécifié "mysite.key". L'interface de ligne de commande Docker prend actuellement en charge la divulgation des secrets des fichiers clients locaux à l'aide de la balise --secret .


 docker build --secret id=mysite.key,src=path/to/mysite.key . 

Comme décrit ci-dessus, les secrets sont définis par défaut dans /run/secrets , cependant, vous pouvez spécifier n'importe quel chemin à l'aide de la clé "cible". Si "cible" est spécifié, mais "id" ne l'est pas, alors "id" devient par défaut le nom de base du chemin de destination.


Il n'est pas nécessaire de se limiter à un secret. Vous pouvez en utiliser n'importe quel nombre, en indiquant différents identifiants.


Si l'auteur du Dockerfile indique que l'instruction RUN peut utiliser le secret et que l'utilisateur invoquant l'assembly ne le fournit pas, le secret est ignoré et aucun fichier n'est installé sur le chemin spécifié. Si cette situation n'est pas souhaitable, utilisez la touche «requis»: cela indiquera que sans valeur, l'assemblage échouera.


 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key,required <command-to-run> 

Implémentation


Le fichier secret est automatiquement installé uniquement dans un système de fichiers tmpfs distinct pour éviter les fuites dans l'image finale ou la commande suivante, et pour qu'il ne soit pas stocké dans le cache de génération local.


Les valeurs secrètes sont également exclues des calculs de cache de génération afin que le cache de métadonnées ne puisse pas être utilisé.


Ssh


Le plus souvent, ils essaient probablement d'accéder à des référentiels privés via le protocole SSH. Oui, vous pouvez utiliser des éléments secrets pour révéler la clé privée SSH pour l'assembly, mais il existe une meilleure solution. Le protocole SSH utilise la cryptographie à clé publique, et grâce à cette conception, vous n'avez pas besoin de divulguer votre clé privée à quiconque. Par exemple, si vous utilisez plusieurs ordinateurs avec SSH, vous n'avez pas besoin de transférer votre clé - fournissez simplement une connexion via le protocole ssh-A .


Nous avons ajouté une fonctionnalité similaire dans la docker build , où vous pouvez utiliser l'étiquette --ssh pour diriger une connexion ou une clé d'agent SSH existante vers l'éditeur de liens. Au lieu de transmettre des informations clés, Docker indique simplement à l'éditeur de liens qu'il est disponible. Si l'éditeur de liens doit accéder au serveur distant via SSH, il contactera le client et demandera la confirmation de la demande spécifique requise pour la connexion. La clé elle-même ne quitte pas le programme client, et après l'achèvement du programme nécessitant un accès, aucune donnée ne reste de l'éditeur de liens pour reconnecter la connexion à distance.


L'accès au transfert de fichiers via le protocole SSH n'est accordé qu'aux commandes du Dockerfile qui ont directement demandé l'accès à SSH en spécifiant le bloc type=ssh . D'autres commandes n'ont pas de données sur l'agent SSH disponible.


Il convient également de noter un autre aspect de SSH - l'utilisation du modèle de sécurité TOFU. Lors de la première connexion au serveur SSH, il demandera des informations sur l'hôte inconnu, car il n'a pas de clé publique disponible localement pour ce serveur et, par conséquent, ne peut pas vérifier si la clé publique fournie par la partie distante est valide pour cette adresse.


Lors de l'assemblage avec Dockerfile, l'exactitude de cette demande ne peut pas être vérifiée et, par conséquent, la clé publique du serveur doit déjà exister dans le conteneur essayant d'utiliser SSH. Il existe plusieurs façons d'obtenir cette clé publique. Par exemple, l'image de base la fournira ou vous la copiez à partir du contexte de génération. Si vous voulez une solution plus simple, exécutez le programme ssh–keyscan dans le cadre de l'assembly - il chargera la clé publique actuelle de l'hôte.


Pour demander l'accès SSH à la commande RUN dans le Dockerfile, vous devez spécifier un bloc de type «ssh». Ensuite, au cours du processus, un socket sera installé avec un accès en lecture seule à l'agent SSH. Cela définira également la variable d'environnement SSH_AUTH_SOCK afin que les programmes utilisant le protocole SSH utilisent automatiquement ce socket.


 # syntax=docker/dockerfile:experimental FROM alpine # install ssh client and git RUN apk add --no-cache openssh-client git # download public key for github.com RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts # clone our private repository RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject 

Côté client Docker, utilisez l'étiquette --ssh indiquer que le transfert SSH est autorisé pour cet assembly.


 docker build --ssh default . 

L'étiquette accepte une paire de valeurs de clé qui détermine l'emplacement du socket de l'agent SSH local ou des clés privées. Si vous souhaitez utiliser la valeur default=$SSH_AUTH_SOCK , vous pouvez laisser le chemin du socket vide.


Dans le bloc Dockerfile, vous pouvez également utiliser la clé id pour séparer les différents serveurs dans le même assembly. Par exemple, l'accès à divers référentiels dans le Dockerfile peut être obtenu avec différentes clés de déploiement. Dans ce cas, dans le Dockerfile, vous utiliserez:


 … RUN --mount=type=ssh,id=projecta git clone projecta … RUN --mount=type=ssh,id=projectb git clone projectb … 

et développez les données client avec la construction du docker --ssh projecta=./projecta.pem --ssh projectb=./projectb.pem . Notez que même si vous spécifiez les clés réelles, seule la connexion de l'agent est envoyée à l'éditeur de liens, pas le contenu réel de ces clés privées.


Avec cela, l'examen des nouvelles fonctionnalités des secrets de construction dans Docker 18.09 est terminé. J'espère que les nouvelles fonctionnalités aideront à mieux utiliser les capacités de Dockerfile dans les projets et fourniront un niveau de sécurité plus élevé pour la chaîne de montage.

Source: https://habr.com/ru/post/fr432682/


All Articles