You may need a self-signed certificate whenever you do a local development or host a web application in your local network.
In this article, I create a wildcard certificate for *.home.local
to use on my local Kubernetes cluster.
First, we need OpenSSL – cryptography and SSL/TLS Toolkit. In this article, I assume you already have it installed on your computer.
Now, to create a certificate, we need to perform these simple steps:
genrsa generates a Triple DES-encrypted and password-protected 2048-bits long private key to a file named ca.key
:
openssl genrsa -des3 -out ca.key 2048
Expected output:
ca.key
with the first line -----BEGIN RSA PRIVATE KEY-----
.Now, let's create a
openssl req -x509 -new -nodes -key ca.key -days 1825 -out ca.pem
Here:
openssl req
– a command to generate PKCS#10 certificate requests and certificates:-x509
– this option outputs a certificate instead of a certificate request.-new
– this option generates a new certificate request. It will prompt the user for the relevant field values.-nodes
– i.e., "no DES": if this option is specified, then if a private key is created, it will not be encrypted.-key ca.key
– this option provides the private key for signing a new certificate or certificate request.-days 1825
– when -x509
is in use, this specifies the number of days to certify the certificate for.-out ca.pem
– specifies the output filename to write to or standard output by default.Expected output:
ca.pem
with the first line -----BEGIN CERTIFICATE-----
.Now, when we have a root certificate, we can create a new certificate signed by our root certificate:
openssl genrsa -out home.local.key 2048
Here, we use our friend genrsa
that we already used in the first step.
Expected output:
home.local.key
with the first line -----BEGIN RSA PRIVATE KEY-----
.openssl req -new -key home.local.key -out home.local.csr
-key
– this option provides the private key for signing a new certificate or certificate request.If you are wondering about the challenge password, here's a great answer on Server Fault explaining that "the "challenge password" requested as part of the CSR generation is not the same thing as a passphrase used to encrypt the secret key": https://serverfault.com/a/266258/550939
Expected output:
home.local.csr
with the first line -----BEGIN CERTIFICATE REQUEST-----
.Create a file home.local.ext
with the following content:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.home.local
openssl x509 -req -in home.local.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out home.local.crt -days 1825 -sha256 -extfile home.local.ext
openssl x509
is the certificate display and signing command:
-req
– by default a certificate is expected on input. With this option, a PKCS#10 certificate request is expected instead, which must be correctly self-signed.-in home.local.csr
– specifies the input to read a certificate from or the input file for reading a certificate request if the -req flag is used. In both cases, this defaults to standard input.-CA ca.pem
– specifies the "CA" certificate to be used for signing.-CAkey ca.key
– sets the CA private key to sign a certificate with.-CAcreateserial
– with this option and the -CA option, the CA serial number file is created if it does not exist. A random number is generated, used for the certificate, and saved into the serial number file determined as described above.-out home.local.crt
– specifies the output filename to write to or standard output by default.-days 1825
– the number of days until a newly generated certificate expires.-extfile home.local.ext
– configuration file containing certificate and request X.509 extensions to add.Expected output:
home.local.crt
with the first line -----BEGIN CERTIFICATE-----
.This is it.
Now, to use this certificate in Kubernetes, we can install it with the following YAML definition:
apiVersion: v1
kind: Secret
metadata:
name: home-crt
type: kubernetes.io/tls
data:
ca.crt: >-
{{ cat ca.pem | base64 }}
tls.crt: >-
{{ cat home.local.crt | base64 }}
tls.key: >-
{{ cat home.local.key | base64 }}
But this is a different story.