{{indexmenu_n>50}} # Exposer le socket Docker via TLS ## Préambule Pour certaines opérations, il peut être utile de pouvoir lancer des commandes Docker à distance. Par exemple, les [[technique:graph_services|graphes des services]] sont construits de manière centralisée en récupérant des informations sur les conteneurs qui tournent, à distance. Une chaîne d'intégration aurait besoin de lancer des commandes à distance. Pour ce faire, l'idée est d'exposer le socket Docker (qui permet d'effectuer toutes les opérations possibles avec Docker) à l'extérieur. Exposer le socket Docker à l'extérieur revient à donner des accès `root` à quiconque pourra discuter avec lui. Il est donc essentiel d'utiliser TLS pour le sécuriser proprement. Pour pouvoir communiquer avec le socket Docker depuis l'extérieur, les éléments suivants sont nécessaires : * Le certificat d'une autorité de certification * Un certificat client * Une clé privée client permettant de signer les messages La clé privée est l'équivalent d'une clé privée SSH, qui est plus sûre qu'un mot de passe. Le certificat client est une sorte de carte d'identité du client, et ne peut être émis que par l'instance de Docker accessible à l'extérieur. Pour ce faire, il faut créer une autorité de certification (CA) côté serveur et générer l'ensemble de ces éléments. On crée ces éléments dans `/DATA/docker/remote`, ils appartiendront à `root` avec le groupe `docker`, et seront en `u=rw,g=r`. On a fixé arbitrairement la durée de vie des certificats à un an. Il conviendra donc de les renouveler et de les mettre à jour sur les serveurs **et** les clients concernés tous les ans. Un tutoriel complet est disponible [dans la documentation officielle](https://docs.docker.com/engine/security/https/), nous en reprenons les éléments principaux. Une bonne pratique est de ne pas ré-utiliser les certificats et clés clientes pour des clients multiples : générez autant de certificats que de clients. ## Créer une clé privée pour la CA Cette opération n'est qu'à faire une fois, pas à chaque renouvellement ! C'est la clé la plus importante, puisqu'elle permet de créer les certificats. Si elle est compromise, n'importe qui pourrait créer un certificat client illégitime. C'est pourquoi on la protegera avec un mot de passe. On génère la clé : ```bash openssl genrsa -aes256 -out ca-key.pem 4096 ``` Générer et stocker la passphrase dans [[asso:tuto:vaultwarden|Vaultwarden]], avec la nomenclature `Tech/Keys//ca-key.pem`. ## Créer ou renouveller la CA On crée la CA à partir de la clé privée existante, `ca-key.pem`, à l'aide de la commande suivante : ```bash $ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem ``` Les informations à remplir sont : * `Country Name` : `FR` * `State or Province Name` : `Picardie` * `Locality Name` : `Compiegne` * `Organization Name` : `Picasoft` * `Organization Unit Name` : `Picasoft` * `Common Name` : `.picasoft.net` *e.g.* `pica01-test.picasoft.net` * `Email Address` : `picasoft@assos.utc.fr` L'autorité de certification ainsi obtenue permettra de créer des certificats (serveur ou client). Elle n'est **jamais** utilisée pour chiffrer les communications. ## Création du certificat serveur Ce certificat est spécifié lors du lancement du démon Docker, et a plusieurs rôles : * Spécifier les hôtes concernés par l'autorité de certification. Ainsi, si ce certificat serveur est utilisé sur un autre hôte, les connexions seront refusées. * La clé privée qui lui est associée permet de chiffrer les communications. On commence par créer une nouvelle clé privée pour le certificat serveur : ```bash $ openssl genrsa -out server-key.pem 4096 ``` On crée une demande de signature du certificat. Attention, on remplace bien le `CN` par le champ `Common Name` de la CA, c'est-à-dire l'URL du serveur. ```bash $ openssl req -subj "/CN=.picasoft.net" -sha256 -new -key server-key.pem -out server.csr ``` Notez que le fichier `extfile.cnf` contient déjà toutes les informations nécessaires pour autoriser l'accès au socket Docker. S'il n'existe pas, créez le avec les informations suivantes : ``` extendedKeyUsage = serverAuth subjectAltName = DNS:.picasoft.net,IP:,IP:127.0.0.1 ``` Ainsi, ce certificat pourra être utilisé pour **valider** les authentifications côté serveur. On génère le certificat signé par la CA elle-même. ```bash openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf ``` On fait du nettoyage : ```bash $ rm server.csr ``` ### Renouvellement des certificats client On commence par effacer puis créer à nouveau les dossiers des clients (*e.g* `graphbot`, `ci`) : Pour chaque client, on crée une nouvelle clé privée: ```bash $ cd $ openssl genrsa -out -key.pem 4096 ``` On crée ensuite la demande de signature de certificat : ```bash $ openssl req -subj '/CN=' -new -key -key.pem -out .csr ``` Le fichier `extfile-client.cnf` contient déjà les informations nécessaires pour autoriser l'accès au socket Docker. S'il n'existe pas, créez le avec les informations suivantes : ``` extendedKeyUsage = clientAuth ``` Ainsi, le client sera autorisé à s'authentifier. On crée ensuite le certificat client signé. ```bash $ openssl x509 -req -days 365 -sha256 -in .csr -CA ../ca.pem -CAkey ../ca-key.pem -CAcreateserial -out -cert.pem -extfile ../extfile-client.cnf ``` On fait du nettoyage : ```bash $ rm .csr ``` Renouvelez l'opération pour l'ensemble des clients. ## Configurer le démon Docker Vérifier que le démon Docker est bien configuré pour [[technique:docker:admin:config#drop_in|démarrer avec TLS et utiliser le certificat généré]]. ## Relancer le démon Docker Avant toute chose, il est **indispensable** de donner des permissions propres à tout ce qui a été généré : ```bash cd /DATA/docker/remote sudo chown -R root:docker . sudo chmod -R u=rwX,g=rwX . ``` Il faut relancer le démon Docker avec les nouveaux certificats. ```bash sudo systemctl restart docker systemctl status docker ``` ## Utilisation des certificats clients Depuis le serveur concerné, récupérez les fichiers suivants : * `ca.pem` : le certificat de la CA elle-même. * `/-cert.pem` : le certificat du client, qui **doit avoir été signé** par la CA. * `/-key.pem` : la clé privée du client pour chiffrer les communications. Pour faciliter et sécuriser la tâche, on peut mettre tout ça dans un tar puis le chiffrer avec un mot de passe temporaire. ```bash tar -cvf certs.tar ca.pem gpg -c certs.tar rm certs.tar ``` Depuis notre PC, on récupère le fichier chiffré, puis on l'envoie vers le bon client: ```bash rsync @.picasoft.net:/DATA/docker/remote/certs.tar.gpg /tmp rsync /tmp/certs.tar.gpg @.picasoft.net:/tmp ``` On se connecte au client et on déchiffre et extrait le fichier: ```bash cd /tmp gpg certs.tar.gpg tar -xvf certs.tar ``` On peut vérifier que tout est ok avec la commande suivante: ```bash docker --tlsverify --tlscacert=/tmp/ca.pem --tlscert=/tmp/client/-cert.pem --tlskey=/tmp/client/-key.pem -H=.picasoft.net:2376 version ``` Si tout se passe bien, vous obtenez la version de Docker. **Vérifiez qu'il n'y a aucune erreur**. Il est nécessaire de mettre à jour les fichiers des services qui l'utilisent : on se référera à leur documentation.