TeKanAid

HashiCorp Vault PKI Secrets Engine Demo for Certificate Management


Have you ever wondered if there is an easier way to manage certificates? In this post you will learn how to use HashiCorp Vault's PKI secrets engine to do so.

HashiCorpVaultPKI
Created: December 22, 2020 | Updated: November 30, 2021

Overview

Certificate management is not an easy task. Most system administrators dread the day they have to work on renewing a certificate. This is because of a couple of reasons:

  • It's a manual and complex process done every few years, so it's hard to remember everything. Therefore, you'll find that system administrators have a method of procedure stored somewhere for when they need to go through this process again.
  • It's risky because it may incur an outage during the process.

HashiCorp Vault's Public Key Infrastructure (PKI) secrets engine can streamline distributing TLS certificates and allows users to create PKI certificates with a single command. Vault PKI reduces the overhead around the usual manual process of:

  • Generating a private key and CSR
  • Submitting to a CA
  • Waiting for a verification and signing process to complete

This is all done while additionally providing an authentication and authorization mechanism to validate as well.

Vault PKI Secrets Engine

It's quite simple to issue certificates with Vault and we'll show you how in this blog post. You can now create short-lived certificates, which is considered best practice from a security point of view.

We use the Vault Terraform provider to build everything. You can also opt to use the CLI, API, or Web UI to run commands to configure Vault for PKI using this guide. If you've been following some of my blog posts, you'll see that I'm a big fan of using Terraform wherever possible to define our infrastructure as code.

Credit

This work is inspired by Steve Dillon's medium blog here.

Code

Subscribe to my newsletter to get access to the source code
You only need to subscribe once. Already subscribed? Enter your name and email to get instant access to the code.

Video

Below is a video explanation and demo.

HashiCorp Vault PKI Secrets Engine Demo for Certificate Management

Video Chapters

You can skip to the relevant chapters below:

  • 00:00 - Introduction
  • 03:43 - Terraform to create the Root and Intermediate CAs
  • 07:13 - Generate a leaf certificate for Grafana
  • 10:13 - Add the cert to Grafana
  • 11:20 - Chrome doesn't trust the cert
  • 12:30 - Add Root & Intermediate CAs to Windows Cert Store
  • 16:30 - Chrome now trusts the Grafana cert
  • 20:30 - Revoke the cert
  • 22:20 - Clear the CRL Cache in Windows 10
  • 23:25 - Chrome shows the cert is revoked
  • 24:44 - Walkthrough of the Terraform Code
  • 36:00 - Conclusion

Pre-requisites

The following is required to follow along:


Create the Root and Intermediate CAs in Vault

First, we need to run the env-vars.sh script to export the VAULT_ADDR and VAULT_TOKEN environment variables. We used the root token for Vault for this demo, but you should not do this in production. You would need to authenticate into Vault using your preferred authentication method.

env-vars.sh:

#!/bin/bash
export VAULT_ADDR=https://<url>
export VAULT_TOKEN=s.xxxxxxxxx

Next, we run terraform apply to create the root and intermediate CAs along with roles in Vault. For a walkthrough of the Terraform code, check this section of the video.

Create the Leaf Certificate with Vault

To create leaf certificates: Run the following command:

./create-server-certs.sh <cert_name> <common_name> <ip_sans> <TTL_in_seconds>

An example would look like this:

./create-server-certs.sh grafana docker01.home 192.168.1.80 31556952

Below is the bash script that we ran. Notice the certificate and private key are created inside of an output folder. Make sure not to push this output folder into GitHub.

create-server-certs.sh:

#!/bin/bash
# pass the name of the cert as the first argument to the script, common name as second argument, ip_sans as third, and TTL in seconds as fourth. Example: `./create-server-certs.sh grafana docker01.home 192.168.1.80 31556952`
set -eu

echo Creating cert for $1
echo Common name: $2
echo IP Sans: $3
echo TTL: $4

source ./env-vars.sh

mkdir -p output/$1

vault write pki-int-ca/issue/server-cert-for-home ttl=$4 common_name="$2" ip_sans="$3" -format=json > output/$1.json

cat output/$1.json | jq -r '.data.certificate' > output/$1/$1_cert.pem
cat output/$1.json | jq -r '.data.private_key' > output/$1/$1_key.pem
cat output/$1.json | jq -r '.data.issuing_ca' > output/$1/ca.pem
cat output/$1.json | jq -r '.data.ca_chain[]' > output/$1/ca_chain.pem

