I was setting up my environment to write a quick API wrapper in Ruby 2.2.1. On paper, that should be an easy task: install rvm, then do rvm install 2.2, create your dotfiles, gemset, write a couple lines of code and you're testing that API.
Then the API fails with some weird certificate error, but your browser does not complain. Time to discern if your HTTP gem is the problem. A quick way to tell if Ruby itself has SSL issues is using irb to request some HTTPS site like Google or Github:
Now, we know that the issue is on the base Ruby and not some gem. Also, we can tell that the issue has something to be with OpenSSL.
OpenSSL and OSX
Apple has deprecated usage of OpenSSL on OSX since version 10.7 Lion and migrated to their own library called Common Crypto. Honestly, based on my expexperience with OpenSSL, I can't blame them.
On my Mac computers, running OSX 10.11 El Capitan, there's still an OpenSSL installation to be found:
The problem here is that Certificate Authorities are not updated by Apple since they assume you'll be using Common Crypto. This is the underlying issue with Ruby when installed by RVM: the binaries were linked against this outdated OpenSSL library. Also, I assume it was compiled statically, because even manually updating certificates for OpenSSL does not fix the issue.
Fortunately, RVM gives us the option of ignoring precompiled binary versions of Ruby and just download the source code and complile it on our own system instead. But, in order for us to compile against an up-to-date CAs list, we need to update OpenSSL beforehand.
I recommend doing so by installing OpenSSL's last Homebrew package. If you already have OpenSSL installed, I recommend removing it altogether. Please notice that it's possible that just issuing an uninstall command may not suffice. We want to uninstall ALL versions of OpenSSL with uninstall --force:
We can now install OpenSSL again. The brew formula is actually very well thought because it will automatically import Common Crypto's CAs into OpenSSL at installation time. This means we'll be using the very same lists Apple (and most apps) are using:
Now, it's time to reinstall Ruby, compiling it against our up-to-date OpenSSL. First, we'll remove the current Ruby installation:
And then we'll install it again with the --disable-binary flag, so it compiles from source:
Now, let's test an HTTPS site to check that we've got it fixed: