Script to Generate Self-Signed Certificates Automatically – July 26, 2020

I always have trouble remembering how to make self-signed certificates, and there are a million different webpages devoted to doing so, but they all do it a little differently, and don't always, work, so here is the millionth-and-one web page, but at least it will work for me.

The features I care about are using private IP addresses, private DNS names, public DNS names, a root authority that needs to be imported into the browser's trusted certificates, and remembering/auto-filling passwords automatically.

Here is my config:

#!/bin/bash
set -e
set -u

ROOT=MyRootCA
SERVER=MyClient1

if [ -f $ROOT.pem ] ; then
  echo "Regenerate root certificate too? (Y/n)"
  read confirm
fi

if [ "${confirm:-Y}" == "Y" ]; then
  echo "Generating root certificate..."
  openssl genrsa -out $ROOT.key 2048
  openssl req -x509 -new -nodes -key $ROOT.key -sha256 -days 1024 -out $ROOT.pem -config $ROOT.req
fi

echo "Generating server certificate..."
openssl genrsa -out $SERVER.key 2048
openssl req -new -key $SERVER.key -out $SERVER.csr -config $SERVER.req
openssl x509 -req -days 730 -CA $ROOT.pem -CAkey $ROOT.key -CAcreateserial -out $SERVER.pem -in $SERVER.csr -extfile $SERVER.req -extensions v3_req

if [ "${confirm:-Y}" == "Y" ]; then
  echo ""
  echo "Remember to import the certificate into your browser: chrome://settings/certificates."
fi

And then the two .req files:

MyRootCA.req:
[req]
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley Root
CN = limedaley.com

MyClient1.req:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley
CN = lemon.limedaley.com
[v3_req]
subjectAltName = @alt_names

[alt_names]
IP = 10.243.0.10 
DNS.1   = lemon.local
DNS.3   = localhost
DNS.4   = lemon.limedaley.com
DNS.5   = lemon

To use, edit the two .req files as appropriate, and then run the generate script (you shouldn't need to edit it) and then import the *root* certificate, not the server certificate into the "Authorities" section in the certificate management section of your browser.

You also need to put the appropriate lines into your webserver.  Here is an example for Apache:

SSLCertificateFile      /etc/ssl/limedaley/MyClient1.pem
SSLCertificateKeyFile /etc/ssl/limedaley/MyClient1.key

When you want to make changes to the $SERVER.req file, you don't need to regenerate the root certificate, but just use the old one, and then you won't need to import it into your browser.