Setting up a PKI using Vault — EXPLAINED

Valente Vidal
14 min readApr 9, 2021
PKI Diagram

I’ve spent a good chunk of time setting up a PKI (Public Key Infrastructure) lately. Having little to no experience or prior knowledge regarding PKIs or PKI setup/management in Hashicorp Vault, I thought it would be a good idea to write a small guide on how to achieve this, including some resources that link to more in depth explanations.

For this guide we’ll be using Hashicorp Vault as previously mentioned to set up our PKI. Setting up Vault in a Cluster or even locally is easy. These are some links to get you started.

I’ve also uploaded some files and scripts to start your local Consul and Vault using Minikube you can find them in my GitLab HERE

I’ll be using the fictional company called Gengar. For a full bash script please visit my GitLab HERE

We will be creating at 2 layer PKI, which consist of a Root CA and an Intermediate CA which will be issuing End Entity certificates through a role. This is how the Issuer and Subject will appear in each corresponding certificate.

Root CA
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Subject: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Intermediate CA
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Subject: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Issuing
End Entity Certificate
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Issuing CA
Subject: C=GB, O=Gengar Corp, OU=Tech Center, CN=Test Certificate

The Root CA will be signed by itself and hence the Issuer and the Subject are Root CA. The intermediate will be signed by the Root CA and therefore the Isser is the Root CA. Lastly the actual certificates being issued by the Intermediate CA will have Issuing CA in the Issuer and the CN specified in the Subject.

Once you have your Vault launched, running, and logged in you can run the following commands to issue a root ca.

Creating the Root CA

vault secrets enable -path=pki_gnr_ca pkivault secrets tune -max-lease-ttl=87600h pki_gnr_cavault write -field=certificate pki_gnr_ca/root/generate/internal max_path_length=1 key_usage='' ext_key_usage='' common_name="Gengar Root CA" ou="GNR PKI" organization="Gengar Corp" country="GB" ttl=87600h key_bits=4096 > CA_cert.crtvault write pki_gnr_ca/config/urls issuing_certificates="http://vault.gengar.com/v1/pki_gnr_ca/ca" crl_distribution_points="http://vault.gengar.com/v1/pki_gnr_ca/crl"vault write pki_gnr_ca/config/crl expiry="4380h"vault read pki_gnr_ca/crl/rotate
If you visit your Vault UI your PKI GNR CA will appear in the dashboard

Breaking down the commands

Enabling the PKI path

vault secrets enable -path=pki_gnr_ca pki

We are merely creating a PKI engine under the path pki_gnr_ca

Tuning the Time To Live

vault secrets tune -max-lease-ttl=87600h pki_gnr_ca

Here we are tuning the max-lease-ttl of pki_gnr_ca to 10 years (87600h) .

Configuring the Root CA

vault write -field=certificate pki_gnr_ca/root/generate/internal max_path_length=1 key_usage='' ext_key_usage='' common_name="Gengar Root CA" ou="GNR PKI" organization="Gengar Corp" country="GB" ttl=87600h key_bits=4096 > CA_cert.crt

This will generate a new self-signed CA certificate and private key. If the path ends with exported, (e.g. pki_gnr_ca/root/generate/exported) the private key will be returned in the response; if it is internal the private key will not be returned and cannot be retrieved later. We will continue with internal and save the private key as a file called CA_cert.crt. If you are planning to use this in production make sure you have a copy if the private key.

Max Path Length

max_path_length is set to 1 because we only have a 2 layer PKI and the last layer in our PKI setup, the Intermediates CA, will be 0. The image below illustrates this very well with a 3 layer PKI, a Root CA and 2 Intermediates CA with the layer 3 issuing EE (End Entity) certificates and layer 4 being the EE certificate it self.

http://www.pkiglobe.org/

In our 2 layer PKI the public root ca certificate, once decrypted will state this information like this:

X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1

Key Usage

The key_usage extension of an X.509 V3 digital certificate defines how the public key contained within the certificate may be used. For example, a key usage extension of dataEncipherment indicates that the certificate may be used to encrypt user data. You can find a list of options HERE

Extended key usage

ext_key_usage further refines key usage extensions. An extended key is either critical or non-critical. If the extension is critical, the certificate must be used only for the indicated purpose or purposes. If the certificate is used for another purpose, it is in violation of the CA’s policy. You can find a list of options HERE

For this example they will be empty key_usage=’’ ext_key_usage=’’

Common Name, Organization Unit, Organization, Country, Time To Live (ttl) and Key Bits

common_name, ou, organization, country, ttl and key_bits

  • common_name: this specifies the requested CN for the certificate. We will use Gengar Root CA to be explicit that this CN is the Root CA
  • ou: This field is the name of the department or organization unit. We will go with GNR PKI
  • organization: We will just state the overall organization. Gengar Corp
  • country: We will just put the country code GB
  • ttl: Is the Time To Live which is 10 years(87600h), this is the average time for a root CA.
  • key_bits: This will be the level of encryption. Vault default for PKI is 2048 but we will change this to be higher: 4096

