Python requests and (rapidssl) certificates

Today I learned that RapidSSL certificates aren't as widely supported on all clients as most others.

When changing an API endpoint URL for a project that used to run locally, non-ssl to a remote, ssl powered server, the code crashed with the error

[Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Now, I always thought that SSL was well supported on python, but that turns out to not always be the case. The fix isn't too obvious in my opinion.

It appears that the requests module ships with its own set of certificates ("cacert.pem"). It ignores system wide certificates, so adding certificates to /etc/ssl/certs on your ubuntu/debian system won't work. This may only be the case for pip installs of requests; if you install the requests module from system packages it may support the system wide certificates.

My solution, in the end, was to copy requests module's cacert.pem file, append two RapidSSL certificates to it (RapidSSL_Primary_Intermediate.crt and RapidSSL_Secondary_Intermediate.crt) and point the REQUESTS_CA_BUNDLE environment variable to it.

When using Django, you can actually do something like

os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(SOMEBASE, 'cacert.pem')

in your settings module.

The new certificates should now automatically apply to all requests. Alternatively, you can explicitly pass the location of the pem file using the 'verify' argument, but you'll have to be carefull to apply it everywhere where an SSL call may take place.


Last updated June 2, 2014, 2:24 p.m. | django requests rapidssl ubuntu python ssl
comments powered by Disqus