Message d’erreur
x509: certificate specifies an incompatible key usage
Également affiché sous la forme
- tls: failed to verify certificate: x509: certificate specifies an incompatible key usage
Les clients TLS ajoutent le préfixe « tls: failed to verify certificate: » ; les serveurs Go qui vérifient des certificats client consignent « http: TLS handshake error from <addr>: tls: failed to verify certificate: x509: certificate specifies an incompatible key usage ».
Go crypto/x509 — CertificateInvalidError (IncompatibleUsage): extendedKeyUsage does not allow this role
Ce que cela signifie
La chaîne est approuvée, mais l’extendedKeyUsage du certificat (ou celui d’un certificat intermédiaire, que Go vérifie aussi) n’autorise pas le rôle pour lequel il est utilisé : un certificat serveur sans serverAuth, ou un certificat client sans clientAuth en TLS mutuel. Go applique l’EKU strictement ; d’autres piles TLS sont plus tolérantes, si bien que le même certificat peut fonctionner ailleurs.
Pourquoi cela se produit
Un certificat client est servi comme certificat serveur
fréquenteDes certificats issus d’un modèle d’authentification client (EKU clientAuth uniquement), par exemple d’une PKI interne, installés sur un serveur.
Un certificat serveur est utilisé pour le TLS mutuel
fréquenteRéutiliser le certificat d’un serveur web (EKU serverAuth uniquement) comme certificat client échoue sur les serveurs Go qui exigent clientAuth.
Un certificat intermédiaire restreint les usages autorisés
occasionnelleGo traite l’EKU des certificats intermédiaires comme une contrainte sur tout ce qui se trouve en dessous d’eux ; un certificat intermédiaire limité à clientAuth ne peut pas émettre de certificats serveur utilisables.
Comment corriger l’erreur
- 1.
Lire l’extendedKeyUsage de chaque certificat
Vérifiez le certificat feuille et chaque certificat intermédiaire ; l’usage dont vous avez besoin doit être autorisé sur tout le chemin.
bash # Leaf and intermediates: which purposes do they allow? openssl x509 -in server.pem -noout -ext extendedKeyUsage,keyUsage # TLS Web Server Authentication = serverAuth, TLS Web Client Authentication = clientAuth - 2.
Réémettre avec le bon EKU
serverAuth pour les certificats serveur, clientAuth pour les certificats client (les deux si un même certificat doit vraiment remplir les deux rôles).
bash # Server certificates need serverAuth; for mutual TLS client certificates need clientAuth openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com" -addext "extendedKeyUsage=serverAuth" - 3.
TLS mutuel : émettre les certificats client avec clientAuth
Les serveurs Go configurés avec RequireAndVerifyClientCert vérifient que l’EKU du certificat client contient clientAuth.
go // Go server verifying client certificates: they need clientAuth (or no EKU at all) cfg := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientCAPool, }