In the public root ca certificate it will look like this:

C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
-
Public-Key: (4096 bit)

Configuring the URLs

vault write pki_gnr_ca/config/urls issuing_certificates="http://vault.gengar.com/v1/pki_gnr_ca/ca" crl_distribution_points="http://vault.gengar.com/v1/pki_gnr_ca/crl"

The endpoint pki_gnr_ca/config/urls is used, like the name suggests, to configure the urls of this CA. It is here where you will define the urls for downloading issuing certificates for the root ca and the CRL which is the certificate revocation list.

vault write pki_gnr_ca/config/crl expiry="4380h"vault read pki_gnr_ca/crl/rotate

These two commands will configure the CRL expiry and rotate them. CRLs should be short in length around a week or 168h, in this example we are setting up the expiry of the CRL for 6 months.

The public certificate of the root CA (Root CA)

To download a public root CA certificate you can visit : http://vault.gengar.com/v1/pki_gnr_ca/ca or http://127.0.0.1:8200//v1/pki_gnr_ca/ca

The file will be download will be in DER format to decrypt it you can use openssl
openssl x509 -in root_ca -text -noout -inform der

Once decrypted the public root CA will look like this:

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
48:2d:2c:23:a3:47:90:59:06:34:d6:b5:b6:c2:02:8e:b2:6d:33:b4
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Validity
Not Before: Apr 2 13:07:54 2021 GMT
Not After : Mar 31 13:08:21 2031 GMT
Subject: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:ce:e7:f5:56:cb:45:7e:cb:23:e9:4b:fe:1d:75:
d9:82:8c:f3:71:1e:9e:4f:03:3b:99:2c:dd:dd:4e:
0b:6d:11:d8:1c:19:80:4c:0c:44:2a:46:c4:32:88:
70:b1:10:14:91:da:4f:97:79:ab:23:e8:ca:8c:c3:
71:d1:18:de:7a:0e:74:e2:a0:0b:e4:53:16:b2:47:
57:31:78:9c:2a:36:89:b3:4b:d8:7b:73:1b:e2:50:
04:a8:9a:c9:33:2c:af:46:35:2f:8e:cb:f4:20:8a:
27:12:4e:e1:c5:77:6d:21:e4:60:7d:49:5b:87:36:
25:be:52:5c:58:d4:86:dd:87:24:ef:f0:24:ee:f9:
52:2c:f8:1e:4c:27:f7:e7:3c:61:62:4e:07:1c:cb:
54:09:ff:85:00:ee:4b:75:87:1e:0c:00:a3:56:c8:
f8:77:66:ad:99:8b:5d:fe:ed:e9:d4:15:c4:5e:6b:
0b:49:44:4d:27:f2:6f:5f:9d:88:6c:00:fd:84:49:
d3:0d:8f:f3:48:dd:77:e1:a1:15:eb:a4:82:4d:a3:
f4:a5:38:93:44:ca:7b:33:a5:30:1a:4b:fc:16:21:
bf:f5:80:f2:e4:7d:85:67:68:06:c1:be:8f:dc:f8:
45:fd:5b:3e:48:12:90:e3:ee:23:d5:f4:0a:56:d9:
8e:00:1b:c1:d5:73:76:85:89:bb:33:0e:a0:86:d5:
ac:5e:f2:32:9d:b9:51:e3:c8:38:f3:80:cc:d8:07:
4d:d8:ff:93:6a:4e:7e:7d:05:5e:c2:3b:7f:25:42:
73:8a:67:80:1e:79:52:14:a2:69:c1:e1:9c:ff:33:
29:11:55:90:28:f5:11:49:da:b0:22:fa:90:d3:2a:
d3:43:d0:6c:60:61:26:fa:33:70:70:94:3f:91:34:
39:b8:0a:a2:bc:05:40:42:5c:69:3b:5a:84:1e:2b:
ef:98:5f:d1:68:18:61:ce:2d:9a:58:2a:22:5d:2f:
41:68:da:43:63:56:fc:d6:b6:3a:0a:65:35:07:a1:
47:4e:9d:44:b4:24:33:8f:c5:aa:98:4a:e4:6c:b8:
fc:50:26:da:48:40:3e:e6:89:b8:6e:8d:d0:07:2d:
e9:4a:63:45:fa:5a:98:39:3d:6c:c4:fc:02:05:2e:
b8:ab:42:2b:19:3e:4d:8f:cc:4d:11:77:08:d6:78:
af:7b:38:14:71:4d:94:8c:61:03:b3:d8:21:e9:b6:
60:34:d4:4f:5f:aa:be:1a:db:88:d6:ed:a5:63:6c:
c0:da:8b:3d:37:3a:1f:6c:3e:20:b5:30:39:a7:56:
12:0a:32:0f:7e:31:67:5b:32:27:4d:70:5b:7a:80:
34:e4:63
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Subject Key Identifier:
37:CD:4A:FE:DF:C7:BE:EC:B8:62:F5:0A:C6:0D:97:1D:EF:51:41:A1
X509v3 Authority Key Identifier:
keyid:37:CD:4A:FE:DF:C7:BE:EC:B8:62:F5:0A:C6:0D:97:1D:EF:51:41:A1
Signature Algorithm: sha256WithRSAEncryption
13:43:6b:51:5d:97:d4:5b:30:16:52:3f:83:22:82:5d:d7:1d:
2d:67:8c:8f:7b:a1:42:a9:f0:ec:c1:38:76:6a:31:41:99:f5:
82:1a:a3:b1:90:9a:16:02:8d:9e:57:ac:b3:69:ce:b5:8d:5a:
b0:49:b6:4b:32:8b:7e:59:82:56:ef:84:b4:9a:21:2d:00:20:
bd:ff:db:0a:4f:f8:bf:cb:45:50:0f:78:75:ca:a0:28:e9:b0:
20:1f:2b:f4:56:76:22:0c:1c:bd:74:fa:76:93:38:2a:f8:a1:
c4:eb:fb:0b:71:58:c9:f8:77:bd:60:23:b1:77:0d:35:dd:dc:
a2:7a:93:3a:7a:32:7a:63:d3:09:c3:51:f2:dc:1d:d0:2b:b1:
c8:07:45:6e:5e:c5:1e:7b:ef:a5:d3:a5:f0:09:2a:31:fc:a7:
6f:e8:32:04:d6:21:fa:aa:64:22:a2:f4:9e:27:44:59:62:b7:
c3:1e:5a:d1:aa:b5:5b:53:19:ab:8b:0d:8f:4c:1f:94:5c:9d:
99:54:28:f5:32:dd:d0:7e:f6:4b:e1:2d:fd:cd:31:be:53:4d:
c0:e8:34:a1:82:2f:c4:d4:82:76:52:16:48:c3:bc:2d:9a:b8:
9f:9a:21:2d:81:a9:0e:26:1c:e0:29:5a:fd:c6:bc:8e:d9:eb:
97:4d:e8:8f:62:63:c4:bf:c4:c9:94:2a:b8:50:f7:d1:f1:6a:
29:74:9f:a5:d8:ac:54:04:fe:a5:7e:4f:bd:44:1e:c0:bd:d3:
c0:85:97:7f:6f:c0:62:44:69:fd:8f:fc:7f:fc:e6:49:71:ef:
85:cf:9f:71:82:31:ed:ed:4d:4b:e8:93:60:0e:04:27:f4:93:
31:b3:bc:1c:10:4e:ac:da:63:44:62:7d:10:86:92:13:5c:2a:
ed:c7:80:10:ef:f9:19:5f:b0:e9:33:ea:6f:c4:f5:b7:3c:65:
90:3e:d1:09:20:40:bc:5a:1d:cb:3b:d0:9a:70:22:e5:0f:54:
34:fa:54:bb:ce:a7:5f:ca:9c:a5:9c:7f:07:3b:6b:49:ca:24:
3f:53:e1:21:1d:04:e6:0c:60:2e:f5:20:e5:6d:29:17:54:b3:
24:30:0b:9d:ae:7a:ca:8a:cb:6e:04:a8:62:19:f5:a2:e0:0d:
99:41:d8:e1:bd:69:6d:6d:e4:5b:0c:fa:7c:5c:bf:bd:6e:55:
f8:5a:2b:ef:23:2e:50:a2:52:d9:21:cb:32:5c:2d:31:1a:ea:
32:43:27:62:c8:58:66:6b:35:46:91:f8:f4:ab:4d:50:dc:c1:
fc:fe:b6:9d:3e:d4:5e:65:60:5f:d3:1f:2d:b3:5d:0b:e4:de:
87:bd:63:2f:ae:fa:4a:9b

