I have been provided with a pem certificate to authenticate with a third party. Authenticating using certificates is a new concept for me.
Inside are two certificates and a private key.
The issuer has advised they do not support SSL verification but use TLS(1.1/1.2).
I have run a script as below:
import requests as req import json url = 'https://url.com/call' certificate_file = "C:/certs/cert.pem" headers = {"Content-Type": "application/json"} req_body ={ "network":{ "network_id": 12345 }, "branch":{ "branch_id": 12345, }, "export_period":{ "start_date_time": "16-11-2021 00:00:00", "end_date_time": "17-11-2021 00:00:00" } } jsonObject = json.dumps(req_body) response = req.post(url,headers=headers,params=jsonObject,verify=certificate_file)
I’m getting the following error:
SSLError: HTTPSConnectionPool(host=’url.com, port=443): Max retries exceeded with url: /call?%7B%22network%22:%20%7B%22network_id%22:%2012345%7D,%20%22branch%22:%20%7B%22branch_id%22:%2012345%7D,%20%22export_period%22:%20%7B%22start_date_time%22:%20%2216-11-2021%2000:00:00%22,%20%22end_date_time%22:%20%2217-11-2021%2000:00:00%22%7D%7D (Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)’)))
Would appreciate guidance, my gut says I should be doing something specific for TLS hence the SSL error.
Advertisement
Answer
The issuer is using an up to date version of HTTPS – SSL is the commonly used term but TLS is the more correct one. Sounds like their setup is correct – meaning you need to call it with a trusted client certificate, as part of an HTTPS request.
I would recommend doing it with the curl tool first so that you can verify that the API works as expected.
curl -s -X GET "https://api.example.com/test" --cert ./certs/example.client.pem --key ./certs/example.client.key --cacert ./certs/ca.pem -H "Content-Type: application/json"
Split the certs into separate files as above. Sounds like one of them is a root certificate authority that you need to tell the client tech stack to trust – for curl this is done using the cacert
parameter as above.
Once this is working you can follow the same approach in the Python requests library. I believe this uses cert
and verify
parameters like this. So it looks like your code is not far off.
result = requests.get( 'https://api.example.com', cert=('example.pem', 'example.key'), verify='ca.pem')
MORE ABOUT MUTUAL TLS
Out of interest, if you ever want to demystify Mutual TLS and understand more, have a look at these advanced Curity resources:
These include an OpenSSL Script you can run, to see what the separated certificate files should look like.