Reputation: 41
I'm using a REST API from euronext.com, to go any further I need to verify the server certificate and send my own client certificate through the module requests.
I already did some testing with curl, both .crt/.pem files were accepted.
But requests is still throwing :
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): saturn-api-h.euronext.com
Traceback (most recent call last):
File "C:\python36\lib\site-packages\urllib3\contrib\pyopenssl.py", line 441, in wrap_socket
cnx.do_handshake()
File "C:\python36\lib\site-packages\OpenSSL\SSL.py", line 1806, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "C:\python36\lib\site-packages\OpenSSL\SSL.py", line 1546, in _raise_ssl_error
_raise_current_error()
File "C:\python36\lib\site-packages\OpenSSL\_util.py", line 54, in exception_from_error_queue
raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')]
What I did try to solve the issue :
Working curl:
curl -i -vvv -X POST https://saturn-api-h.euronext.com/SaturnWebServices/rest/Authentication/AuthenticateUser -H "Content-Type: application/json" --cert ./client.crt --cacert ./digicert-full-chain.crt
With a valid Authorization headers it return a 200 status code, without it 401 "Access denied!". If the certificate validation fails, it redirects to euronext.com with status code 302.
Problematic python:
endpoint = 'https://saturn-api-h.euronext.com/SaturnWebServices/rest/Authentication/AuthenticateUser'
headers = { 'Content-Type': 'application/json', } #'Authorization': 'Basic <auth_string>',
r = requests.post(endpoint, headers = headers, verify = './digicert-full-chain.crt', cert = './client.crt')
Certificates:
digicert-full-chain.crt is containing the full chain from DigiCert:
client.crt is containg our certificate and its key.
Why is curl command working whereas python's requests module is failling?
Is there any way to show the complete handshake process from the requests module?
Upvotes: 2
Views: 2582
Reputation: 41
I solved the problem myself, a certificate was missing from the full chain.
Doing /usr/local/lib/python3.4/dist-packages/certifi/cacert.pem > certifi-digicert.pem; digicert-full-chain.pem >> certifi-digicert.pem
and passing the resulting certificate to the verify argument worked.
As a side note, I used the strace command to compare certificate locations from both python and curl:
strace <python_command> |& grep open | grep -E 'crt|pem'
strace <curl_command> |& grep open | grep -E 'crt|pem'
I also checked with Wireshark to get the full handshake process, the pyOpenSSL module was getting an error after the server's Certificate Request. Alert (Level: Fatal, Description: Unknown CA)
.
Upvotes: 2