Creating the Intermediate CA

vault secrets enable -path=pki_int_gnr_ca pkivault secrets tune -max-lease-ttl=43800h pki_int_gnr_cavault write -format=json pki_int_gnr_ca/intermediate/generate/internal max_path_length=0 key_bits=4096 common_name=”Gengar Issuing CA" ou=”GNR PKI” organization=”Gengar Corp” country=”GB” | jq -r ‘.data.csr’ > pki_int_gnr_ca.csrvault write -format=json pki_gnr_ca/root/sign-intermediate max_path_length=0 key_bits=4096 common_name=”Gengar Issuing CA" ou=”GNR PKI” organization=”Gengar Corp” country=”GB” csr=@pki_int_gnr_ca.csr format=pem_bundle ttl=”43800h” | jq -r ‘.data.certificate’ > pki_int_gnr_ca.cert.pemvault write pki_int_gnr_ca/intermediate/set-signed certificate=@pki_int_gnr_ca.cert.pemvault write pki_int_gnr_ca/config/urls issuing_certificates=”http://vault.gengar.com/v1/pki_int_gnr_ca/ca" crl_distribution_points=”http://vault.gengar.com/v1/pki_int_gnr_ca/crl"vault write pki_int_gnr_ca/config/crl expiry=”4380h”vault read pki_int_gnr_ca/crl/rotate
Once you have run the commands for the Root CA and the Intermediate CA you should be able to see them in your UI

