I'm trying to scrape an endpoint that requires an SSL certificate for authentication. When I try accessing the site in the browser, a window comes up where I select the certificate to be sent with the request. When downloading the webpage, I've tried doing:
import urllib
urllib.request.urlopen("https://mywebpage.com/some/endpoint", cafile = "C:/Users/Me/path/to/my/cert.p12")
but I got the following error:
ssl.SSLError: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4149)
I thought this might be because I was sending a PKCS12 instead of a PEM file, so I did the following:
openssl pkcs12 -in "C:/Users/Me/path/to/my/cert.p12" -out "C:/Users/Me/path/to/my/cert.pem"
I provided the same value for the PKCS12 passphrase and the PEM password. I then tried doing this:
import urllib
urllib.request.urlopen("https://mywebpage.com/some/endpoint", cafile = "C:/Users/Me/path/to/my/cert.pem")
However, this returns the following SSL error:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)
When I do ssl.SSLContext().load_verify_locations(cafile = "C:/Users/Me/path/to/my/cert.pem")
I get no errors and the certificate information seems to load.
I then decided to try getting around the issue and tried searching for the specific SSL error. I came across this SO question. Since I'm using Windows, my version of OpenSSL is likely configured to be different from what Python is expecting, so I tried doing the following:
import ssl
import certifi
from urllib import request
request.urlopen("https://mywebpage.com/some/endpoint",
context = ssl.create_default_context(cafile = certifi.where()))
but this returned the following SSL error:
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1007)
So, what am I doing wrong here? It appears that the server was unable to verify the SSL certificate I sent with the request but, when I check it, it appears to match. How can I make this request work?