错误信息
Could not verify the SSL certificate for https://gems.example.com/.
也可能输出为
- Bundler::Fetcher::CertificateFailureError Could not verify the SSL certificate for https://gems.example.com/.
每次尝试时,Bundler 都会打印“Retrying fetcher due to error (n/4): Bundler::Fetcher::CertificateFailureError Could not verify the SSL certificate for <source>.”,随后是“There is a chance you are experiencing a man-in-the-middle attack, but most likely your system doesn't have the CA certificates needed for verification.”。源 URL 即你在 Gemfile 中配置的地址。
Bundler — Bundler::Fetcher::CertificateFailureError while fetching a gem source
含义
Bundler 无法验证 Gemfile 中某个 gem 源的 TLS 证书,重试之后放弃了。它把 OpenSSL 验证错误包装在 Bundler::Fetcher::CertificateFailureError 中,并附加一条提示:系统可能缺少 CA 证书。与 Ruby 的一般情况一样,受信任的 CA 就是这个 Ruby 所用 OpenSSL 证书包中的 CA,除非 Bundler 的 ssl_ca_cert 设置另有指定。
原因
使用公司证书的私有 gem 服务器
常见Gemfury、Artifactory、Nexus 或自托管的 gem 服务器,其 CA 不在 Ruby 使用的证书包中(在 CI 镜像中很常见)。
rubygems.org 前面有执行 TLS 检查的代理
常见浏览器通过操作系统证书存储信任代理的根证书,但 Ruby 的 OpenSSL 证书包并不信任它。
这个 Ruby 使用自己的 CA 证书包
偶见基于 Homebrew OpenSSL 或自带 OpenSSL 构建的 Ruby,以及 Windows 上的 RubyInstaller,都不会读取操作系统证书存储。
修复方法
- 1.
设置 Bundler 的 ssl_ca_cert
bundle config set ssl_ca_cert 用于配置 Bundler 在拉取时使用的 CA 文件。在我们的测试中,这一设置立即解决了这个错误。
bash # Trust a CA for Bundler (stored in .bundle/config; --global for ~/.bundle/config) bundle config set --local ssl_ca_cert /etc/ssl/private-ca/corp-root-ca.pem bundle install - 2.
或者设置 SSL_CERT_FILE
这个 OpenSSL 环境变量对 Bundler、RubyGems 和应用程序同样生效;把它指向一个同时包含公共根证书的证书包。
bash # Or for the whole process (Bundler, RubyGems and Net::HTTP) SSL_CERT_FILE=/etc/ssl/private-ca/corp-ca-bundle.pem bundle install - 3.
把 CA 安装到 Ruby 读取的证书存储中
查看 OpenSSL::X509::DEFAULT_CERT_FILE,确认对应的是哪个证书包文件,然后把根证书添加进去(在 Debian 和 Ubuntu 上通过 update-ca-certificates 添加)。
bash sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && sudo update-ca-certificates ruby -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE' # the bundle this Ruby reads - 4.
RubyGems:.gemrc 中的 :ssl_ca_cert
gem install 有自己的一项设置,用途相同。
yaml # ~/.gemrc — the same CA for "gem install" :ssl_ca_cert: /etc/ssl/private-ca/corp-root-ca.pem
相关错误
state=error: certificate verify failed (unable to get local issuer certificate)Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems)state=error: certificate verify failed (self-signed certificate in certificate…Ruby openssl (Net::HTTP, Faraday, RubyGems)npm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLYnpm (Node.js)There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FA…pip