Originally posted on ixa.io
We recently had to work around an issue integrating with a service that did not provide the full SSL certificate chain. That is to say it had the server certificate installed but not the intermediate certificate required to chain back up to the root. As a result we could not verify the SSL connection.
Not a concern, we thought, we can just pass the appropriate intermediate certificate as the CA cert using the verify keyword to Requests. This is after all what we do in test with our custom root CA.
response = requests.post(url, body, verify=settings.INTERMEDIATE_CA_FILE)
While this worked using curl and the openssl command it continued not to work in Python. Python instead gave us a vague error about certificate validity. openssl is actually giving us the answer though by showing the root CA in the trust chain.
The problem it turns out is that you need to provide the path back to a root CA (the certificate not issued by somebody else). The openssl command does this by including the system root CAs when it considers the CA you supply, but Python considers only the CAs your provide in your new bundle. Concatenate the two certificates together into a bundle:
-----BEGIN CERTIFICATE----- INTERMEDIATE CA CERT -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- ROOT CA CERT THAT ISSUES THE INTERMEDIATE CA CERT -----END CERTIFICATE-----
Pass this bundle to the verify keyword.
You can read up about Intermediate Certificates on Wikipedia.