[インデックス 11229] ファイルの概要
このコミットは、Go言語の標準ライブラリ crypto/tls
パッケージ内の root_unix.go
ファイルに対する変更です。このファイルは、Unix系システムにおいてTLS (Transport Layer Security) 通信で使用されるルート証明書(CA証明書)の探索パスを定義しています。具体的には、様々なLinuxディストリビューションやBSD系OSで一般的に使用されるCA証明書のファイルパスのリストを保持しており、Goプログラムが安全なHTTPS接続などを確立する際に、これらのパスから信頼されたルート証明書をロードできるようにしています。
コミット
このコミットは、Go言語の crypto/tls
パッケージにFreeBSDシステムにおけるルート証明書の新しい探索パスを追加するものです。これにより、FreeBSD環境でGoアプリケーションがTLS接続を行う際に、システムが提供する信頼されたルート証明書を正しく認識できるようになり、x509: certificate signed by unknown authority
のような証明書検証エラーが解消されます。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/18de11479c08fcb3d0b457a4bcabae5457168258
元コミット内容
commit 18de11479c08fcb3d0b457a4bcabae5457168258
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Jan 18 10:03:00 2012 -0800
crypto/tls: add FreeBSD root certificate location
Fixes #2721.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5532090
変更の背景
この変更は、Go言語のIssue #2721「crypto/tls: no root certificate for FreeBSD」を解決するために行われました。このIssueは、2012年1月17日に報告されたもので、FreeBSD環境でGoのgoinstall
コマンド(現在のgo get
に相当)を実行した際に、「x509: certificate signed by unknown authority」というエラーが発生し、ルート証明書が見つからないことが原因であることが示されていました。
Goのcrypto/tls
パッケージは、TLS接続の際にサーバーから提示された証明書が信頼できる認証局(CA)によって署名されているかを検証する必要があります。この検証には、システムにインストールされている信頼されたルートCA証明書のセットが必要です。しかし、FreeBSDシステムでは、Goがデフォルトで探索するパスにルート証明書が存在しなかったため、TLS接続が失敗していました。
この問題は、GoアプリケーションがFreeBSD上でHTTPS通信やその他のTLSで保護されたサービスと通信する際に、セキュリティ上の問題や機能不全を引き起こす可能性がありました。そのため、FreeBSD固有のルート証明書パスを追加することで、GoがFreeBSD環境でも正しく証明書を検証できるようにすることが急務でした。
前提知識の解説
TLS (Transport Layer Security)
TLSは、インターネット上で安全な通信を行うための暗号化プロトコルです。ウェブサイトのHTTPS接続、電子メールの送受信、VPN接続など、様々なアプリケーションで利用されています。TLSは、通信の盗聴、改ざん、なりすましを防ぐために、以下の主要な機能を提供します。
- 暗号化: 通信内容を暗号化し、第三者による盗聴を防ぎます。
- 認証: 通信相手が本物であることを確認します。特にサーバー認証では、サーバーが提示するデジタル証明書を用いてその正当性を検証します。
- 完全性: 通信内容が途中で改ざんされていないことを保証します。
デジタル証明書と認証局 (CA)
TLS通信において、サーバーの身元を保証するためにデジタル証明書が使用されます。この証明書は、サーバーの公開鍵、ドメイン名、有効期限などの情報を含み、信頼された第三者機関である認証局 (Certificate Authority, CA) によってデジタル署名されています。
クライアント(Goアプリケーションなど)がサーバーとTLS接続を確立する際、サーバーは自身のデジタル証明書をクライアントに提示します。クライアントは、この証明書が信頼できるCAによって署名されているかを検証します。この検証プロセスでは、クライアントが自身で保持しているルートCA証明書のリストを使用します。ルートCA証明書は、自己署名された証明書であり、信頼の基点となります。
ルート証明書ストア
オペレーティングシステムやアプリケーションは、信頼されたルートCA証明書を保存するための「ルート証明書ストア」または「トラストストア」を持っています。Goのcrypto/tls
パッケージは、TLS接続を行う際に、このシステムレベルのルート証明書ストアから信頼されたCA証明書をロードしようとします。
Unix系システムでは、これらの証明書は通常、特定のディレクトリ(例: /etc/ssl/certs
)にファイルとして格納されています。各ディストリビューションやOSによって、これらのファイルの命名規則や配置場所が異なるため、Goのような汎用的なライブラリは、複数の一般的なパスを探索する必要があります。
FreeBSDにおけるルート証明書
FreeBSDは、Unix系オペレーティングシステムの一つであり、そのルート証明書の管理方法も他のLinuxディストリビューションとは異なる場合があります。FreeBSDでは、security/ca_root_nss
パッケージがインストールされている場合、NSS (Network Security Services) ライブラリによって管理されるルート証明書が/usr/local/share/certs/ca-root-nss.crt
のようなパスに配置されることが一般的です。Goがこのパスを認識していなかったため、FreeBSD環境でのTLS接続に問題が生じていました。
技術的詳細
Go言語のcrypto/tls
パッケージは、TLSプロトコルの実装を提供し、クライアントおよびサーバーサイドでの安全な通信を可能にします。このパッケージは、デフォルトでシステムにインストールされているルートCA証明書を使用して、ピアの証明書を検証します。
root_unix.go
ファイルは、Unix系システム(Linux、OpenBSD、FreeBSDなど)におけるルート証明書の探索ロジックをカプセル化しています。具体的には、certFiles
という文字列スライスの変数に、各OSでルート証明書が格納されている可能性のあるパスのリストを定義しています。GoのTLSクライアントが接続を確立する際、このリストを順番に走査し、最初に見つかった有効な証明書ファイルからルートCA証明書をロードします。
このコミット以前は、certFiles
リストにFreeBSD固有のパスが含まれていなかったため、FreeBSDシステムではGoがルート証明書を見つけられず、証明書検証エラーが発生していました。
追加されたパスは、/usr/local/share/certs/ca-root-nss.crt
です。このパスは、FreeBSDでsecurity/ca_root_nss
ポート(またはパッケージ)をインストールした際に、MozillaのNSSプロジェクトから派生したルート証明書が配置される標準的な場所です。このパスを追加することで、GoはFreeBSD環境でもシステムが提供する信頼されたルート証明書を正しくロードし、TLS接続を成功させることができるようになります。
この変更は、Goのクロスプラットフォーム互換性を向上させ、FreeBSDユーザーがGoアプリケーションをよりスムーズに利用できるようにするために重要でした。
コアとなるコードの変更箇所
--- a/src/pkg/crypto/tls/root_unix.go
+++ b/src/pkg/crypto/tls/root_unix.go
@@ -13,10 +13,11 @@ import (
// Possible certificate files; stop after finding one.
var certFiles = []string{
-\t"/etc/ssl/certs/ca-certificates.crt", // Linux etc
-\t"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
-\t"/etc/ssl/ca-bundle.pem", // OpenSUSE
-\t"/etc/ssl/cert.pem", // OpenBSD
+\t"/etc/ssl/certs/ca-certificates.crt", // Linux etc
+\t"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
+\t"/etc/ssl/ca-bundle.pem", // OpenSUSE
+\t"/etc/ssl/cert.pem", // OpenBSD
+\t"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
}
func initDefaultRoots() {
コアとなるコードの解説
変更はsrc/pkg/crypto/tls/root_unix.go
ファイル内のcertFiles
変数に対して行われています。
certFiles
は、Goのcrypto/tls
パッケージがUnix系システム上で信頼されたルートCA証明書を探す際に参照するファイルパスのリストを定義した[]string
型のグローバル変数です。このリストに列挙されたパスは、GoがTLS接続の際にシステムが提供するルート証明書をロードするために順番に試行されます。
このコミットでは、既存のリストに以下の新しいエントリが追加されました。
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
この行は、FreeBSDシステムで一般的にルート証明書が配置されるパス/usr/local/share/certs/ca-root-nss.crt
をcertFiles
リストに追加しています。コメント// FreeBSD
は、このパスがFreeBSDに特化したものであることを示しています。
この変更により、GoアプリケーションがFreeBSD環境でTLS接続を確立しようとする際、crypto/tls
パッケージは、この新しいパスも探索対象に含めるようになります。もしFreeBSDシステムにsecurity/ca_root_nss
パッケージがインストールされており、このパスに有効なルート証明書ファイルが存在すれば、Goはそれをロードして証明書検証に使用できるようになります。これにより、FreeBSDにおける「x509: certificate signed by unknown authority」エラーが解消され、TLS通信が正常に行われるようになります。
関連リンク
- Go Issue #2721: https://github.com/golang/go/issues/2721
参考にした情報源リンク
- Go Issue 2721: crypto/tls: no root certificate for FreeBSD: https://github.com/golang/go/issues/2721
- Go's
crypto/tls
package documentation: https://pkg.go.dev/crypto/tls - FreeBSD Bugzilla – Bug 256003: Go applications ignore system trusted TLS certificates: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=256003
- Stack Overflow - Where does Go look for SSL root certificates?: https://stackoverflow.com/questions/22007368/where-does-go-look-for-ssl-root-certificates