When working on your Rails app or when installing gems, you might get this Ruby SSL error
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
This error, as you can see on the message, has something to do with SSL and certificates. First, let’s discuss why you need to use SSL. When your app connects to a 3rd-party API or when gem
If you don’t use the HTTPS version and use the non-secure HTTP version, the data you receive can be altered by anyone on the path from the user to your server. And you wouldn’t know it was altered. If you request a gem from http://rubygems.org from your
In short, you should always use HTTPS, which is secured using an SSL certificate.
Secure Sockets Layer or SSL is the security protocol that provides secure communication between two machines. In the cases above, between the machines of your app and the 3rd-party API or between your machine and the rubygems.org machine.
How does SSL work? Machine 1 initiates the connection and looks at the SSL certificate of machine 2. This certificate contains numbers that machine 1 will use to encrypt their communication. This is a simple and incomplete description of the whole process. We’ll not go into details on how the encryption or the SSL handshake works.
The encrypted communication makes sure that what you send to the server and vice versa isn’t altered. However, the initial connection is done in clear text since it comes before encrypted communication is set up. So, while you’re sure that communication is secure, how do you know you’re talking to the correct server?
SSL certificates are signed by a Certificate Authority. The signature tells you that the certificates are real. The Certificate Authorities are also signed for the same reason. This can go on until you reach a root certificate. This setup creates a chain of trust. As long as you trust the root certificate, you can trust the certificate of the website you’re communicating with.
The root certificates are installed on your machine and there’s an implied trust that the existing certificates are valid.
When machine 1 connects to machine 2, machine 1 has to verify that the certificate is real. If this verification fails, you’ll get the certificate verify failed
When verification fails, it can mean one of two things. Either your machine doesn’t have the correct root certificates or you’re connecting to a URL that has a problem with the certificates.
If it’s the latter, the best (if not only) option is to ask the 3rd-party site to fix their certificates. The solutions mentioned below are for the first scenario where the problem is on your machine.
Scale performance. Not price. Try Engine Yard today and enjoy our great support and huge scaling potential for 14 days.
Deploy your app for free with Engine Yard.
The Problem
The certificate verify failed
When developing Rails applications, this can happen when
- you
run gem install
or bundle install
. Your machine needs to connect to the gem sources like https://rubygems.org - your app connects to a 3rd-party API like GitHub API
- you use a gem like ActiveMerchant to connect to payment sites like PayPal
Solutions
Update CA certificates
The correct solution depends on which code connects to an HTTPS URL. The first thing you can try is to update the root certificates on your machine.
If you’re using Linux, you can use your package manager to update the CA certificates.
apt-get update ca-certificates
yum update ca-certificates
On RVM on OSX, you can run
rvm osx-ssl-certs update all
If you don’t use RVM, you can extract the certificates from Apple’s Keychain yourself.
cert_file='$( openssl version -d | awk -F''' '{print $2}' )/cert.pem'
mkdir -p '${cert_file%/*}'
security find-certificate -a -p /Library/Keychains/System.keychain > '$cert_file'
security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> '$cert_file'
For more information, check out the SSL documentation.
Update Gems
In some cases, updating the system CA certificates
rubygems.org in 2014 had to update their SSL certificate. RubyGems also provides CA certificates and a newer RubyGems version had to be manually installed to get it working again. You can read more about this issue in the Ruby Gems guides here. This is unlikely to happen again but if you’re having issues with RubyGems, check your system certificates first then the RubyGems issues.
Bad Solutions
There are other solutions to this error but are not considered best practices.
Turn off verification
You can turn off verification when using net-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
Use http version
When you encounter certificate verify failed
http://rubygems.org
https://rubygems.org
Set SSL_CERT_FILE
This isn’t a bad solution if you know what you’re doing. However, there are a lot of solutions out there that suggest downloading CA certificates to your machine and setting SSL_CERT_FILE
The problem with this approach is you don’t know if you can trust the CA certificates you’re downloading. In some cases, the CA certificates are even downloaded in clear text. Double trouble if you ask me.
Summary
The Ruby OpenSSL certificate verify failed
If you are interested on security issues, make sure to check out this Engine Yard’s blog section