Mensagem de erro
x509: certificate signed by unknown authority
Go crypto/x509 — returned by Certificate.Verify and TLS dials
O que significa
O Go tentou montar uma cadeia do certificado do servidor até uma raiz em que confia e não conseguiu: nenhum caminho termina em um certificado do pool de raízes configurado. O certificado pode ser perfeitamente válido — o Go só não tem motivo para confiar no emissor dele. Este é o erro TLS mais frequente em implantações com Go.
Por que acontece
O servidor não envia o certificado intermediário
comumAs raízes dos trust stores assinam os intermediários, e os intermediários assinam os certificados folha. Um servidor configurado só com o certificado folha (cert.pem em vez de fullchain.pem) deixa o Go sem como ligar folha → raiz. Os navegadores muitas vezes disfarçam isso com intermediários em cache; o Go, não.
CA interna ou privada fora do pool
comumCAs corporativas, certificados autoassinados de desenvolvimento e certificados emitidos pela mesh não constam do repositório do sistema, e isso é intencional. O cliente precisa ser informado deles explicitamente.
Imagem de contêiner mínima sem certificados de CA
comumAs imagens scratch e slim não trazem /etc/ssl/certs. Toda conexão TLS então falha com este erro, por mais público e válido que seja o certificado do destino.
Um proxy de interceptação reassina o tráfego
ocasionalMiddleboxes corporativos de inspeção de TLS substituem os certificados por outros assinados pela CA da empresa. Máquinas sem essa CA instalada veem todos os sites externos como não confiáveis.
Como corrigir
- 1.
Adicionar a CA ao pool de raízes do cliente
Estenda o pool do sistema em vez de substituí-lo, para que os sites públicos continuem funcionando junto com sua CA interna.
go roots, err := x509.SystemCertPool() if err != nil { roots = x509.NewCertPool() } pem, _ := os.ReadFile("internal-ca.pem") roots.AppendCertsFromPEM(pem) client := &http.Client{Transport: &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: roots}, }} - 2.
Corrigir o servidor: servir a cadeia completa
Verifique o que o servidor realmente envia; se aparecer só um certificado, aponte o servidor para o arquivo da cadeia completa (por exemplo, o fullchain.pem do Let's Encrypt).
bash openssl s_client -connect api.example.com:443 -showcerts </dev/null \ | grep -c "BEGIN CERTIFICATE" # 1 = leaf only (broken), 2+ = chain present - 3.
Incluir certificados de CA na imagem
Em imagens mínimas, copie um bundle de CAs para dentro da imagem durante o build. Nunca “resolva” isso com InsecureSkipVerify — isso desativa a verificação por completo.
docker FROM alpine AS certs RUN apk add --no-cache ca-certificates FROM scratch COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/