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 ?
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.
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"
}
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`.
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.
Mais pourquoi ça ne plante que 5% du temps alors ? Si la chaîne manque, ça devrait planter tout le temps, non ?
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.
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.
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.
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"
}
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 }}
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 ?
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.
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.
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.
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.
C'est prévu, j'utilise un watcher sur le système de fichiers pour rotate les certs dans le serveur HTTP de Go.
Merci pour l'explication sur la chaîne, j'aurais pu chercher longtemps pourquoi ça ne plantait que par intermittence. Vous gérez !
Vous devez être connecté pour poster un message !
Recevoir les derniers articles gratuitement en créant un compte !
S'inscrire
paul-roland
Membre depuis le 19/03/2025Hello. 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`.