Fehlermeldung
x509: certificate signed by unknown authority
Go crypto/x509 — returned by Certificate.Verify and TLS dials
Was der Fehler bedeutet
Go hat versucht, vom Zertifikat des Servers eine Kette zu einem Root-Zertifikat aufzubauen, dem es vertraut, und ist gescheitert: Kein Pfad endet bei einem Zertifikat im konfigurierten Root-Pool. Das Zertifikat kann völlig gültig sein – Go hat nur keinen Grund, seinem Aussteller zu vertrauen. Das ist der mit Abstand häufigste TLS-Fehler in Go-Deployments.
Warum der Fehler auftritt
Der Server sendet das Zwischenzertifikat nicht
häufigRoot-Zertifikate in Trust Stores signieren Zwischenzertifikate, Zwischenzertifikate signieren Leaf-Zertifikate. Ist ein Server nur mit dem Leaf-Zertifikat konfiguriert (cert.pem statt fullchain.pem), kann Go die Lücke Leaf → Root nicht schließen. Browser überdecken das oft mit zwischengespeicherten Zwischenzertifikaten; Go tut das nicht.
Interne/private CA nicht im Pool
häufigFirmen-CAs, selbstsignierte Entwicklungszertifikate und von einem Service Mesh ausgestellte Zertifikate sind dem Zertifikatsspeicher des Systems konstruktionsbedingt unbekannt. Du musst sie dem Client ausdrücklich bekannt machen.
Minimales Container-Image ohne CA-Zertifikate
häufigImages vom Typ scratch und slim bringen kein /etc/ssl/certs mit. Jeder TLS-Verbindungsaufbau scheitert dann mit diesem Fehler, egal wie öffentlich und gültig das Zertifikat des Ziels ist.
Abfangender Proxy signiert den Traffic neu
gelegentlichMiddleboxes für TLS-Inspektion in Unternehmen ersetzen Zertifikate durch solche, die von der Firmen-CA signiert sind. Rechner, auf denen diese CA nicht installiert ist, halten jede externe Website für nicht vertrauenswürdig.
So behebst du den Fehler
- 1.
CA zum Root-Pool des Clients hinzufügen
Erweitere den System-Pool, statt ihn zu ersetzen, damit öffentliche Websites neben deiner internen CA weiter funktionieren.
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.
Server korrigieren: vollständige Kette ausliefern
Prüfe, was der Server tatsächlich sendet; erscheint nur ein Zertifikat, verweise den Server auf die Fullchain-Datei (zum Beispiel fullchain.pem von 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.
CA-Zertifikate im Image mitliefern
Kopiere bei minimalen Images beim Build ein CA-Bundle hinein. „Löse“ das nie mit InsecureSkipVerify – damit ist die Prüfung komplett abgeschaltet.
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/