Breaking down the commands

Enabling the PKI path

vault secrets enable -path=pki_int_gnr_ca pki

Just like before we will be creating an additional pki engine this time in the path pki_int_gnr_ca

Tuning the Time To Live

vault secrets tune -max-lease-ttl=43800h pki_int_gnr_ca

We will set the max time to live for 43800h which is 5 years.

vault write -format=json pki_int_gnr_ca/intermediate/generate/internal max_path_length=0 key_bits=4096 common_name=”Gengar Issuing CA" ou=”GNR PKI” organization=”Gengar Corp” country=”GB” | jq -r ‘.data.csr’ > pki_int_gnr_ca.csr

We’ll be generating a certificate signing request (CSR) for our root to sign.

Max Path Length

This will be equal to 0. This is to signal that this is the last level in our PKI and no more intermediates will follow. Meaning that the certificates this Ca generates will be for End Entity (EE) users.

In the certificate it will appear like this:

X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0

Common Name, Organization Unit, Organization, Country, Time To Live (ttl) and Key Bits

common_name, ou, organization, country, and key_bits

The information here will be slightly different to the one on our root ca.

  • common_name will be set to Gengar Issuing CA This is to establish this will be the level in the PKI that will be issuing certificates to EE users
  • ou will remain the same as in the root ca: GNR PKI
  • organization will remain the same as in the root ca:Gengar Corp
  • country will remain the same as in the root ca: GB
  • key_bits will remain the same as the root ca: 4096
jq -r ‘.data.csr’ > pki_int_gnr_ca.csr

the last bit of the command will output the CSR into a file called pki_int_gnr_ca.csr

Signing the Intermediate CA

vault write -format=json pki_gnr_ca/root/sign-intermediate max_path_length=0 key_bits=4096 common_name=”Gengar Issuing CA" ou=”GNR PKI” organization=”Gengar Corp” country=”GB” csr=@pki_int_gnr_ca.csr format=pem_bundle ttl=”43800h” | jq -r ‘.data.certificate’ > pki_int_gnr_ca.cert.pem

This command will sign the CSR that we just created and output a pem file

You should note that we are providing the same values common_name, ou, organization, country, and key_bits . This is just as a precaution if you trust the entity that will be sending you the CSR you can remove all of those values and replace them with use_csr_values=true This will use the values provided in the CSR:

If set to true, then: 1) Subject information, including names and alternate names, will be preserved from the CSR rather than using the values provided in the other parameters to this path; 2) Any key usages (for instance, non-repudiation) requested in the CSR will be added to the basic set of key usages used for CA certs signed by this path; 3) Extensions requested in the CSR will be copied into the issued certificate. — https://www.vaultproject.io/api/secret/pki#use_csr_values

csr=@pki_int_gnr_ca.csr format=pem_bundle ttl=”43800h”

when using the @ through command line you are stating to Vault the location of the file you are providing is local, since the path of the CSR is the same as where we saved it we’ll just give it the name of the file.

format=pem_bundle is just the format of output

ttl is the time to live set to 5 years (43800h)

Installing the Signed Certificate

vault write pki_int_gnr_ca/intermediate/set-signed certificate=@pki_int_gnr_ca.cert.pem

Here we’re providing the pem file we obtained from the root ca from the command above.

Configuring the URLs

vault write pki_int_gnr_ca/config/urls issuing_certificates=”http://vault.gengar.com/v1/pki_int_gnr_ca/ca" crl_distribution_points=”http://vault.gengar.com/v1/pki_int_gnr_ca/crl"

Like we defined in the root ca we are defining the urls for downloading issuing certificates for the issuing ca and the CRL.

vault write pki_int_gnr_ca/config/crl expiry=”4380h”vault read pki_int_gnr_ca/crl/rotate

These two commands will configure the CRL expiry and rotate them. CRLs should be short in length around a week or 168h, in this example we are setting up the expiry of the CRL for 6 months. If you use this for production remember to keep this short like a week or two.

The public certificate from the intermediate CA (Issuing CA)

