**Ceci est une ancienne révision du document !**
Exposer le socket Docker via TLS
Introduction
Pour certaines opérations, il peut être utile de pouvoir lancer des commandes Docker “à distance”. Des exemples sont :
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. Pour des raisons de sécurité élémentaires, on l’expose via TLS.
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
Pour ce faire, il faut créer une autorité de certification (CA) côté serveur et générer l’ensemble des éléments ci-dessus.
Ces éléments seront créés dans /DATA/docker/remote
et appartiendront à root:docker
. Pour l’instant, les machines concernées sont :
pica01
pica02
pica01-test
Ces certificats ont une durée de vie qui a été fixée à 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, 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.
Notons enfin que les passphrases
chiffrant les clés privées des autorités de certification, celles-là même qui permettent de produire des certificats serveur et client, sont mises à disposition sur le pass pour les clés autorisées, avec la nomenclature Tech/Keys/<serveur>/ca-key.pem
.
L’ensemble des opérations expliquées plus bas, sauf indication contraire, se passent dans le dossier /DATA/docker/remote
, sur le serveur concerné (exemple : pica01-test.picasoft.net
)
Renouvellement de la CA
On crée la CA à partir de la clé privée existante, ca-key.pem
, à l’aide de la commande suivante :
- snippet.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
:<serveur>.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.
Renouvellement 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 :
- snippet.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.
- snippet.bash
$ openssl req -subj "/CN=<serveur>.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:<serveur>.picasoft.net,IP:<IP du serveur>,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.
- snippet.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 :
- snippet.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:
- snippet.bash
$ cd <client> $ openssl genrsa -out <client>-key.pem 4096
On crée ensuite la demande de signature de certificat :
- snippet.bash
$ openssl req -subj '/CN=<client>' -new -key <client>-key.pem -out <client>.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é.
- snippet.bash
$ openssl x509 -req -days 365 -sha256 -in <client>.csr -CA ../ca.pem -CAkey ../ca-key.pem -CAcreateserial -out <client>-cert.pem -extfile ../extfile-client.cnf
On fait du nettoyage :
- snippet.bash
$ rm <client>.csr
Renouvelez l’opération pour l’ensemble des clients.
Relancer le démon Docker
Avant toute chose, il est indispensable de donner des permissions propres à tout ce qui a été généré :
- snippet.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. Attention, prévenez l’équipe technique et choisissez votre moment, puisque tous les conteneurs seront redémarrés. Pour ce faire :
- snippet.bash
$ sudo systemctl restart docker $ systemctl status docker
On vérifie dans les logs que tout s’est bien passé. Un petit docker ps
ne fait pas de mal.
Vous remarquerez qu’on ne spécifie nulle part au démon Docker quels certificats il faut utiliser. C’est parce que la configuration du service docker
utilise le système de drop-in
pour rajouter des paramètres. Par exemple, sur pica01-test
, le fichier /etc/systemd/system/docker.service.d/override.conf
contient :
[Service] ExecStart= ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/DATA/docker/remote/ca.pem --tlscert=/DATA/docker/remote/server-cert.pem --tlskey=/DATA/docker/remote/server-key.pem --host=tcp://0.0.0.0:2376 --host=fd:// [Unit] Requires=docker.socket
On retrouve bien les paramètres attendus.
Utilisation des certificats clients
Depuis le serveur concerné, récupérez les fichiers suivants :
ca.pem
: le certificat de la CA elle-même.<client>/<client>-cert.pem
: le certificat du client, qui doit avoir été signé par la CA.<client>/<client>-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.
- snippet.bash
tar -cvf certs.tar ca.pem client 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:
- snippet.bash
rsync <user>@<serveur>.picasoft.net:/DATA/docker/remote/certs.tar.gpg /tmp rsync /tmp/certs.tar.gpg <user>@<client>.picasoft.net:/tmp
On se connecte au client et on déchiffre et extrait le fichier:
- snippet.bash
gpg /tmp/certs.tar.gpg tar -xvf /tmp/certs.tar
On peut vérifier que tout est ok avec la commande suivante:
- snippet.bash
docker --tlsverify --tlscacert=/tmp/ca.pem --tlscert=/tmp/<client>/<client>-cert.pem --tlskey=/tmp/<client>/<client>-key.pem -H=<serveur>.picasoft.net:2376 version
Si tout se passe bien, vous obtenez la version de Docker. Vérifiez qu’il n’y a aucune erreur.
Enfin, il est nécessaire de mettre à jour les fichiers les services qui l’utilisent : on se référera à leur documentation.