Fehlermeldung
x509: certificate specifies an incompatible key usage
Auch ausgegeben als
- tls: failed to verify certificate: x509: certificate specifies an incompatible key usage
TLS-Clients stellen das Präfix „tls: failed to verify certificate: “ voran; Go-Server, die Client-Zertifikate prüfen, protokollieren „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
Was der Fehler bedeutet
Die Kette ist vertrauenswürdig, aber die Erweiterung extendedKeyUsage des Zertifikats (oder die eines Zwischenzertifikats, die Go ebenfalls prüft) erlaubt nicht die Rolle, in der es verwendet wird: ein Serverzertifikat ohne serverAuth oder ein Client-Zertifikat ohne clientAuth bei Mutual TLS. Go setzt EKU streng durch; manche anderen TLS-Stacks sind nachsichtiger, deshalb kann dasselbe Zertifikat anderswo funktionieren.
Warum der Fehler auftritt
Ein Client-Zertifikat wird als Serverzertifikat ausgeliefert
häufigAuf einem Server installierte Zertifikate aus einer Vorlage für Client-Authentifizierung (EKU nur clientAuth), etwa aus einer internen PKI.
Ein Serverzertifikat wird für Mutual TLS verwendet
häufigWer das Zertifikat eines Webservers (EKU nur serverAuth) als Client-Zertifikat wiederverwendet, scheitert an Go-Servern, die clientAuth verlangen.
Ein Zwischenzertifikat schränkt die erlaubten Verwendungen ein
gelegentlichGo behandelt EKU auf Zwischenzertifikaten als Einschränkung für alles darunter; ein auf clientAuth beschränktes Zwischenzertifikat kann keine nutzbaren Serverzertifikate ausstellen.
So behebst du den Fehler
- 1.
extendedKeyUsage jedes Zertifikats lesen
Prüfe das Leaf-Zertifikat und jedes Zwischenzertifikat; der benötigte Verwendungszweck muss entlang des ganzen Pfads erlaubt sein.
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.
Mit der richtigen EKU neu ausstellen
serverAuth für Serverzertifikate, clientAuth für Client-Zertifikate (beides, wenn ein Zertifikat wirklich beide Rollen erfüllen muss).
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.
Mutual TLS: Client-Zertifikate mit clientAuth ausstellen
Go-Server mit RequireAndVerifyClientCert prüfen, ob die EKU des Client-Zertifikats clientAuth enthält.
go // Go server verifying client certificates: they need clientAuth (or no EKU at all) cfg := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientCAPool, }