Self-Signed Certificates and Urllib with Python - python

I have a self-signed certificate file, and I need to make requests to a REST endpoint that requires the certificate. How do I pass this information using the standard python 2.7.x libraries?
Is there a way I can check if the current user has the self-signed certificate installed in the certificate store on Windows? If so, can I grab the certificate?
How do you just use urllib/urllib2 to pass a self-signed certificate?
Thank you

Related

Python: How can I combine requests and windows certificate store for Client Side Certificates

I'd like to use client side certificates from pythons requests lib (https://requests.readthedocs.io/en/master/user/advanced/#client-side-certificates) on my windows system.
The cert itself is stored in windows cert store.
What's the best way to access this cert and pass it to requests?
Thanks for your help.

Python Requests with wincertstore

I'm trying to connect to my corporate's internal webpages through the requests package, but since python does not use the windows default trusted certificates the connection is denied. I found out that wincertstore can be used to fetch the windows default certificates. But I'm still not sure how to use that along with the my request. Below is the code I have tried so far.............
import requests, socket, atexit, ssl, wincertstore
from requests.auth import HTTPBasicAuth
certfile = wincertstore.CertFile()
certfile.addstore("CA")
certfile.addstore("ROOT")
atexit.register(certfile.close)
ssl_sock = ssl.wrap_socket(s,ca_certs=certfile.name,
cert_reqs=ssl.CERT_REQUIRED)
requests.get(url)
I get the following error...................
requests.exceptions.SSLError: HTTPSConnectionPool(host='myhost', port=443): Max retries exceeded with url: myurl (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))
I am able to use wget on the same url and download the content.
wget --no check certificate --user=my username --password=my password URL
But I am not interested in downloading the content as I only need to scrape a small portion of the webpage content.
Pythin version = 3.6.5
Wincertstore link - Link
Thanks in advance for your help..............
I had a similar issue and fixed it using the python-certifi-win32 package (now out of maintenance):
As of 2022 (as mentioned by Briareos386 in the comments)
pip install pip-system-certs
Original answer (out of maintenance)
pip install python-certifi-win32
now you can just use:
requests.get(url, verify=True)
and the certificate is checked using the Windows Certificate Store.
Note:
This only works if the certificate is installed in the Windows Certificate Store...
This is all explained in the SSL Cert Verification section of the requests docs.
By default, requests uses the certs from certifi if present, falling back to whatever urllib3 thinks is your OS cert store, which itself falls back on whatever Python thinks it is (although in older versions it often didn't).
Your company apparently has a private, maybe even self-signed, cert, which isn't going to be in certifi. It might be in the Windows cert store—in which case urllib3 should automatically pick it up—but I suspect that it isn't. Maybe the cert is installed directly into some custom browser setup your IT department forces you to use, instead of into the OS store. Or maybe it's not installed at all. (You didn't mention being able to access this site in a browser without seeing a broken-lock icon…)
You're passing --no check certificate (or, more likely, --no-check-certificate?) to wget, so you're just not verifying SSL. And if you want to do the same thing in requests, that's just:
requests.get(url, verify=False)
If you're pretty sure that you do have the cert installed, even though wget can't find it… well, your code isn't going to work as written. Here's what would work:
Ignore the cert and just disable validation, as shown above.
Figure out where the relevant cert actually is installed and how to load it, and:
Pass it as the verify argument on every requests call.
Set it up somewhere statically and pass it in an environment variable.
Install it into your default cert store so everything works automatically.
Write an HTTPAdapter that installs it into your requests session.
First, your code is just trying to get the default cert in exactly the same way Python already does. That wincertstore module is just a backport of what's already builtin to Python 3.4+.
Second, all your code is doing is getting a cert, using it to create an SSL socket, ignoring that socket, and telling requests to do its normal thing. That isn't going to help anything. If you want to pass a cert to requests, you either do this:
requests.get(url, verify='/path/to/cert')
… or put it in the environment variable REQUESTS_CA_BUNDLE
… or do the HTTPAdapter code that I showed you in chat (and which you found an old, non-working version of somewhere unspecified). See HTTPAdapter in the docs if you actually want to do that.
In my case (Windows 10 + Python 3.10.2 + Elasticsearch 8.0.1)
When I ran the code below
requests.get('https://192.168.1.3:9200')
I got this error
Caused by SSLError(SSLCertVerificationError(1, '[SSL:
CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed
certificate in certificate chain (_ssl.c:997)')))
I tried previous solutions but none of them worked for me. I could fix the problem after adding Kibana's CA SSL certificate into Python's default certificate store.
Kibana's CA SSL can be found in your Kibana config file (kibana.yml > elasticsearch.ssl.certificateAuthorities)
Python's default certificate store can be found with this Python code
certifi.where()
Then copy the Kibana's CA certificate content and
paste it into the cacert.pem file.
Then it worked for me.

Install a trusted root certificate in PhantomJS

Is it possible to start a selenium PhantomJS session with a specific certificate?
Right now if I run it with PhantomJS I get Missing certficate. Adding --ignore-ssl-errors is not an option, this site needs the certificate.
I can use Chrome or Firefox and install the certificate first and then call webdriver.Chrome() and it will work, but is it possible to do this with PhantomJS?
I assume that you mean the use of client certificates, not the specification of other trusted CAs for validation of the servers certificate. Client certificates are not implemented (see what is the correct way to feed an ssl certificate into phantomjs) while different trusted CA can be specified with the --ssl-certificates-path option.

Connect to IIS server using .pfx certificate

Hi I am new to SSL and I am trying to connect to an IIS ASP.NET web server which has issued to me a unique .pfx certificate to verify me to the server.
Using a browser where I have installed the certificate I am able to connect the site where I have to upload a file on a daily basis.
I am trying to write a python script to do the same task. I have tried to use the Python Mechanize library.
While adding certificate I converted the .pfx file to .key and .cer PEM file so that it could be attached to add_client_certificate method, but later, I found out that IIS server accepts only .pfx certificate and there is no way to attach a .pfx certificate directly to the Mechanize browser instance.
Is there a way or another library where I can do this task?
You can use requests library
import requests
requests.get("https://your_server", cert=('client01.cer', 'client01.key'))

How to add client certificate using python mechanize

I am a client to a secured HTTPS server who has issued to me a password protected .pfx certificate to identify me to its system every-time. Using browser where I have installed the certificate (apparently only IE6 and previous versions works) i am able to log in and upload a file which i need to do on a daily basis. Right now am trying to write a Python script to do the same task and I am not sure if it is doable this way.
I am trying to use python mechanize library to connect to the server.
Using OpenSSL I have broken down the .pfx file into .key and .cer PEM files.
And I am using them as certificate for my python script.
Here is my code snippet
br = mechanize.Browser()
br.add_client_certificate(host,"I:/Key.key","I:/certificate.crt:")
whatever I tried it throws various SSL exception .. namely
SSL_CTX_use_certificate_chain_file
SSL_CTX_use_PrivateKey_file
Can anyone please tell me what possibly I could be doing wrong or if at all this is not the right approach.
I was able to get rid of errors by ways described in this link.
It didn't solve my purpose though because the server I was trying to connect is a IIS based server and it only accepts .pfx certificates.

Categories

Resources