How to create your own self-signed root Certificate Authority(CA)
The million dollar question is why do we need Certificate Authority(CA) in first place? and where CA is used? A CA acts as a trusted third-party, trusted both by the owner of the certificate and by the party relying on the certificate in HTTPS communication.e.g DigiCert Inc. The whole process takes place behind the scene when we access any HTTPS website on the internet. Here is how it works, let's look at the following illustration, A university being a trusted CA, an employer being a browser and a candidate being a server.
An employer requests candidate to submit his/her credentials, a candidate submits his/her credentials to the employer. The employer verifies credentials from common trusted party by both the candidate and employer, which is in this case is a university. This is how CA certificate trust works between browser and the server in HTTPS communication. HTTPS is nothing but an extension to HTTP and sometime referred as HTTP on TLS (Transport Layer Security) or HTTP on SSL (Secure Socket Layer). This trust is shown in browsers by green or grey padlock icon in the address bar.
"The principal motivations for HTTPS are authentication of the accessed website, and protection of the privacy and integrity of the exchanged data while in transit. It protects against man-in-the-middle attacks, and the bidirectional encryption of communications between a client and server protects the communications against eavesdropping and tampering. In practice, this provides a reasonable assurance that one is communicating with the intended website without interference from attackers." - Wikipedia
Here is an example of browser showing untrusted SSL certificate error.
We must have trusted third-party CA certificate for servers on the internet for proper functioning of websites, but what if, a server is self hosted with self-signed SSL certificate. Obviously, trusted check will fail and browser will report a warning as shown above. Actually, the warning message indicates that the trust of chains are not maintained, and in absence of trust it is considered as man-in-the-middle attack. So, how do we avoid annoying warnings for domains hosted locally.
- Add individual self-signed domain certificate to browser : This is cumbersome process to maintain, every new additional domain requires change in browser certificates.
- Create your own root CA: Be a self trusted third-part and sign all self hosted SSL certificates, this will need one time maintenance in the browser certificate management to add root CA. All SSL certificates signed using our own root CA will be trusted by the browser by default.
The following is the network map of my home lab, as you can see I have way too many self hosted web tools, so maintaining these all in every browser is painful.
This is where custom root CA comes handy. I sign all my self-signed SSL certificates with my own root CA and then I setup trust by installing root CA in the browser by eliminating need of installing each self-singed SSL certificate.
The following are the steps to create custom root CA and self-signed certificates for each domain. I will use gitlab as client example, but all the steps are same with the exception of domain name for any other domain. I will be signing all my SSL domain certificates using same root CA to eliminate a need to setup trust between different system. e.g. Local gitlab repository for HANA Express artifacts requires HTTPS and trusted SSL.
Create root key: This is the key used to sign the certificate requests, anyone holding this can sign certificates on your behalf. So keep it in a safe place!
openssl genrsa -des3 -out rootCA.key 4096
if you want a non password protected key remove -des3 option
Create and Self-Sign root CA
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
This is the root CA we need to configure in browsers to establish trust, the certificate validity in above command is 1024 days, which can be changed according to needs.
Create self-signed certificate for self hosted domains: This procedure needs to be followed for each domain/appliance that needs a trusted certificate from our root CA.
Gitlab host FQDN is gitlab.jamb.io in my case.(I'm running my own local dns for jamb.io)
Create server certificate key
openssl genrsa -out gitlab.jamb.io.key 2048
Create Signing Request (CSR): This is where we specify details for the certificate we want to generate.
Important: Please mind that while creating the signing request is important to specify the Common Name providing domain name for the service, also it has to be different than the root CA common name.
openssl req -new -key gitlab.jamb.io.key -out gitlab.jamb.io.csr
Generate the certificate using the domain CSR and key along with root CA key
openssl x509 -req -in gitlab.jamb.io.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out gitlab.jamb.io.crt -days 1024 -sha256
Openssl generates V1 certificates by default unless specified, however, Google chrome tends to report error for V1 certificates. I have written a small script to combine all above steps into single shell script along with V3 additions for easier execution.
Generate domain V3 certificate shell script
#!/bin/bash
function gen_extfile()
{
domain=$1
cat << EOF
authorityKeyIdentifier=keyid,issuer\n
basicConstraints=CA:FALSE\n
keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment\n
subjectAltName = @alt_names\n
[alt_names]\n
DNS.1 = $domain
EOF
}
extFile=$(gen_extfile $1)
openssl genrsa -out $1.key 2048
openssl req -new -sha256 -key $1.key -subj "/C=CA/ST=QC/O=Home/CN=$1" -out $1.csr
openssl x509 -req -in $1.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out $1.crt -days 4000 -sha256 -extfile <(printf "$extFile")
openssl verify -verbose -CAfile rootCA.crt $1.crt
The script can be executed as follows to generate host certificate. It will generate three files: host key .key, .csr and .crt
./scriptname.sh gitlab.jamb.io
The final step is to import our newly generated host certificates in gitlab server. The official documentation for importing SSL certificates is listed here.