Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Net::HTTP responds with OpenSSL::SSL::SSLError "certificate verify failed" after certificate renewal

We recently renewed the SSL certificate of our site, and the following occurs on Mac OS El Capitan 10.11.3:

require 'net/http'

Net::HTTP.get URI('https://www.google.com')
# => "<HTML>...</HTML>"

# The site whose certificate got renewed
Net::HTTP.get URI('https://www.example.com')
# => OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed

All my searches on Google and StackOverflow come up with answers suggesting a problem with the Ruby installation, but they seem to be related to older Ruby versions and I don't think this is the case here. Here is what I've tried:

  • brew update
  • brew upgrade openssl
  • rvm osx-ssl-certs update all
  • rvm install ruby-2.3.1 --disable-binary --with-openssl-dir="$(brew --prefix openssl)" (I did not have this version before)
  • rvm requirements
  • crlrefresh rpv to purge the OSX system wide CRL cache, per Uzbekjon's suggestion.

How can I resolve this?

Notes:

  • The problem does not occur on a freshly installed linux Docker container that has bare Ruby 2.2.3. So maybe it's something to do with Mac OS, or SSL local caching.
  • This issue might have existed before the certificate renewal. I cannot know for sure. However, the renewal did cause a similar problem with a 3rd party we're using as I discuss in this question.
  • The certificate installation was verified by Namecheap to be correct, online checkers show everything works, and all major browsers show the certificate as valid.

Solution

With much help from BoraMa, it is now clear what was happening. COMODO added a new root called COMODO RSA Certification Authority instead of the previous COMODO Certification Authority. The new root was not registered within Mac's keychain, causing this issue.

One way we attempted to debug this was by running:

openssl s_client -connect www.mysite.com:443

Which showed a warning verify error:num=20:unable to get local issuer certificate. This warning is not an issue, as openssl s_client does not use any certificates by default. Running the following was able to prevent the warning after downloading the certificate from COMODO into comodo.pem (index here):

openssl s_client -connect www.mysite.com:443 -CAfile comodo.pem

However, this could not and did not affect Ruby OpenSSL interface. This article made things much clearer for me, and the SSL doctor script created by its author was also helpful, as it confirmed the hypothesis. The article suggested to look at OpenSSL::X509::DEFAULT_CERT_FILE, which for me was /usr/local/etc/openssl/cert.pem. That file did not exist on my machine, which meant Apple's patch for OpendSSL was using the Keychain App. For whatever reason, importing comodo.pem into my keychain and marking it as trusted based on this post did not work.

So, the solution was to create the cert.pem file manually. I went to the keychain app, and exported all System Root certificates to system_root.pem. Then: cat system_root.pem comodo.pem > cert.pem and moving that file to /usr/local/etc/openssl/ did the trick. Running Net::HTTP.get in Ruby no longer failed.

like image 550
AmitA Avatar asked May 01 '16 12:05

AmitA


1 Answers

I would try to double-check the trusted certificate store if it contains the COMODO_RSA_Certification_Authority.pem certificate. In my (Linux) setup, the site works OK but when I temporarily remove the certificate of the COMODO cert authority from the cert store, I get exactly the same error as you (while in browsers it still works as they have their own cert stores).

BTW, the same error is also recognizable using curl as it also appears to use the same trusted cert store as ruby, so you might first ensure that the site works under curl.

In linux, the cert store is located usually in /etc/ssl/certs whereas under OSX it should probably be /System/Library/OpenSSL (see this article for other options).

You should see something like the following in the cert store directory:

root@apsara:/etc/ssl/certs$ ls -l | grep COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root     73 úno 28 10:24 COMODO_RSA_Certification_Authority.pem -> /usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
lrwxrwxrwx 1 root root     38 úno 28 10:24 d4c339cb.0 -> COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root     38 úno 28 10:24 d6325660.0 -> COMODO_RSA_Certification_Authority.pem

The following is a snipped of some attributes of this root CA certificate:

$ openssl x509 -in COMODO_RSA_Certification_Authority.pem -noout -text
Certificate:
Data:
    Version: 3 (0x2)
    Serial Number:
        4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
Signature Algorithm: sha384WithRSAEncryption
    Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
    Validity
        Not Before: Jan 19 00:00:00 2010 GMT
        Not After : Jan 18 23:59:59 2038 GMT
    Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
            Public-Key: (4096 bit)
            Modulus:
                00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf:
                ...
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Key Identifier: 
            BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
        X509v3 Key Usage: critical
            Certificate Sign, CRL Sign
        X509v3 Basic Constraints: critical
            CA:TRUE
Signature Algorithm: sha384WithRSAEncryption
     ...

The certificate can be downloaded from Comodo here (index of all certs is here).

More info: while looking into it, it turns out that there are actually two distinct certification chains for certs by the Comodo CA. One, the older one, is the one with the root CA listed above. The newer validation chain uses "External CA root" certificates in the chain. This forum post explains further, with specific instructions for OSX for marking those certs as trusted.

like image 109
Matouš Borák Avatar answered Oct 19 '22 10:10

Matouš Borák