本文へスキップ
ecdsa.com
Go crypto/x509Go

エラーメッセージ

x509: certificate signed by unknown authority

Go crypto/x509 — returned by Certificate.Verify and TLS dials

このエラーの意味

Go はサーバーの証明書から信頼済みのルートまでのチェーンを構築しようとしましたが、失敗しました。設定されたルートプールに含まれる証明書で終わるパスが 1 つもありません。証明書自体はまったく問題なく有効な場合もあり、単に Go にその発行者を信頼する理由がないだけです。これは、Go アプリケーションの運用で最もよく遭遇する TLS エラーです。

発生する理由

修正方法

  1. 1.

    クライアントのルートプールに CA を追加する

    システムのプールを置き換えるのではなく、拡張してください。そうすれば、社内 CA を使うサイトに加えて、パブリックなサイトにも引き続き接続できます。

    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. 2.

    サーバー側の修正:完全なチェーンを返す

    サーバーが実際に何を送信しているかを確認してください。証明書が 1 つしか表示されない場合は、完全なチェーンを含むファイル(Let's Encrypt の fullchain.pem など)をサーバーに指定してください。

    bash
    openssl s_client -connect api.example.com:443 -showcerts </dev/null \
      | grep -c "BEGIN CERTIFICATE"   # 1 = leaf only (broken), 2+ = chain present
  3. 3.

    イメージに CA 証明書を含める

    最小構成のイメージでは、ビルド時に CA バンドルをコピーしてください。InsecureSkipVerify でこの問題を「解決」してはいけません。検証が完全に無効になります。

    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/

関連するエラー

署名エラーデータベースをすべて見る