Skip to the content.

Creating certificates for SSL/TLS protected services

Creating a certificate without a root CA

If you dont need to have your self signed cert signed by a Root CA in order to have that root CA added to your certificate store and trusted by your client, you can generate a key and cert in a fairly simple fashion.

First, set some environment variables with your chosen hostname and IP address, these will be added to the CN and SAN fields in the cert

export DEVICENAME='hostname'
export IP='192.168.0.1'

If you want the key and cert in seperate files device.key for the private key, device.pem for the certificate, run the following:

openssl req -x509 -newkey rsa:4096 -keyout device1.key -out device1.pem -sha256 -days 1826 -nodes -subj "/C=AU/ST=A.C.T./L=Canberra/O=Secops/OU=Org/CN=$DEVICENAME" -extensions SAN -config <(cat /etc/ssl/openssl.cnf && printf "\n[SAN]\nsubjectAltName=DNS:$DEVICENAME,DNS:$IP")

I have filled in details above for the location, organisation, organisational unit, and have included subject alternative name values for both the IP address and hostname in the above. Feel free to change these as required, remove the SAN for the IP address, etc.

Alternatively to the above, you can also combine the key and cert into the same file server1.pem, by setting the keyout and newkey to the same pem file by either running openssl as shown below, or by concatenating the files together, with the key file first:

openssl req -x509 -newkey rsa:4096 -keyout server1.pem -out server1.pem -sha256 -days 1826 -nodes -subj "/C=AU/ST=A.C.T./L=Canberra/O=Secops/OU=Org/CN=$DEVICENAME" -extensions SAN -config <(cat /etc/ssl/openssl.cnf && printf "\n[SAN]\nsubjectAltName=DNS:$DEVICENAME,DNS:$IP")

Creating a certificate signed with a root CA you create

If you want your certificate signed using a root CA you create, so that you can add that root CA to a trust store so that client software trusts it, you need to create the CA and then sign a certificate request.

Create the Root CA key and Cert:

Run the following one-liner, to create a root CA certificate rootca.pem and a root CA private key rootca.key:

openssl req -x509 -newkey rsa:4096 -sha256 -keyout rootca.key -out rootca.pem -days 1826 -nodes -subj "/C=AU/ST=A.C.T./L=Canberra/O=Secops/OU=Org/CN=RootCA"

The subject details of the root CA have been filled in with example values in the above, feel free to change them as required.

Create the device key, csr, and then sign it with the RootCA cert:

This will create a certificate with common name and alternative names set to the correct values.

Set some environment variables with your chosen hostname and IP address, these will be added to the CN and SAN fields in the cert

export DEVICENAME='hostname'
export IP='192.168.0.1'

Now run the following commands to generate a device key, and create the certificate signing request:

openssl genrsa -out device.key 4096
openssl req -new -sha256 -key device.key -out device.csr -subj "/C=AU/ST=A.C.T./L=Canberra/O=Secops/OU=Org/CN=$DEVICENAME" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf && printf "\n[SAN]\nsubjectAltName=DNS:$DEVICENAME,DNS:$IP")

I have filled in details above for the location, organisation, organisational unit, and have included subject alternative name values for both the IP address and hostname in the above. Feel free to change these as required, remove the SAN for the IP address, etc.

The above will create a key for the servers certificate device.key, and a certificate signing request device.csr with all of the specified details like common name, SANs etc, that will end up in the final certificate.

The last step is to create a certificate device.pem signed by the root CA based on details in the signing request:

openssl x509 -req -in device.csr -CA rootca.pem -CAkey rootca.key -CAcreateserial -out device.pem -days 1826 -sha256 -extensions SAN -extfile <(cat /etc/ssl/openssl.cnf && printf "\n[SAN]\nsubjectAltName=DNS:$DEVICENAME,DNS:$IP") 

Again, I have included details on the alternative names for the final certificate in the command above, change them as required for your purposes.

As a final step, you may want to have the server key and certificate chain included in one file, server.pem, for easy use in certain servers, which you can do by concatenating the required files together, with the key first followed by certificates in order up the chain ending with the root CA certificate:

cat device.key device.pem rootca.pem > server.pem

Trust a root CA signed certificate

On Ubuntu to add the signing Root CA to the local stores so it is trusted (The filename must end in .crt to be recognised, but the rest of the name doesn’t matter too much):

sudo cp rootca.pem /usr/share/ca-certificates/rootca.crt 
sudo cp rootca.pem /usr/local/share/ca-certificates/rootca.crt

Then run the following commands to import the certificates into the various places that various components of Ubuntu look.

sudo dpkg-reconfigure ca-certificates
sudo update-ca-certificates

If a Python application needs to trust the certificate, it may use the system store, or if the certifi module is installed it will use its own certificates file. You can find where it is using:

>>> import certifi
>>> certifi.where()

For Python requests, you can specify an alternate CA Bundle via an environment variable:

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

You can also append to the end of the certifi store using something like the following:

(cat /usr/local/lib/python3.5/dist-packages/certifi/cacert.pem && printf "\n" && cat rootca.pem )| sudo tee /usr/local/lib/python3.5/dist-packages/certifi/cacert.pem > /dev/null

Checking the certificate or certificate signing request you created

If you want to see the details of the certificate file you created, say server.pem, run openssl like below

openssl x509 -in server.pem -text -noout

To look at whats in a certificate signing request device.csr, run openssl like below:

openssl req -text -noout -verify -in device.csr