If you decrypt the public intermediate CA you will get the following

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
5a:5a:7a:99:ea:a0:d4:dd:56:35:b3:f2:88:9e:74:8c:62:28:62:6b
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Root CA
Validity
Not Before: Apr 2 13:08:19 2021 GMT
Not After : Apr 1 13:08:49 2026 GMT
Subject: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Issuing CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:c8:0d:20:a7:9a:d4:53:ea:5b:cb:eb:1a:21:61:
af:9a:0e:92:77:aa:b9:95:75:07:c8:3e:09:fa:07:
73:0d:e5:c1:f5:7f:9d:79:36:62:e0:21:d1:dc:57:
b8:d8:8a:c3:e1:49:61:5d:a7:cd:14:96:e0:59:21:
52:f9:59:d9:04:7f:6d:67:e4:ae:04:52:5d:29:e2:
e3:d3:f1:19:c2:8b:18:6e:ea:16:76:ab:52:93:77:
e2:0d:b8:d2:88:10:50:68:44:49:7d:c6:bb:f4:54:
d7:92:32:2e:2a:ea:2b:72:a7:c0:1e:dd:33:18:4a:
58:1f:56:64:83:41:5d:5b:55:e5:46:e8:e6:0e:49:
10:65:1f:68:43:b9:0c:bd:6e:45:83:a0:fb:78:12:
8c:eb:bf:37:a3:99:7a:2a:51:1c:c0:ab:2c:64:b4:
aa:e8:9c:4f:c5:8b:28:be:3d:f2:a7:df:2d:24:e4:
66:08:2c:a9:41:03:0c:16:ea:ca:ad:d3:29:48:c4:
b6:0a:56:21:fc:1b:29:c6:c8:82:53:2a:da:9a:0e:
19:87:92:6b:15:d9:5a:71:73:a8:48:4a:e1:5a:96:
16:03:ef:45:e2:9e:51:5d:cc:a2:40:e3:2c:df:34:
50:56:c7:5e:76:e0:4d:e2:2f:6a:cd:6b:b4:2a:ce:
11:47:ad:5a:d2:29:39:ac:d9:5e:52:ea:21:02:e2:
be:ea:bf:ac:ad:5b:2a:27:6d:ad:07:c5:2c:c3:33:
9a:00:f5:81:6a:38:27:6b:3d:e5:3d:03:d0:1c:00:
23:46:24:f2:e1:37:63:d6:95:b0:48:20:94:cf:24:
7d:36:33:50:39:43:2d:bb:bc:a7:07:62:39:ac:d1:
56:90:e5:ee:fd:d6:e4:74:34:ba:a3:8e:52:30:e4:
86:57:30:b6:a6:06:56:0f:2f:d4:50:d7:d7:68:d8:
86:3f:b4:4c:1b:75:59:cb:c0:fc:ee:7b:38:e8:30:
58:39:10:3f:3b:2b:bc:e7:4f:8a:17:a4:39:af:00:
16:23:7f:bb:72:3f:70:75:8c:9f:b0:fb:7b:30:17:
45:49:09:02:11:9e:33:2f:97:be:cf:a4:63:13:a2:
e4:ff:1e:c5:53:0f:4c:c4:c4:5f:b8:d3:d7:ca:a9:
06:7e:c6:ce:25:08:1c:a7:74:04:05:fb:d7:cf:6d:
a2:d1:b1:65:1a:af:2a:ed:8b:9c:ae:0c:16:15:d7:
b3:18:4a:db:bf:32:d3:ad:0d:fa:d0:34:b0:c0:a9:
62:c8:e6:fe:9e:98:b4:55:aa:a2:99:85:9b:ce:28:
03:d6:2d:8e:7a:95:d3:66:96:89:c4:27:0a:30:91:
7f:d5:e1
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
32:EA:DD:96:21:AC:A0:76:C5:BF:78:59:2C:4D:11:88:E8:08:F4:8F
X509v3 Authority Key Identifier:
keyid:37:CD:4A:FE:DF:C7:BE:EC:B8:62:F5:0A:C6:0D:97:1D:EF:51:41:A1
Authority Information Access:
CA Issuers - URI:http://vault.gengar.com/v1/pki_gnr_ca/ca
X509v3 CRL Distribution Points:Full Name:
URI:http://vault.gengar.com/v1/pki_gnr_ca/crl
Signature Algorithm: sha256WithRSAEncryption
2f:f2:38:f0:57:5f:4d:48:49:c6:1e:9a:8c:2b:8c:10:25:e0:
71:1d:63:6a:85:b3:3e:db:4b:d0:1d:1c:bc:50:0d:33:1c:d6:
48:70:3f:89:3e:e0:c0:ba:27:c1:6e:f2:56:36:95:c2:fc:17:
da:28:cd:1a:93:20:cd:1f:9e:34:a6:db:f5:4a:42:d8:62:0b:
50:ff:ff:cc:2f:98:e2:77:29:45:47:85:f5:c7:57:01:44:a6:
81:94:37:d2:ed:d2:fe:8f:2d:40:e4:39:80:99:2b:e9:09:2e:
6a:0b:63:50:7a:6b:57:ce:ea:10:ef:d3:76:c1:a9:82:0c:1e:
a2:b3:3a:f7:90:fa:68:d5:b0:bd:8a:6c:13:47:b5:97:9e:1d:
37:58:ba:5f:a9:bc:77:82:2e:82:ba:2f:22:27:e6:8d:f7:6c:
8d:f6:80:c8:f1:b3:4a:d2:44:93:ec:8d:25:f8:fa:51:73:51:
54:32:a2:36:f8:bb:7c:41:c5:74:8c:d5:d8:29:d9:39:72:3d:
d8:72:72:bf:a2:da:e4:1c:f1:4f:c4:52:3c:14:df:3a:e9:d3:
ec:77:1c:fc:11:8c:a9:18:4f:72:9c:0f:e7:f3:46:e9:43:2e:
d4:0e:35:f4:95:01:6a:ae:e2:4d:e1:09:e5:c9:c6:26:98:37:
da:87:bb:2e:f8:02:2d:a9:c7:4e:94:54:85:93:99:0e:1b:b2:
a6:e7:32:3c:20:bb:57:d5:4b:45:0c:7c:19:36:bb:d7:4e:43:
e4:8c:ae:81:ad:2f:e1:c4:24:38:11:8d:55:79:43:3a:38:14:
8a:a2:25:99:fb:c4:37:0d:45:69:4f:9c:71:c1:f3:7c:33:87:
3b:9e:4c:90:92:13:ff:0e:7e:e3:6c:77:d6:0b:f8:7b:64:16:
f4:1b:08:75:b7:d9:53:22:16:c6:18:00:99:ad:e6:fb:1a:e9:
5c:dc:94:79:0f:0f:55:ea:ad:20:ed:87:38:5d:8f:4f:46:51:
d9:77:63:20:27:3f:7d:c0:12:e0:1c:9a:d1:f0:89:0c:8e:7d:
08:9e:1e:27:7e:01:6c:4c:4f:f4:2d:2c:58:74:c3:7e:20:b7:
74:21:1f:0e:3d:fd:a1:e6:ad:59:a0:d7:4f:b0:ac:d5:95:44:
97:de:8c:b8:41:52:a8:ce:93:68:46:3d:c0:d4:a4:10:bb:c8:
6e:ee:20:be:6a:51:34:0c:f1:c4:ed:41:2c:2a:d9:d2:b2:26:
39:f1:09:51:aa:8b:56:4a:25:f4:38:ab:b1:71:eb:9f:c3:17:
df:f8:89:ed:85:36:ca:f4:ec:28:28:df:d5:1c:a8:79:94:09:
5a:f5:cd:a5:ad:f5:20:af

The Role

Up until this point we have created the Root and Intermediate Certificate Authorities. Now we need to create a role which will utilise the Intermediate CA to issue EE certificates.

vault write pki_int_gnr_ca/roles/Issuer  allow_any_name=True server_flag=False client_flag=False allow_subdomains=false ou="Tech Center" organization="Gengar Corp" country="GB" key_usage="DigitalSignature, KeyEncipherment" use_csr_common_name=true ext_key_usage="" ext_key_usage_oids="" ttl="4380h" max_ttl="4380h"   enforce_hostnames=false allow_bare_domains=true
Once you run the command you will be able to see the role in pki_int_gnr_ca

This is a very long command so let’s break it down in parts like we did the others and show what each part is responsible for in an EE (End Entity) certificate.

Setting up the role

vault write pki_int_gnr_ca/roles/Issuer

Here we tell Vault we’ll create a role called Issuer which will issue certificates using the pki_int_gnr_ca level. This can be called what ever you want, for this example it’s called Issuer. It should be noted creating this role doesn’t add an additional level in the PKI it is merely a role which will use the intermediate PKI.

Allow Any Name

allow_any_name=True

Specifies if clients can request any CN. Useful in some circumstances, but make sure you understand whether it is appropriate for your installation before enabling it. — Vault Docs

If you are using it for production you will want to have this to False and provide a specific value.

Server Flag and Client Flag

server_flag=False client_flag=False

Specifies if certificates are flagged for server use. — Vault Docs

Specifies if certificates are flagged for client use. — Vault Docs

When server_flag and client_flag are not defined as false, -the default is true for both, you get TLS Web Server Authentication in Extended Key Usage detail in the EE certificate:

X509v3 Extended Key Usage:
TLS Web Server Authentication

Allow Subdomains

allow_subdomains=false

This would allow hunter.example.com to be allowed, that is if example.com is in the allowed list. Which because of allow_any_name=True this is allowed.

Ou, Organization and Country

ou=”Tech Center” organization=”example.com Corp” country=”GB”

In this example we are only specifying the ou and the organization

Key Usage

key_usage=”DigitalSignature, KeyEncipherment”

Key usage extensions define the purpose of the public key contained in a certificate. You can use them to restrict the public key to as few or as many operations as needed. For example, if you have a key used only for signing or verifying a signature, enable the digital signature and/or non-repudiation extensions. Alternatively, if a key is used only for key management, enable key encipherment. — https://help.hcltechsw.com/domino/11.0.0/conf_keyusageextensionsandextendedkeyusage_r.html

Using the config: key_usage=”DigitalSignature, KeyEncipherment” will output the following in the EE certificate:

X509v3 Key Usage: critical
Digital Signature, Key Encipherment

If you wish to remove all together this option from the certificate you need to set the to be empty key_usage=””

Use CSR Common Name

use_csr_common_name=true

This will use the CSR common name when you are signing a CSR.

Ext Key Usage and Ext Key Usage OID

ext_key_usage=”” ext_key_usage_oids=””

Extended Key Usage extensions (EKUs) are newer and are generally used to restrict usage while the Key Usage Extensions (KUEs) are considered less flexible. KUEs is defined in terms of “operations whereas EKUs are defined in terms of “operations”. Generally EKUs are checked offensively (ie. This certificate must contain this EKU OID) whereas KUEs are generally checked defensively (ie. This certificate must contain this but may contain this or that). — https://knowledge.digicert.com/quovadis/ssl-certificates/extended-key-usage-and-key-usage-extensions.htm

TTL (Time To Live) and Max TTL

ttl=”4380h” max_ttl=”4380h”

This will define how long the certificates that this role generates will last. For testing 4380h (6 months) will be more than enough. Note that the role values default to system values if not explicitly set. Set both for more control

Enforce Hostnames

enforce_hostnames=false

Specifies if only valid host names are allowed for CNs, DNS SANs, and the host part of email addresses. — Vault Docs

Allow Bare Domains

allow_bare_domains=true

Specifies if clients can request certificates matching the value of the actual domains themselves; e.g. if a configured domain set with allowed_domains is example.com, this allows clients to actually request a certificate containing the name example.com as one of the DNS values on the final certificate. In some scenarios, this can be considered a security risk. — Vault Docs

Issuing a certificate

You can issue an EE certificate using the UI, by going to your browser or you can do this by terminal. If you want to issue a certificate using terminal you can use a command like this one:

vault write -format=json pki_int_gnr_ca/issue/Issuer name=”Test Certificate” common_name=”Test Certificate”

The output will be a Certificate, Issuing CA, and a CA chain all encrypted.

if you want the output decrypted you can use a command like this:

vault write -format=json pki_int_gnr_ca/issue/Issuer name=”Test Certificate” common_name=”Test Certificate” | jq -r ‘.data.certificate’ | openssl x509 -noout -text >> cert1

If you generate a certificate using this PKI and role setup it will generate a Certificate, Issuing CA, and a CA chain. The certificate will be the End Entity (EE) certificate that the End Entity will use. Depending on the usage of the certificate you might also require a Chain Certificate. Vault doesn’t provide a true Chain Certificate without some configuration. For that you will need to generate a public certificate from the Root CA and concat it along with the Issuing CA which in this case is the Intermediate CA and the EE certificate in the following order:

— — -BEGIN CERTIFICATE — — -
(Your Primary SSL certificate: certificate.crt)
— — -END CERTIFICATE — — -
— — -BEGIN CERTIFICATE — — -
(Your Intermediate certificate: issuing_int_ca.crt)
— — -END CERTIFICATE — — -
— — -BEGIN CERTIFICATE — — -
(Your Root certificate: issuing_root_ca.crt)
— — -END CERTIFICATE — — -

You can download the the Public Issuing Root CA and the Public Issuing Intermediate CA by visiting the URL you set up the both of these up

“http://vault.gengar.com/v1/pki_gnr_ca/ca"
and
“http://vault.gengar.com/v1/pki_int_gnr_ca/ca"

If you are using local host then you will need to change the URL to the bellow when creating the Root CA and the Intermediate CA:

“http://http://127.0.0.1:8200//v1/pki_gnr_ca/ca"
and
“http://http://127.0.0.1:8200//v1/pki_int_gnr_ca/ca"

The end result

When finally issued and decrypted the certificate will look something like this:

