Une PKI, c'est facile. Faire confiance à une PKI, beaucoup moins
Monter une autorité de certification interne m'a pris une demi-journée. Faire en sorte que quoi que ce soit lui fasse confiance m'a occupé bien plus longtemps.
Le HTTPS public était réglé depuis deux semaines. Traefik, Let's Encrypt, renouvellement automatique, cadenas vert. Dossier clos, dans ma tête.
Puis cette question au point du jeudi : et entre le proxy et le conteneur, ça circule en quoi ?
En clair. Tout l'intérieur de l'infra, Traefik vers les applis, les agents vers le SIEM, les clients vers le DNS, parlait en HTTP non chiffré.
« C'est notre réseau »
Mon premier réflexe a été de défendre l'existant : le réseau est segmenté, personne d'extérieur n'y accède, à quoi bon chiffrer.
C'est exactement le raisonnement qui a coûté cher à pas mal de boîtes. Il tient tant qu'on suppose que l'attaquant est dehors. Dès qu'on admet qu'il peut déjà être dedans, poste compromis, conteneur vulnérable, identifiant volé, un réseau interne en clair devient un réseau où il suffit d'écouter pour récolter des jetons de session et des identifiants.
C'est l'idée derrière le zero trust : la position dans le réseau ne fait pas la confiance.
Let's Encrypt ne peut pas nous aider ici
J'ai commencé par essayer de demander des certificats Let's Encrypt pour les services internes. Impossible, et pour une bonne raison.
Let's Encrypt vérifie qu'on contrôle un domaine, soit en répondant sur le port 80, soit en posant un enregistrement DNS public. Un service en vault.interne.lan, joignable seulement depuis le VLAN SRV, ne peut satisfaire ni l'un ni l'autre. Il n'existe pas sur Internet.
Il fallait notre propre autorité.
step-ca
step-ca est une autorité de certification légère, pensée pour l'automatisation. Elle expose une API ACME, le même protocole que Let's Encrypt, ce qui permet de réutiliser les mêmes mécanismes de renouvellement automatique côté clients.
step ca init \
--name "Sentinel Internal CA" \
--dns ca.interne.lan \
--address :8443 \
--provisioner admin@interne.lan
step ca provisioner add acme --type ACME
Côté Traefik interne, trois lignes suffisaient :
certificatesResolvers:
interne:
acme:
caServer: https://ca.interne.lan:8443/acme/acme/directory
email: admin@interne.lan
storage: /certs/acme-interne.json
Une demi-journée, tests compris. J'étais assez content de moi.
Là où j'ai vraiment passé du temps
Un certificat signé par une autorité que personne ne connaît ne vaut rien. Chaque client affiche une grosse erreur rouge. Il faut distribuer le certificat racine partout.
Et « partout » recouvre des réalités très différentes. Les navigateurs utilisent le magasin du système, sauf Firefox qui gère le sien à part. Sur Linux il faut déposer le fichier dans /usr/local/share/ca-certificates/ puis lancer update-ca-certificates. Chaque image Docker a son propre magasin, donc un conteneur alpine ne voit pas les certificats de l'hôte, il faut les monter dedans ou rebâtir l'image. Node.js ignore le magasin système et veut NODE_EXTRA_CA_CERTS. Python utilise le bundle de certifi, encore ailleurs.
C'est là que j'ai compris ce qu'est une PKI. Pas un logiciel qui signe des certificats, mais un problème de distribution de la confiance, dont le logiciel est la partie facile.
Deux heures perdues sur un champ obsolète
Un service refusait le certificat avec une erreur de nom. Le certificat était valide, la CA reconnue, et le nom correct dans le champ Common Name.
Le problème : depuis plusieurs années, les clients TLS ignorent complètement le Common Name. Ils ne regardent que l'extension Subject Alternative Name. J'avais suivi un tutoriel écrit avant ce changement.
step certificate inspect cert.pem --format json | jq '.extensions.subject_alt_name'
Leçon de méthode : quand une couche crypto refuse quelque chose, elle a presque toujours une bonne raison. Lire la spec prend moins de temps que de tâtonner. J'ai fait l'inverse.
Ce que le cours ne disait pas
En cours de crypto, la PKI est un schéma. Une racine, des intermédiaires, une chaîne de signature, des certificats feuilles. Je savais dessiner l'arbre et expliquer chaque nœud.
Le schéma ne dit pas que la confiance ne se propage pas toute seule. Chaque système qui doit valider un certificat a besoin qu'on lui installe explicitement la racine, et chaque écosystème le fait à sa sauce.
La théorie décrit la vérification. En pratique, le boulot c'est la logistique de la confiance. C'est sans doute le chantier où l'écart entre ce que je croyais savoir et ce que je savais faire était le plus grand.