# Dump the certificates in text mode
openssl x509 -noout -text -in output/$1/ca.pem > output/$1/ca.pem.txt 
openssl x509 -noout -text -in output/$1/$1_cert.pem > output/$1/$1_cert.pem.txt

Moving the Certificate and the Private Key

Now that we have our certificate and key, we need to move them to the server where Grafana is running. Below is an scp command to do that.

# Example command to scp the folder containing the cert and the key from local to remote machine:
scp -r /mnt/c/Users/Sam/Deployments/HashiCorp/Vault/vault-ca-demo/output/grafana sam@192.168.1.80:/home/sam/automation/grafana/config/certs

You then need to reload Grafana so it can pick up the certificate. Now use your browser to navigate to the Grafana site using https. You'll notice that your browser gives you a warning message. Below is what it looks like in Chrome:

Error Certificate Authority Invalid

This message is basically saying that the browser doesn't trust this certificate because it doesn't know nor trust the CA that issued the certificate. This is because our Vault's root and intermediate CAs are not part of the certificate store of Windows. We'll see how to add these two CAs to the Windows certificate store in the next section.

Add the Root & Intermediate CAs to the Windows Certificate Store

The Windows certificate store doesn't understand the .pem format so we need to convert to the .crt format using the script below:

convert-pem.sh:

#!/bin/bash
# Convert the root and int certs from .pem to .crt to be used in the Windows Certificate Store
openssl x509 -outform der -in output/root_ca/ca_cert.pem -out output/root_ca/ca_cert.crt
openssl x509 -outform der -in output/int_ca/int_cert.pem -out output/int_ca/int_cert.crt

In the Microsoft Management Console (mmc):

  • You will need to import the root ca certificate into the Trusted Root Certification Authorities -> Certificates folder
  • Also, import the intermediate ca certificate into the Intermediate Certification Authorities -> Certificates folder
  • You may need to reboot the computer (I tried restarting the Chrome browser, but that didn't work)

Below you can see where we've imported both the Vault root and intermediate CAs in the Windows certificate store.

Vault Root CA added to Windows Cert Store

Vault Intermediate CA added to Windows Cert Store

You can also watch the video section going through the process here.

Chrome Trusts the Grafana Certificate

Now you can once again navigate to the Grafana URL using https. Make sure you open a new incognito window to avoid caching. When you do, you'll see that Chrome trusts the certificate issued as it trusts the entire certificate chain. The certificate chain is made up of the root CA and the intermediate CA.

Valid Grafana Certificate

Revoke the Certificate

You can revoke a certificate by following this example:

vault write pki-int-ca/revoke serial_number="62:d3:ac:77:93:25:34:11:e0:47:27:0f:d1:db:92:67:51:8c:30:3c"

You can also remove a revoked certificate and clean the Certificate Revocation List (CRL) by running this command:

vault write pki_int/tidy tidy_cert_store=true tidy_revoked_certs=true

Clear the CRL Cache in Windows

There is a CRL cache that needs to be flushed in Windows so that the Chrome browser reaches out to the CRL URL to check if the certificate was revoked. I found this out from this forum post.

To view the CRL Cache:

certutil -urlcache crl

To Clear it:

certutil -setreg chain\ChainCacheResyncFiletime @now

Chrome Shows the Certificate is Revoked

Now if you try navigating to the Grafana URL again, you won't be able to proceed because the certificate is revoked.

Grafana Certificate is Revoked

Conclusion

In this blog post, we talked about certificate management with the Vault PKI secrets engine. We saw how easy it was to create a root and intermediate CA inside of Vault. It was also quite quick and simple to create a leaf certificate for Grafana. We didn't need to go through the lengthy process of:

  1. Generating a private key and CSR
  2. Submitting to a CA
  3. Waiting for a verification and signing process to complete

We also witnessed how to revoke a certificate easily.

Most organizations have their own root CA which they use to sign an intermediate CA for Vault. They then import that intermediate CA into Vault and use Vault to issue leaf certificates. The leaf certificates issued by Vault now are trusted internally in an organization because the certificate chain is trusted based on the root CA.

You may be wondering if there is a way to automate the renewal of leaf certificates. Take a look at this post that talks about Consul-Template to Automate Certificate Management for HashiCorp Vault PKI.

References