multi_level_SAN_wildcard_certificates¶
Multi-Level Subdomain (SANs) Wildcard SSL Certificate Management with EasyRSA¶
Overview¶
In some circumstacnes it's desirable to match multiple levels of wildcards in an SSL certificate. One example is limiting the amount of 'internal' certificates to manage for multiple evnironment tiers such as dev,qa,stage,test,etc. Whose domain names are in the format n.foo.com, where n is a numeric identifier of the tier), where having a certificate which matches something like web1.dev.foo.com and also web1.qa.foo.com would be needed.
The method to do this is with the subjectAltName extension (which is an alias within the certificate for the subject of the certificate, abbreviated SAN) for each subdomain which we want to wildcard.
One caveat is that if SANs are in use they must also contain the commonName (CN) as an alternate name, since the browser will ignore the CN in that case (in this example, a SAN for *.foo.com and foo.com would be added).
Create/Update OpenSSL Configuration File¶
SANs are added to the certificate when the certificate signing request is created. The safest way to do this is to create a copy of EasyRSAs openssl.cnf file. This allows you to build certificates that do NOT contain SANs by default.
EasyRSA uses the same OpenSSL configuration file (cnf) for both request generation and signing
In order to determine the current openssl configuration file used by EasyRSA switch to the user that manages your certficiates and view the $KEY_CONFIG variable
echo $KEY_CONFIG /home/ca/openssl-1.0.0.cnf
Now create a copy of this openssl configuration file. I suggest giving it a name that describes the top level domain you'll be creating a wildcard for. For example openssl-*.foo.com.cnf
cp /home/ca/openssl-1.0.0.cnf openssl-*.foo.com.cnf
Update OpenSSL Settings for Certificate Request Generation (CSR)¶
Uncomment or Add the line containing req_extensions = v3_req to allow the extentions to be added to the certificate request CSR.
req_extensions = v3_req # The extensions to add to a certificate request
Next in the [v3_req] section, add the SANs sectional reference (subjectAltName = @alt_names). You can also add them inline if desired
[ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names
Then add the setion [alt_names] in the file
Note that in the DNS.n lines, the n enumerates the entry number starting at 1.
[ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] DNS.1 = foo.com DNS.2 = *.foo.com DNS.3 = *.dev.foo.com DNS.4 = *.qa.foo.com
Update OpenSSL Settings for Certificate Creation/Signing¶
Uncomment or Add the line containing copy_extensions = copy. This line ensures that the v3 extension sections for subjectAltNames are copied from the CSR into the newly minted certificate. The reason that this is commented out by default is that it introduces a security risk. For example if a certificate request contains a basicConstraints extension with CA:TRUE and the copy_extensions value is set to copyall and the user does not spot this when the certificate is displayed then this will hand the requester a valid CA certificate.
[ CA_default ] dir = $ENV::KEY_DIR # Where ... ... ... RANDFILE = $dir/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert copy_extensions = copy # https://www.openssl.org/docs/apps/ca.html#WARNINGS
Build and Sign Wildcard Certificate/Key¶
Before building and/or signing a certificate request we need to point EasyRSA to use the custom OpenSSL configuration file we created. The eaiest way to do this is to export a new KEY_CONFIG parameter set by the vars file
export KEY_CONFIG=/home/ca/openssl-*.foo.com.cnf
Verify the parameter is correctly set
echo $KEY_CONFIG /home/ca/openssl-1.0.0.cnf
When creating a wildcard certificate for the first time you can use the build-key-server script bundled with EasyRSA
$ ./build-key-server *.foo.com-server Generating a 2048 bit RSA private key ...................+++ .........................................................................+++ writing new private key to '*.foo.com-server.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [NY]: Locality Name (eg, city) [Metropolis]: Organization Name (eg, company) [LexCorp]: Organizational Unit Name (eg, section) [Weapons Manufacturing]: Common Name (eg, your name or your server's hostname) [*.foo.com-server]:*.foo.com Name []:*.foo.com-server Email Address [root@ca.example.dev]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /home/ca/openssl-*.foo.com.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'NY' localityName :PRINTABLE:'Metropolis' organizationName :PRINTABLE:'LexCorp' organizationalUnitName:PRINTABLE:'Weapons Manufacturing' commonName :T61STRING:'*.foo.com' name :T61STRING:'*.foo.com-server' emailAddress :IA5STRING:'root@ca.example.dev' Certificate is to be certified until Jun 21 13:15:42 2025 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
"Update"/Build New Wildcard Certificate¶
If you need to add or remove SANs from the wildcard certificate a new certificate Signing Request and Certifcate must be built. This new Singing Request and Certificate will still use the original key.
Update the OpenSSL configuration file (cnf) to add or remove the needed SANs
Note that in the DNS.n lines, the n enumerates the entry number starting at 1.
vim openssl-\*.foo.com.cnf
Before a new Singing Request and Certificate can be built/generated we must revoke the old certificate. This can be accomplished using the revoke-full script bundled with EasyRSA
./revoke-full \*.foo.com-server Using configuration from /home/ca/openssl-*.foo.com.cnf Revoking Certificate 14. Data Base Updated Using configuration from /home/ca/openssl-*.foo.com.cnf *.foo.com-server.crt: C = US, ST = NY, L = Metropolis, O = LexCorp, OU = Weapons Manufacturing, CN = *.foo.com, name = *.foo.com-server, emailAddress = root@ca.example.dev error 23 at 0 depth lookup:certificate revoked
After the old certificate is revoke a new Signing Request must be generated using the current Key. This can be accomplished by calling the openssl command directly to build a new signing request
openssl req -new -key keys/\*.foo.com-server.key -out keys/\*.foo.com-server.csr -config openssl-\*.foo.com.cnf You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [NY]: Locality Name (eg, city) [Metropolis]: Organization Name (eg, company) [LexCorp]: Organizational Unit Name (eg, section) [Weapons Manufacturing]: Common Name (eg, your name or your server's hostname) [CHANGEME]:*.foo.com Name []:*.foo.com-server Email Address [root@ca.example.dev]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Next build/generate and sign the certificate from the signing request. This can be accomplished using the sign-req script bundled with EasyRSA
./sign-req *.foo.com-server Using configuration from /home/ca/openssl-*.foo.com.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'NY' localityName :PRINTABLE:'Metropolis' organizationName :PRINTABLE:'LexCorp' organizationalUnitName:PRINTABLE:'Weapons Manufacturing' commonName :T61STRING:'*.foo.com' name :T61STRING:'*.foo.com-server' emailAddress :IA5STRING:'root@ca.example.dev' Certificate is to be certified until Jun 21 13:31:50 2025 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated