エラーメッセージ
state=error: certificate verify failed (self-signed certificate in certificate chain)
別の表記
- OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=127.0.0.1:8443 state=error: certificate verify failed (self-signed certificate in certificate chain)
メッセージ全文は「SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (self-signed certificate in certificate chain)」です。OpenSSL 1.1.1 ベースの Ruby は、ハイフンなしの「self signed」と出力します。
Ruby openssl (Net::HTTP, Faraday, RubyGems) — OpenSSL::SSL::SSLError from SSL_connect
このエラーの意味
サーバーのチェーンは、Ruby の OpenSSL が信頼していない自己署名のルート証明書で終わっています。rubygems.org のような公開ホストで起きる場合は、TLS を検査するプロキシやウイルス対策ソフトが接続を再署名しています。社内ホストで起きる場合は、Ruby が使うストアに会社のルートがありません。
発生する理由
TLS を検査するプロキシ
よくある企業のプロキシは、rubygems.org、GitHub、各種 API への接続を独自のルートで再署名します。Ruby の OpenSSL のストアには、そのルートがありません。
チェーンにプライベートルートを含む社内サービス
よくあるルートはサーバーから送信されていますが、クライアントにはインストールされていません。
Ruby がシステムとは別のバンドルを使っている
ときどきrbenv/asdf で Homebrew の OpenSSL を使ってインストールした Ruby や、Windows の RubyInstaller は、独自の CA バンドルを使います。
修正方法
- 1.
ルートを特定する
公開ホストのチェーンを出力してください。会社名やセキュリティベンダーの名前が付いたルートであれば、それが信頼すべきルートです。
bash openssl s_client -connect rubygems.org:443 -servername rubygems.org -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' - 2.
SSL_CERT_FILE で結合したバンドルを指定する
SSL_CERT_FILE はデフォルトのバンドルを置き換えるため、公開ルートとプロキシのルートを結合してください。
bash # Public roots + the proxy root in one bundle cat /etc/ssl/certs/ca-certificates.crt corp-proxy-root.pem > ~/.config/corp-ca-bundle.pem export SSL_CERT_FILE=~/.config/corp-ca-bundle.pem - 3.
ルートをシステム全体にインストールする(Linux)
システムの OpenSSL にリンクされた Ruby は、update-ca-certificates の実行後にそのルートを読み込みます。
bash sudo cp corp-proxy-root.pem /usr/local/share/ca-certificates/corp-proxy-root.crt && sudo update-ca-certificates
関連するエラー
state=error: certificate verify failed (unable to get local issuer certificate)Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems)Could not verify the SSL certificate for https://gems.example.com/.Bundlercurl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)