If you decrypt the certificate you will get the following:Certificate:
Data:
Version: 3 (0x2)
Serial Number:
52:83:e6:c2:c9:1f:a9:f3:a3:62:76:ec:91:cb:4e:b5:1f:8d:64:de
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, O=Gengar Corp, OU=GNR PKI, CN=Gengar Issuing CA
Validity
Not Before: Mar 25 13:49:20 2021 GMT
Not After : Sep 24 01:49:50 2021 GMT
Subject: C=GB, O=Gengar Corp, OU=Tech Center, CN=Test Certificate
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:bc:10:50:70:16:34:2a:2f:e4:5b:58:85:7f:42:
87:e7:0c:b4:bf:ea:c9:c6:70:be:24:91:75:22:eb:
83:cc:b2:03:3f:b9:cf:bf:d5:53:5e:b8:10:9b:44:
f8:db:b5:e4:9d:33:94:ef:36:47:cb:81:52:a0:46:
36:14:7f:d2:34:05:bc:df:30:ae:ec:9a:85:db:57:
5c:da:b8:a4:70:84:b0:05:af:6a:a1:d3:ce:39:4e:
d2:cf:ef:dc:2d:c0:af:84:82:b2:0c:78:49:e0:99:
11:63:04:77:69:b7:0a:11:5f:0a:9f:98:ff:9e:a8:
c0:24:2e:0c:62:ab:fe:11:24:20:cf:98:98:69:0c:
f6:b4:52:64:64:d2:e5:ac:68:4a:5e:c5:ca:58:5f:
5c:8d:b3:10:1f:24:e3:2b:f0:b2:7c:aa:79:79:cd:
c2:4f:71:2d:b8:ab:47:66:b0:45:5d:0d:d6:52:cd:
f2:bc:96:c6:ec:06:16:41:a3:a5:dd:27:cf:26:91:
d7:69:4e:3e:c2:1c:df:ad:a6:a1:b5:a4:79:78:a3:
0e:b1:14:b9:ab:06:7e:b6:04:44:b4:5d:b8:70:9c:
80:43:7d:45:8a:40:26:2f:cd:f6:e3:e5:52:fe:58:
06:f3:b1:fe:84:56:cb:45:09:e2:1d:f5:ed:2d:a5:
3a:4b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Subject Key Identifier:
82:FF:65:DF:8C:01:E8:D0:1B:A2:B2:31:69:A2:78:79:E5:06:FC:AD
X509v3 Authority Key Identifier:
keyid:58:DD:52:46:97:11:C5:D3:50:B8:8E:F2:34:87:0C:48:78:47:75:B7
Authority Information Access:
CA Issuers - URI:http://vault.gengar.com/v1/pki_int_gnr_ca/ca
X509v3 CRL Distribution Points:Full Name:
URI:http://vault.gengar.com/v1/pki_int_gnr_ca/crl
Signature Algorithm: sha256WithRSAEncryption
13:db:69:0f:e1:2d:0b:1d:e6:f9:94:52:ad:7f:53:10:89:64:
d5:e2:cf:f6:5d:a3:c1:c4:fe:cf:85:34:6b:c0:76:c4:71:96:
a4:c3:49:01:54:ae:0e:14:62:11:b4:0f:94:f9:56:3c:99:ec:
d2:3c:11:99:b0:d9:9f:c1:4f:78:6a:d6:78:46:8e:e2:8a:58:
2f:85:05:13:f2:58:47:35:bc:61:77:23:9d:7a:66:f8:88:be:
e3:82:6b:4c:15:7c:3f:fb:a9:ae:43:b8:1f:ec:95:f9:52:03:
2f:e9:71:80:98:48:71:70:f2:4f:13:6c:33:12:ba:1a:40:d3:
60:64:43:a7:a2:3e:a2:34:43:6e:74:99:35:85:c6:38:02:df:
95:be:60:54:ac:a9:18:54:27:60:05:32:48:0b:a6:86:ac:bb:
94:d9:45:a1:0b:66:a3:a8:4d:be:f0:db:68:08:13:fb:93:a9:
8b:8d:25:e0:a8:49:99:8a:16:78:d5:49:fc:7e:4f:a7:d8:b8:
e7:bf:96:87:de:ca:27:80:08:c3:2c:28:db:c3:8a:de:64:be:
af:07:a9:64:a5:06:23:d3:d0:d6:64:29:f8:33:70:7d:70:8c:
4d:55:28:f3:0c:04:55:99:a0:06:d6:0b:db:da:c7:e1:3c:30:
e4:8a:f1:f6:45:17:c3:a0:76:2a:72:cf:42:cd:ca:b5:c7:2c:
ad:5c:8e:67:ed:51:96:bf:8e:39:64:78:25:f3:84:43:11:8f:
a5:39:36:b4:53:b5:05:b3:f2:a3:fe:fb:c6:ff:48:5c:2f:b5:
6b:3c:d7:25:ee:8a:eb:af:13:02:b6:94:86:d3:af:66:a1:c9:
51:70:1e:ef:d0:26:6e:54:0c:0b:ab:f2:af:19:b9:bc:03:72:
d2:f5:a5:8e:d8:2e:b1:22:7c:9a:90:5d:8d:8a:9e:b3:31:74:
44:58:52:23:34:24:ce:70:31:bb:f8:29:be:2e:0f:aa:a1:47:
61:bf:b0:75:83:03:00:fe:f4:66:07:f6:5d:65:c9:8b:45:2b:
e6:01:67:81:6e:c4:5d:e4:0f:39:2d:fd:c0:9a:bd:f9:dd:ee:
9a:23:11:18:d6:cf:71:f1:a1:70:89:a2:5f:c7:05:49:e4:72:
12:fc:c5:66:f0:a4:7d:c0:1c:4d:87:8b:98:34:46:cc:08:6c:
04:58:fe:8d:6e:0d:00:2d:9e:82:a7:ef:3c:5a:04:7b:13:48:
c6:c8:53:47:e3:91:71:48:27:6e:16:47:ec:79:ea:a2:55:28:
35:78:97:e2:47:02:1d:15:67:d0:2f:79:a7:49:a8:0c:1c:d1:
11:2b:1b:5e:96:80:d7:1c

If you have any questions feel free to leave a comment and I will respond as soon as I can.

--

--