There is trouble brewing, or: Openssl issues on Ruby with Homebrew

This post is to describe an issue I’ve run into using < 2.3 versions of Ruby on OSX with rvm and brew.

Don’t even get me started on working with older versions of Ruby — we have some maintenance projects running in ruby-1.8.3! Even modern Rubies may give you a hard time, however, and this is one of the times. Actually, I am writing this post as a reminder for me because I ran into the same problem twice now, and what is worse, the second time it took me nearly the same amount of fruitless googling to solve it as it took the first. And the solution was the same! So, let us proceed with order.

After system-wide update of openssl using Homebrew on OSX Yosemite I encountered this problem bundling a Ruby 2.2 project:


$bundle
Fetching source index from https://rubygems.org/
Retrying fetcher due to error (2/4): Bundler::Fetcher::CertificateFailureError Could not verify the SSL certificate for https://rubygems.org/.
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. For information about OpenSSL certificates, see http://bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile sources and change 'https' to 'http'.

This is somehow disconcerting if, as it happened with me, everything else (including other versions of Ruby) were working happily and not complaining about CA certificates in any way. So what I did was rvm removeing and rvm installing the offending Ruby. But it did not work! This time, as soon as I tried to gem install bundle

(Gem::RemoteFetcher::FetchError)
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/specs.4.8.gz)

A word of warning: Googling this will immediately point you to this Rubygems troubleshooting page, don’t go there as it won’t solve your problem. It is actually misleading as the strategy proposed for manually updating the certificate tells you to look inside the /{ruby-version}/rubygems/ssl-cert directory — as we will see, this is not the right place to look.

The situation is all the more strange since if you try to directly connect to rubygems:

openssl s_client -showcerts -connect rubygems.org:https

it works flawlessly. This, however, is actually a step towards the light, because it points you to the fact that it is ruby who is fetching the wrong certificate.

You can make sure the diagnosis is right by running:

ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE'

(even more useful if you can compare it with a different and working Ruby version).
The right path should be /usr/local/etc/openssl/cert.pem (the path to the Homebrew version of openssl) so if you instead find that the output of the previous command is /etc/openssl/cert.pem (path to the system version), that’s a sure sign that the problem lies with the Ruby install.

The key here is that the rvm install of some Rubies (in my case the black sheep was Ruby 2.2.1) come with pre-compiled binaries that reference the system version of openssl. So if you have openssl installed with Homebrew, you need to compile the Ruby onto your system on install in order to make sure it will reference the correct version.

So, the solution is simple enough: if the problem persists after a plain rvm install, try installing from source using the --disable-binary flag:

rvm install 2.2.1 --disable-binary

Now you can verify that the path to certificates is the correct one:

$ ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE'
/usr/local/etc/openssl/cert.pem

And your bundle should now work smoothly (after you gem install bundler, obviously!).

TL;DR

If you have certificate problems with Ruby after updating Openssl with Homebrew you should rvm uninstall Ruby and then

rvm install ruby-version-you-need --disable-binary

to make sure the Homebrew version of Openssl is linked inside the Ruby install

Leave a Reply

Sort by:   newest | oldest | most voted
Andrea Longhi
Editor

Thank you for the post, unfortunately my issue required still a different solution.

After installing the Bundler gem, I got a message saying that my CA certificates were outdated, expired sometime in the past. After googling and trying another hundred solutions, I found the one that worked for me:

$ sudo security delete-certificate -Z 2F173F7DE99667AFA57AF80AA2D1B12FAC830338 /System/Library/Keychains/SystemRootCertificates.keychain
$ brew postinstall openssl

Credits goes to this github link

wpDiscuz