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

エラーメッセージ

x509: certificate relies on legacy Common Name field, use SANs instead

別の表記

  • tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead

TLS 接続の中では(Go 1.20 以降)、テキストの先頭に「tls: failed to verify certificate:」が付き、HTTP クライアントではさらに「Get \"https://…\":」が付きます。Go で作られたプログラム(kubectl、Terraform、Docker、Prometheus、Vault CLI)も同じテキストを出力します。

Go crypto/x509 — HostnameError for a certificate without subjectAltName (Go 1.15+)

このエラーの意味

サーバーの証明書にはサブジェクト代替名(SAN)拡張がないため、ホスト名はサブジェクトのコモンネームにしか存在しません。Go は RFC 6125 と CA/Browser Forum のルールに従い、Go 1.15 でコモンネームのホスト名を受け入れなくなり(1.17 で完全に廃止)、CN が一致していたはずの場合にはそのことを明示的に報告します。解決策は SAN を含む証明書だけで、クライアント側で切り替えられる設定はもう残っていません。

発生する理由

修正方法

  1. 1.

    SAN 拡張がないことを確認する

    返される証明書のサブジェクトと subjectAltName を出力してください。

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
    # No "X509v3 Subject Alternative Name" in the output -> reissue the certificate
  2. 2.

    subjectAltName を含めて再発行する

    すべての DNS 名(クライアントが IP アドレスを使う場合は IP アドレスも)を subjectAltName に入れてください。openssl x509 -req で CSR に署名する場合、-copy_extensions copy または -extfile を指定しない限り、CSR の拡張は破棄されます。

    bash
    openssl req -new -key server.key -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com" -out server.csr
    # when signing with "openssl x509 -req", keep the extension:
    openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -days 90 -copy_extensions copy -out server.pem
  3. 3.

    Go のフラグを探さない

    一時的な回避策だった GODEBUG=x509ignoreCN=0 は Go 1.17 で削除されたため、証明書を再発行する以外に解決策はありません。

    text
    GODEBUG=x509ignoreCN=0 only worked in Go 1.15–1.16 and was removed in Go 1.17;
    there is no switch left in current Go releases. The certificate must carry SANs.

関連するエラー

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