Creating Self-Signed OpenSSL Certs in Python For Development

Do you need a quick way to generate OpenSSL self-signed certificates for your local projects? In this article, we’ll show you how to create a utility that automates the process. You’ll find the code you need to get started quickly and easily. This solution was developed as part of a script to set up self-signed certificates and virtual hosts on an Apache 2.4 installation on Windows.

First Step, Installing OpenSSL

Before we can have Python generate some certs for us, we have to install OpenSSL. One of the easiest ways to get this installed, along with other useful tools, is to use Git Bash. When you install this tool, you will get a lot of functionality for handling Git and it comes with OpenSSL out of the box. Start the process of installing that and once completed, we can use Python to run openssl commands.

Second Step, Wrap the Command In a Function

To make things a bit easier, we are going to wrap our OpenSSL command code in a function which we can call on to build keys for each site we create dynamically. We will make this function include two pieces of information. The first is a site slug we can use to identify the site (this might be a site slug used to setup folders and write to the hosts file and vhosts entries) and the path to where we would like to save the key/crt files. This is how the function may look…

import os
import subprocess

def generate_ssl_key(site_slug: str, destination_path: str,) -> None:
    command = [
        'openssl', 'req', '-new', '-x509', '-days', '3652',
        '-nodes',
        '-keyout', fr"{destination_path}\{site_slug}.key", '-out', fr"{destination_path}\{site_slug}.crt",
        '-subj', f"/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN={site_slug}.local"
    ]

    # Silence the output of openssl by sending it to devnull
    with open(os.devnull, 'wb') as null_file:
        subprocess.run(command, stdout=null_file, stderr=subprocess.STDOUT, check=True)

Explanation: This function will take a site slug that we will use to associate the files with a given site. We will also provide a destination path to tell openssl where we would like to put these keys once it generates them. To use this function, we will need to include both the “os” and “subprocess” modules. The command is setup to create a .key file and a .crt file. We are telling openssl to create the key that is a X.509 certificate instead of a .csr. We are currently issuing the license for about 10 years (adjust the -days parameter as you see fit). We are then using the destination path and the site slug to determine where we would like to save the certificate files.

As part of the process we are setting some details of the key issuer including the country code, state, city, company name etc. You can set these how you like. I have set this to be from Portland Oregon in the USA for the company “Company Name” and the certificate will be for the domain “sitename.local”. If your development environment is going to be configured differently, make sure the CN is setup to match the environment. For me a site would be something like “example.local”.

Lastly, OpenSSL is going to output a bunch of information as it creates the certificate and we want to silence that. What we did here is open up a stream to a special location that will essentially throw away whatever data we stream to it. In the *nix world this would be devnull but for our purpose we are calling it simply null_file.

The idea here is that we will direct the standard out stream to this null file and whatever openssl outputs will simply be thrown away and never displayed. In the case of error, we redirect the standard error stream to standard out which again is thrown away at the end. We use the subprocess.run() command to run our openssl command. This module is very useful for running processes, so take some time to look it up. The information there is priceless.

The Result

Once we have this all setup, calling this function is going to run the openssl command which will generate the certificate files in our destination path with the site_slug name and registered for our site_slug.local domain. The output openssl outputs will be silenced and will end. Because of the silencing, be sure to put in a quick print statement to let you know when it has ended.

Conclusion

In this article we talked about a quick way to generate local self-signed certs for our local web development projects using OpenSSL and Python. We provided some example code and ran through it to see how it works. Mixing this code along with code that then writes a vhosts entry to your Apache vhosts SSL conf file and writes to your hosts file to set site_slug.local to point to your local IP, you can quickly configure and launch your own development environments with a few keystrokes. I hope you found this little trick useful and something you can use in a bigger project to create your own web development environments using the power of Python!

If you’d like to support future articles, please check out our Programmers Idea Book and make a purchase. It’s full of project ideas that can help take your skills to the next level and well worth the investment. Thank you! 🙂

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 25 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.