Python using system SSL certificates?

jamstooks picture jamstooks · Jun 1, 2015 · Viewed 18.7k times · Source

I ran into the recent Authorize.net SSL certificate invalidation debacle last week.

I've been able to get curl to accept their certificate finally:

$ curl -Iv https://secure.authorize.net
...
*  SSL certificate verify ok.
...

but python is still rejecting it with requests:

>>> requests.get('https://secure.authorize.net', verify=True)
...
  InsecurePlatformWarning

and in my code:

File "/usr/lib/python2.7/ssl.py", line 405, in do_handshake
    self._sslobj.do_handshake()
SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Can anyone tell me why python doesn't seem to be using the system certificates for validation? Any ideas on a fix?

EDIT

I am using Ubuntu and installed the certificate this way:

sudo curl -o /usr/local/share/ca-certificates/entrust_ssl_ca.crt https://www.entrust.net/downloads/binary/entrust_ssl_ca.cer
sudo update-ca-certificates

after running this, curl worked properly, but python still didn't recognize the certificate.

Answer

larsks picture larsks · Jun 1, 2015

You don't mention what OS you're using or where you installed the certificates to make them available to Curl.

I used strace on my system to see where Python is looking for certificates. On my Fedora system Python is using/etc/pki/tls/certs/ca-bundle.crt, which is the standard location on Fedora, Red Hat, and similar systems.

On Ubuntu, Python is looking in /etc/ssl/certs/ca-certificates.crt.

According to the documentation:

You can pass verify the path to a CA_BUNDLE file with certificates of trusted CAs. This list of trusted CAs can also be specified through the REQUESTS_CA_BUNDLE environment variable.

...so you could provide your application with a list of CA certificates that is independent of what is installed on the system.

Update

Running openssl s_client -showcerts -connect secure.authorize.net:443 shows that the *.authorize.net certificate is signed by the "Entrust Certification Authority - L1K" certificate, which is signed by the "Entrust Root Certification Authority - G2" certificate, which is signed by the "Entrust Root Certification Authority" certificate. The certificate you have installed as entrust_ssl_ca.crt is the "Entrust.net Secure Server Certification Authority", which is "none of the above".

I would just visit http://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/ and download everything, but the top-level certificate in the above chain is this one. That's the second certificate listed on the downloads page.