Saltar al contenido
ecdsa.com
Go crypto/tls (Go ≥ 1.20)Go

Mensaje de error

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

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

Qué significa

Desde Go 1.20, los fallos del handshake TLS envuelven el error x509 subyacente con el prefijo «tls: failed to verify certificate:», de modo que los registros muestran tanto la capa (el handshake TLS) como la causa raíz (falló la construcción de la cadena). El sufijo varía —autoridad desconocida, certificado caducado, nombre de host que no coincide— y es la parte sobre la que hay que actuar. El prefijo también sirve como filtro práctico de registros: buscarlo con grep separa los fallos de confianza TLS de los errores de la aplicación, y precisamente por eso se añadió el envoltorio.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Dar al cliente las anclas de confianza correctas

    El mismo remedio que para el error x509 sin prefijo: un pool de raíces que contenga la CA emisora, configurado en el transporte que realmente se usa para la conexión.

    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.

    Inspeccionar lo que presenta el servidor

    Revisa la cadena que envía el servidor, sus emisores y su validez antes de tocar el código del cliente: la mayoría de las soluciones acaban siendo de configuración de la cadena en el 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.

    Mantener la verificación activada, incluso en las pruebas

    Los servidores de httptest te dan un cliente ya configurado; úsalo en lugar de desactivar la verificación de forma global.

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

Errores relacionados

Explorar toda la base de datos de errores de firma