Mac + OpenSSL (homebrew) + rbenvという環境でNet::HTTP使ってSSLでの通信をしようと思ったらエラーがでた。
net/http.rb:917:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
たとえば、こんな感じのコードでhttpsなURLにアクセスする場合。
require 'net/https' require 'uri' url = URI.parse('https://www.google.co.jp/') https = Net::HTTP.new(url.host, url.port) https.use_ssl = true https.start do |http| res = http.get('/') puts res.body end
そういえば前にもこのエラー見たなぁとも思いながら調べてみる。
ようするに、クライアント側にバンドルされるべきの証明書がないのが原因らしい。
Rubyが見に行く証明書のパスは”/usr/local/etc/openssl/cert.pem”だけど、実際にはファイルはない。
% ruby -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE' "/usr/local/etc/openssl/cert.pem" % ls /usr/local/etc/openssl/cert.pem ls: /usr/local/etc/openssl/cert.pem: No such file or directory
ちなみにCentOS6.4ではちゃんとファイルがあるので動作する。
RPM的にはca-certificatesというパッケージでインストールされている。
% ruby -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE' "/etc/pki/tls/cert.pem" % ls /etc/pki/tls/cert.pem /etc/pki/tls/cert.pem@ % ls -l /etc/pki/tls/cert.pem lrwxrwxrwx. 1 root 19 4月 21 14:45 2012 /etc/pki/tls/cert.pem -> certs/ca-bundle.crt % rpm -qf /etc/pki/tls/certs/ca-bundle.crt ca-certificates-2010.63-3.el6_1.5.noarch
MacにhomebrewでインストールしてもCA証明書はインストールされないということのようだ。
curlのサイトが配布してくれているPEM形式のCA証明書をRubyが読み込んでいるパスに保存してあげる。
curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/etc/openssl/cert.pem
中身の冒頭を読むとわかるようにこの証明書はMozillaが配布しているルート証明書をcurlなどが使えるようにPEMの形式に自動的に変換したものだ。
Automatically converted CA Certs from mozilla.org
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla’s root certificates
## file (certdata.txt). This file can be found in the mozilla source tree:
## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
これで、エラーが出ずにNet::HTTPをつかってSSLでアクセスできるようになった。
curlでもhttps://www.google.co.jpにアクセスできるので、ローカルのどこかにCA証明書があるはずなんだけど、それは見つけられなかった・・・
参考記事
library net/https – Ruby 2.0.0 リファレンスマニュアル
Ruby の OpenSSL ライブラリで証明書のエラー – happy lie, happy life
"Certificate verify failed" OpenSSL error when using Ruby 1.9.3 – Stack Overflow
関連記事
- None Found