Recently, for reasons, I had to generate a self-signed certificate with subject alternative names. As an additional wrinkle, I was trying to do it as part of the userdata script for a machine instance in EC2 running Amazon Linux. This turned out to be more difficult than expected.
After piecing together various blog posts this is what I ended up with.
LOCAL_HOSTNAME=$(GET http://169.254.169.254/latest/meta-data/local-hostname) LOCAL_IPV4=$(GET http://169.254.169.254/latest/meta-data/local-ipv4) openssl req \ -newkey rsa:2048 \ -nodes \ -sha256 \ -x509 \ -days 3650 \ -config <(cat <<EOF [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = US ST = California L = Los Angeles O = Example.com CN = $LOCAL_HOSTNAME [v3_req] keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = $LOCAL_HOSTNAME DNS.2 = $(hostname) IP.1 = $LOCAL_IPV4 EOF ) \ -keyout server.key \ -out server.crt
The above (almost) single line command:
- Fetches the private IP and hostname of the EC2 instance.
- Generates an new RSA private key with 2048 bits:
- Doesn’t require a password for the private key:
- Use the SHA-2 signature algorithm (gotta keep your self-signed certs up to date with the cool kids):
- Sets the expiry to 10 years:
- Passes in a custom openssl config:
- Writes the private key to a file:
- Writes the public key to a file:
The custom config file
- Sets the distinguished name for the certificate
- Enables x509 extensions (needed for subjectAltName)
- Specfies that the key is for server authentication
- Sets the alternative names to the FQDN, the hostname, and the IP address of the instance.
Generating a self-signed certificate this way at least means we can do host verification.