Mensaje de error
x509: certificate specifies an incompatible key usage
También se muestra como
- tls: failed to verify certificate: x509: certificate specifies an incompatible key usage
Los clientes TLS añaden el prefijo «tls: failed to verify certificate: »; los servidores Go que verifican certificados de cliente registran «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
Qué significa
La cadena es de confianza, pero el extendedKeyUsage del certificado (o el de un intermedio, que Go también comprueba) no permite el papel para el que se usa: un certificado de servidor sin serverAuth, o un certificado de cliente sin clientAuth en TLS mutuo. Go aplica el EKU de forma estricta; algunas otras pilas TLS son más permisivas, así que el mismo certificado puede funcionar en otros sitios.
Por qué ocurre
Se sirve un certificado de cliente como certificado de servidor
frecuenteCertificados de una plantilla de autenticación de cliente (EKU solo clientAuth), por ejemplo de una PKI interna, instalados en un servidor.
Se usa un certificado de servidor para TLS mutuo
frecuenteReutilizar el certificado de un servidor web (EKU solo serverAuth) como certificado de cliente falla en los servidores Go que exigen clientAuth.
Un intermedio restringe los usos permitidos
ocasionalGo trata el EKU de los intermedios como una restricción sobre todo lo que cuelga de ellos; un intermedio limitado a clientAuth no puede emitir certificados de servidor utilizables.
Cómo solucionarlo
- 1.
Leer el extendedKeyUsage de cada certificado
Comprueba el certificado hoja y cada intermedio; el propósito que necesitas tiene que estar permitido en toda la ruta.
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.
Volver a emitir con el EKU correcto
serverAuth para certificados de servidor, clientAuth para certificados de cliente (ambos si un mismo certificado realmente tiene que cumplir los dos papeles).
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 mutuo: emitir certificados de cliente con clientAuth
Los servidores Go con RequireAndVerifyClientCert comprueban que el EKU del certificado de cliente incluya clientAuth.
go // Go server verifying client certificates: they need clientAuth (or no EKU at all) cfg := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientCAPool, }