Pular para o conteúdo
ecdsa.com
Go crypto/tls (Go ≥ 1.20)Go

Mensagem de erro

tls: failed to verify certificate: x509: certificate signed by unknown authority

Go crypto/tls (Go ≥ 1.20) — wrapping x509 verification errors

O que significa

Desde o Go 1.20, as falhas de handshake TLS encapsulam o erro x509 subjacente com o prefixo “tls: failed to verify certificate:”, de modo que os logs mostram tanto a camada (handshake TLS) quanto a causa raiz (a construção da cadeia falhou). O sufixo varia — autoridade desconhecida, certificado expirado, nome de host divergente — e é ele que diz o que fazer. O prefixo também é um filtro de log prático: um grep por ele separa as falhas de confiança do TLS dos erros da camada de aplicação, e foi exatamente para isso que o encapsulamento foi adicionado.

Por que acontece

Como corrigir

  1. 1.

    Dar ao cliente as âncoras de confiança certas

    A mesma solução do erro x509 sem prefixo: um pool de certificados raiz que contenha a CA emissora, configurado no transporte HTTP que de fato abre a conexão.

    go
    pool := x509.NewCertPool()
    caPEM, _ := os.ReadFile("ca.pem")
    pool.AppendCertsFromPEM(caPEM)
    
    client := &http.Client{Transport: &http.Transport{
        TLSClientConfig: &tls.Config{RootCAs: pool},
    }}
    resp, err := client.Get("https://internal.example:8443/healthz")
  2. 2.

    Inspecionar o que o servidor apresenta

    Veja a cadeia servida, os emissores e a validade dela antes de mexer no código do cliente — a maioria das correções acaba sendo na configuração da cadeia no lado do servidor.

    bash
    openssl s_client -connect internal.example:8443 -servername internal.example \
      </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
  3. 3.

    Manter a verificação ativada, mesmo em testes

    Os servidores do httptest fornecem um cliente já configurado; use-o em vez de desativar a verificação globalmente.

    go
    srv := httptest.NewTLSServer(handler)
    defer srv.Close()
    resp, err := srv.Client().Get(srv.URL)   // trusts srv's cert, nothing else

Erros relacionados

Ver toda a base de erros de assinatura