hans_meine
hans_meine

Reputation: 1921

Add single certificate to requests

I am trying to connect to a corporate intranet HTTPS server, which uses an in-house CA, from within Python/requests running on a Linux machine. I have a .pem file that contains our certificate (4096 bit RSA, CSSM_KEYUSE_VERIFY, CA = true).

I put this into a subfolder of /usr/share/ca-certificates and used sudo dpkg-reconfigure ca-certificates in order to integrate it in the system.

In the requests documentation, I found:

You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs … If verify is set to a path to a directory, the directory must have been processed using the c_rehash utility supplied with OpenSSL.

I believe (but am not sure) that /etc/ssl/certs fulfills this condition.

Now, I tried requests in various ways:

requests.get(download_url)
# throws requests.exceptions.SSLError: ("bad handshake: Error([
#   ('SSL routines', 'ssl3_get_server_certificate',
#    'certificate verify failed')],)",)

requests.get(download_url, verify = False)
# works, but is obviously bad (and spits out a warning)

requests.get(download_url, verify = pem_file_path)
# same SSLError as above (option shows no effect)

requests.get(download_url, cert = pem_file_path)
requests.get(download_url, cert = '/etc/ssl/certs')
# both throw OpenSSL.SSL.Error: [
#   ('PEM routines', 'PEM_read_bio', 'no start line'),
#   ('SSL routines', 'SSL_CTX_use_PrivateKey_file', 'PEM lib')]

requests.get(download_url, verify = '/etc/ssl/certs')
# Finally, this raises an unprintable exception:
# requests.exceptions.SSLError: <exception str() failed>

Actually, using self-signed certificates with requests in python looks like it could describe the same problem (but is not answered yet).

Upvotes: 5

Views: 14174

Answers (1)

hans_meine
hans_meine

Reputation: 1921

Thanks to @stark, I found out that the problem was that my certificate file was expired. With the correct, up-to-date certificate (even in DER format, with the .cer extension), the following syntax now works:

requests.get(download_url, verify = cer_file_path)

Upvotes: 3

Related Questions