Using Hashicorp Vault as a PKI SSL/TLS CA

Posted on July 9, 2016

Encrypting data is important, both in transit and at rest. By far the most popular method of in-transit encryption is SSL/TLS. That sad truth is, except for our public facing web sites, most administrators rarely use it unless they have to. Many companies only run their own CA for VPN’s or LDAP infrastructure, and they tend to use old solutions like Easy-RSA.

Hashicorp’s Vault burst onto the scene last year and has taken secrets management to the next level. One underrated capability of Vault is to act as a Certificate Authority (CA) via the PKI secrets backend. The docs are a little thin for helping people get going, so I wanted to provide a complete walkthrough to help people explore this exciting capability of Vault.

In this tutorial we’ll:

Setup a Vault Server

Create a Root CA for our organization

Create an Intermediate CA for our organization

Create TLS Keys and Certificates for a web server

Test the certificate using NGINX

I want to clarify at the outset that this is a proof-of-concept walkthrough and doesn’t necessarily constitute good or best practices. Our focus here is on the basics of utilizing the PKI backends for our purposes. A real-world deployment of Vault should be setup in HA mode, be protected with TLS itself, utilize non-root tokens and policies, and the TTL’s associated with your CA’s and Certs should be carefully considered depending on your deployment.

The most exciting aspect of Vault as a CA is that your end-points requiring protection can request certs and keys directly from Vault whenever they wish. This means that you can set really low TTL’s on your certificates and simply update them from cron on a regular basis. That functionality however is something I’ll cover in a separate blog, but be assured that it is that capability that takes Vault from a nifty alternative to EasyRSA or CFSSL to a mind-blowing game changer for how we manage TLS.

Starting Vault

After downloading Vault, I’m going to create a directory into which it’ll store secrets and configuration. We’ll create a basic configuration file and start the server:

Creating a Root CA

Within Vault, secrets are managed by “backends”. To use a backend it must be mounted. When you get started with Vault this seems very odd, but there turns out to be a good reason. Backends can be mounted multiple times with different paths. This is extremely important when we do PKI because each PKI backend can only represent a single CA! Therefore, we’ll be mounting the PKI backend twice, once for the Root CA and one more for the Intermediate CA. In this way, you can support as many CA’s as you wish on a single Vault server, keeping them completely distinct.

So, we begin by mounting a PKI backend for our “cuddletech” Root CA. When we mount it, we’ll provide a “path” (used for accessing the specific backend), description, and maximum lease TTL:

Excellent! We have a CA! Lets look at the certificate to verify. We’ll pull this certificate via curl and pipe the PEM into openssl (the vault CLI has a bug the makes it preferable to use curl in this case):

Creating an Intermediate CA

Creating the Intermediate CA is similar to that of the Root CA, with the big difference being that instead of creating a Cert and Key in one action, we’ll create a key and CSR, then sign that CSR by the Root before putting the resulting Cert back into the intermediate. So we’ll be working with a second PKI backend but switching back into the first just to sign the CSR.

So, again, create a new backend for the intermediate. We’ll call this the Ops Intermediate CA:

Requesting a Certificate for a Web Server

Now that our CA’s are configured, we’ll want to issue certificates. Doing so requires 2 steps. First we create a role which defines constraints around the certificates we generate, such as key type and strength, types of certificates allowed, etc. Secondly we’ll actually request a certificate using the role.

We’ll create a role named “web_server” on our Intermediate CA, which issues 2048 bit keys with a maximum TTL of 1 year and allows any name.

Since we’re using NGINX, we’ll put the certificate and issuing_ca certs into a single file named ssl_test.cuddletech.com.crt. We’ll put the private_key into ssl_test.cuddletech.com.key.

Now we’re ready to setup NGINX!

Testing our Cert with NGINX

To test our certificate we’ll use NGINX. Remember that NGINX expects the CA certificate to be appended into the same file as the ssl_certificate (server cert first, then CA cert afterwards). Copy the cert and key files to NGINX and start it up.

Once NGINX is up, point your browser at it and you’ll get the old familiar “Your connection is not secure” warning. All we need to do is extract our Root CA certificate and import it into our browser thanks to chains of trust! To export the root CA: