Echecs de validation TLS intermittents avec Vault PKI et Go

paul-roland 04/04/2026
RÉSOLU
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

Hello. J'ai un souci hyper étrange sur notre mesh mTLS. On utilise HashiCorp Vault comme autorité de certification pour nos microservices en Go.

Aléatoirement, certains services refusent de se parler avec une erreur de validation de certificat. Ce qui me rend fou, c'est que ça marche 95% du temps. Les certificats sont générés par un vault-agent en sidecar.

L'erreur côté client Go est : x509: certificate signed by unknown authority.

04/04/2026 à 08:15

18 commentaires

fperrier
Membre
Avatar de fperrier
fperrier
Membre

Salut. Si c'est intermittent, c'est souvent un problème de chaîne de certification incomplète. Est-ce que tes services reçoivent bien l'intégralité de la chaîne (certificat + intermediates) ou juste le certificat final ?

05/04/2026 à 09:17

C'est une piste. Les clients Go sont très stricts sur la présence des certificats intermédiaires lors du handshake TLS si ceux-ci ne sont pas dans le trust store local du container.

Montre-nous comment ton vault-agent écrit les fichiers sur le disque.

Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

Voici ma configuration de template dans le vault-agent-config.hcl :

template {
  contents = "{{ with secret \"pki_int/issue/dot-com\" \"common_name=service.internal\" }}{{ .Data.certificate }}{{ end }}"
  destination = "/etc/tls/tls.crt"
}
template {
  contents = "{{ with secret \"pki_int/issue/dot-com\" \"common_name=service.internal\" }}{{ .Data.issuing_ca }}{{ end }}"
  destination = "/etc/tls/ca.crt"
}
Modifié le 23/05/2026 à 16:20
fperrier
Membre
Avatar de fperrier
fperrier
Membre

Je vois le problème. Dans ton tls.crt, tu n'écris que le certificat final. Si ton client ne connaît pas l'intermediate qui a signé ce cert, il rejette la connexion.

Vault renvoie plusieurs champs : certificate, issuing_ca, et ca_chain.

Modifié le 23/05/2026 à 16:20

Exactement. Pour que le TLS handshake soit complet, le serveur doit envoyer son certificat ET les certificats intermédiaires. Le client, lui, n'a besoin que du Root CA dans son trust store.

Tu devrais concaténer le cert et la chaîne dans ton fichier de destination.

14/04/2026 à 15:25
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

Mais pourquoi ça ne plante que 5% du temps alors ? Si la chaîne manque, ça devrait planter tout le temps, non ?

16/04/2026 à 16:51
fperrier
Membre
Avatar de fperrier
fperrier
Membre

Pas forcément. Si un service a déjà réussi à valider une chaîne via un autre service qui lui envoyait la chaîne complète, certains runtimes (ou l'OS) peuvent mettre l'intermediate en cache mémoire.

C'est le syndrome de l'intermediate manquant classique. On peut vérifier ça avec un openssl s_client -connect sur un service qui tourne.

Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

J'ai testé la commande sur un pod suspect :

openssl s_client -connect localhost:8443 -showcerts

Résultat : je ne vois qu'un seul certificat dans le dump. Effectivement, la chaîne est absente.

19/04/2026 à 09:05

Voilà. Il faut que tu modifies ton template pour inclure ca_chain. Attention, ca_chain est une liste dans la réponse JSON de Vault.

Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

J'ai essayé de modifier le template comme ça, mais ça me sort une erreur de syntaxe consul-template :

template {
  contents = "{{ with secret \"pki_int/issue/dot-com\" }}{{ .Data.certificate }}{{ .Data.ca_chain }}{{ end }}"
  destination = "/etc/tls/tls.crt"
}
23/04/2026 à 15:01
fperrier
Membre
Avatar de fperrier
fperrier
Membre

C'est normal, ca_chain ne peut pas être affiché directement car c'est un objet complexe. Tu dois itérer dessus ou utiliser une fonction de jointure.

Essaie ça plutôt :

{{ .Data.certificate }}
{{ range .Data.ca_chain }}{{ . }}
{{ end }}
Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

J'ai appliqué le changement. Maintenant mon fichier tls.crt contient bien trois blocs BEGIN CERTIFICATE.

Est-ce que je dois aussi modifier le ca.crt utilisé par le client pour la validation ?

Modifié le 23/05/2026 à 16:20

Le ca.crt du client doit impérativement contenir le Root CA. Si ton pki_int est un intermediate, assure-toi que le client possède bien la racine tout en haut.

Si tu utilises issuing_ca de l'intermediate PKI, ça ne marchera que si c'est lui-même qui a signé. Pour être safe, mets le Root CA complet dans ton trust store.

Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

J'ai mis à jour le ConfigMap qui contient le Root CA pour tous les pods. J'ai relancé un test de charge entre mes services.

Plus aucune erreur unknown authority dans les logs des clients Go après 10 000 requêtes.

Modifié le 23/05/2026 à 16:20
fperrier
Membre
Avatar de fperrier
fperrier
Membre

Excellent. C'est une erreur subtile car beaucoup de navigateurs web masquent le problème en téléchargeant l'intermediate manquant via AIA (Authority Information Access), mais les librairies TLS de backend comme celle de Go ne le font jamais.

03/05/2026 à 12:13

Petit conseil bonus : vérifie aussi la TTL de tes certificats Vault. Si tu génères des certs de 24h via vault-agent, assure-toi que ton application recharge les fichiers sur le disque sans redémarrer, sinon tu vas avoir une autre surprise demain matin.

Modifié le 23/05/2026 à 16:20
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

C'est prévu, j'utilise un watcher sur le système de fichiers pour rotate les certs dans le serveur HTTP de Go.

05/05/2026 à 20:13
paul-roland
Auteur Actif
Avatar de paul-roland
paul-roland
Auteur Actif

Merci pour l'explication sur la chaîne, j'aurais pu chercher longtemps pourquoi ça ne plantait que par intermittence. Vous gérez !

07/05/2026 à 20:57

Laisser une réponse

Vous devez être connecté pour poster un message !

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire