Python Friday #141: Read TLS/SSL Certificates in Python

We must renew TLS/SSL certificates before they reach their end of life. Otherwise, our users get an unfriendly message about an unsecure web page. Why not write a Python script that checks our sites and shows how many days are remaining for our certificates?

This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.

 

The challenge

While the requests package is the go-to helper for all things related to web requests, it does not allow us to read SSL certificates. Requests checks that the connection is secure, but it does not allow us to inspect the certificate with our own code. Therefore, we need to use sockets and work on a lower level of network traffic.

 

Preparation

For this application we need the socket and the ssl module. Both are part of Python, so we do not need to install them. The list domains allow us to check multiple sites in one go:

To store the data from the certificate, we use a named tuple:

 

Load the certificate

The main part of this application is to get the certificate. We must create an SSL context, wrap it around a socket with the host name we want to check and open the connection. From that connection we can read the certificate:

If everything works, we get a certificate for the domain we are interested in. Otherwise, the socket or the connection throw an exception that we will handle in the main block.

 

Read the certificate

The certificate offers its own challenges. Some parts we can access directly, like the expiration date. Other values, like the issuer, are hidden deep down the certificate and we need to rebuild a dictionary to access the values. We can put all the parts we are interested in into the named tuple CertificateInfo and save us the trouble of repeating the logic to access the certificate values everywhere in our code.

 

Show the result

With the main block we can create a basic report that tells us when the certificates will expire:

At the time of writing this post, I get these results:

ImproveAndRepeat.com, 2022-12-09, 80, Let’s Encrypt
python.org, 2022-10-24, 33, Let’s Encrypt
python-err.org getaddrinfo failed

I made a deliberate error with the third domain name and the error handling worked well enough to give us an error message without crashing our application.

 

An improved report

While the report works, it is hard to read and easy to misunderstand. Therefore, I like to use a Rich table to create a better looking report:

This creates a table in the console with headers and is easy to read:

The result as a table

 

Next

Working with sockets is not magic, but it needs a lot more knowledge of networking and how to establish a connection to a remote host. Luckily, working at this low level of the technology stack is most often not necessary. Next week we go to the other end of the network abstractions and look at Selenium to access the internet with a regular web browser.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.