Mensagem de erro
x509: certificate specifies an incompatible key usage
Também aparece como
- tls: failed to verify certificate: x509: certificate specifies an incompatible key usage
Clientes TLS acrescentam o prefixo “tls: failed to verify certificate: ”; servidores Go que verificam certificados de cliente registram “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
O que significa
A cadeia é confiável, mas o extendedKeyUsage do certificado (ou o de um intermediário, que o Go também verifica) não permite o papel em que ele é usado: um certificado de servidor sem serverAuth ou um certificado de cliente sem clientAuth no TLS mútuo. O Go aplica o EKU de forma rigorosa; algumas outras pilhas TLS são mais tolerantes, então o mesmo certificado pode funcionar em outros lugares.
Por que acontece
Um certificado de cliente é servido como certificado de servidor
comumCertificados de um modelo de autenticação de cliente (EKU só com clientAuth), por exemplo, de uma PKI interna, instalados em um servidor.
Um certificado de servidor é usado no TLS mútuo
comumReutilizar o certificado de um servidor web (EKU só com serverAuth) como certificado de cliente falha em servidores Go que exigem clientAuth.
Um intermediário restringe os usos permitidos
ocasionalO Go trata o EKU dos intermediários como uma restrição sobre tudo o que está abaixo deles; um intermediário limitado a clientAuth não consegue emitir certificados de servidor utilizáveis.
Como corrigir
- 1.
Ler o extendedKeyUsage de cada certificado
Verifique o certificado folha e cada intermediário; a finalidade de que você precisa deve ser permitida ao longo de todo o caminho.
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.
Reemitir com o EKU correto
serverAuth para certificados de servidor, clientAuth para certificados de cliente (os dois, se um único certificado realmente precisar cumprir os dois papéis).
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 mútuo: emitir certificados de cliente com clientAuth
Servidores Go com RequireAndVerifyClientCert verificam se o EKU do certificado de cliente inclui clientAuth.
go // Go server verifying client certificates: they need clientAuth (or no EKU at all) cfg := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientCAPool, }