Vault's PKI secrets engine can dynamically generate X.509 certificates on demand. This allows services to acquire certificates without going through the usual manual process of generating a private key and Certificate Signing Request (CSR), submitting to a CA, and then waiting for the verification and signing process to complete.
»Personas
The steps described in this tutorial are typically performed by a security engineer.
»Challenge
Organizations should protect their website; however, the Traditional PKI process workflow takes a long time which motivates organizations to create certificates which do not expire for a year or more.
»Solution
Use Vault to create X509 certificates for usage in MTLS or other arbitrary PKI encryption. While this can be used to create web server certificates. If users do not import the CA chains, the browser will complain about self-signed certificates.
Creating PKI certificates is generally a cumbersome process using traditional
tools like openssl
or even more advanced frameworks like CFSSL. These tools
also require a human component to verify certificate distribution meets
organizational security policies.
Vault PKI secrets engine makes this a lot simpler. The PKI secrets engine can be an Intermediate-Only certificate authority which potentially allows for higher levels of security.
- Store CA outside the Vault (air gapped)
- Create CSRs for the intermediates
- Sign CSR outside Vault and import intermediate
- Issue leaf certificates from the Intermediate CA
»Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault environment. Refer to the Getting Started to install Vault.
NOTE: An interactive tutorial is also available if you do not have a Vault environment to perform the steps described in this tutorial. Click the Show Terminal button to start.
»Policy requirements
NOTE: For the purpose of this tutorial, you can use root
token to work
with Vault. However, it is recommended that root tokens are only used for just
enough initial setup or in emergencies. As a best practice, use tokens with
appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this tutorial, your policy must include the following permissions:
# Enable secrets engine
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# List enabled secrets engine
path "sys/mounts" {
capabilities = [ "read", "list" ]
}
# Work with pki secrets engine
path "pki*" {
capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]
}
If you are not familiar with policies, complete the policies tutorial.
»Scenario Introduction
In this tutorial, you are going to first generate a self-signed root certificate.
Then you are going to generate an intermediate certificate which is signed by
the root. Finally, you are going to generate a certificate for the
test.example.com
domain.
Each step will be illustrated in three ways but you only need to follow the steps for one.
- CLI command
- API calls with cURL
- Web UI
In this tutorial, you will perform the following:
- Generate Root CA
- Generate Intermediate CA
- Create a Role
- Request Certificates
- Revoke Certificates
- Remove Expired Certificates
»Step 1: Generate Root CA
In this step, you are going to generate a self-signed root certificate using PKI secrets engine.
First, enable the
pki
secrets engine at thepki
path.$ vault secrets enable pki
Tune the
pki
secrets engine to issue certificates with a maximum time-to-live (TTL) of 87600 hours.$ vault secrets tune -max-lease-ttl=87600h pki
Generate the root certificate and save the certificate in
CA_cert.crt
.$ vault write -field=certificate pki/root/generate/internal \ common_name="example.com" \ ttl=87600h > CA_cert.crt
This generates a new self-signed CA certificate and private key. Vault will automatically revoke the generated root at the end of its lease period (TTL); the CA certificate will sign its own Certificate Revocation List (CRL).
Configure the CA and CRL URLs.
$ vault write pki/config/urls \ issuing_certificates="http://127.0.0.1:8200/v1/pki/ca" \ crl_distribution_points="http://127.0.0.1:8200/v1/pki/crl"
»Step 2: Generate Intermediate CA
Now, you are going to create an intermediate CA using the root CA you regenerated in the previous step.
First, enable the
pki
secrets engine at thepki_int
path.$ vault secrets enable -path=pki_int pki
Tune the
pki_int
secrets engine to issue certificates with a maximum time-to-live (TTL) of 43800 hours.$ vault secrets tune -max-lease-ttl=43800h pki_int
Execute the following command to generate an intermediate and save the CSR as
pki_intermediate.csr
.$ vault write -format=json pki_int/intermediate/generate/internal \ common_name="example.com Intermediate Authority" \ | jq -r '.data.csr' > pki_intermediate.csr
Sign the intermediate certificate with the root certificate and save the generated certificate as
intermediate.cert.pem
.$ vault write -format=json pki/root/sign-intermediate csr=@pki_intermediate.csr \ format=pem_bundle ttl="43800h" \ | jq -r '.data.certificate' > intermediate.cert.pem
Once the CSR is signed and the root CA returns a certificate, it can be imported back into Vault.
$ vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem
»Step 3: Create a Role
A role is a logical name that maps to a policy used to generate those credentials. It allows configuration parameters to control certificate common names, alternate names, the key uses that they are valid for, and more.
Here are a few noteworthy parameters:
Param | Description |
---|---|
allowed_domains | Specifies the domains of the role (used with allow_bare_domains and allow-subdomains options) |
allow_bare_domains | Specifies if clients can request certificates matching the value of the actual domains themselves |
allow_subdomains | Specifies if clients can request certificates with CNs that are subdomains of the CNs allowed by the other role options (NOTE: This includes wildcard subdomains.) |
allow_glob_domains | Allows names specified in allowed_domains to contain glob patterns (e.g. ftp*.example.com) |
In this step, you are going to create a role named example-dot-com
.
Create a role named example-dot-com
which allows subdomains.
$ vault write pki_int/roles/example-dot-com \
allowed_domains="example.com" \
allow_subdomains=true \
max_ttl="720h"
»Step 4: Request Certificates
Keep certificate lifetimes short to align with Vault's philosophy of short-lived secrets.
Execute the following command to request a new certificate for the
test.example.com
domain based on the example-dot-com
role.
$ vault write pki_int/issue/example-dot-com common_name="test.example.com" ttl="24h"
Key Value
--- -----
certificate -----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgIUTQABMCAsXjG6ExFTX8201xKVH4IwDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMB4XDTE4MDcyNDIxMTMxOVoX
...
-----END CERTIFICATE-----
issuing_ca -----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgIUbMYp39mdj7dKX033ZjK18rx05x8wDQYJKoZIhvcNAQEL
...
-----END CERTIFICATE-----
private_key -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAte1fqy2Ekj+EFqKV6N5QJlBgMo/U4IIxwLZI6a87yAC/rDhm
W58liadXrwjzRgWeqVOoCRr/B5JnRLbyIKBVp6MMFwZVkynEPzDmy0ynuomSfJkM
...
-----END RSA PRIVATE KEY-----
private_key_type rsa
serial_number 4d:00:01:30:20:2c:5e:31:ba:13:11:53:5f:cd:b4:d7:12:95:1f:82
The response contains the PEM-encoded private key, key type and certificate serial number.
»Step 5: Revoke Certificates
If a certificate must be revoked, you can easily perform the revocation action which will cause the CRL to be regenerated. When the CRL is regenerated, any expired certificates are removed from the CRL.
In certain circumstances, you may wish to revoke an issued certificate.
To revoke a certificate, execute the following command.
$ vault write pki_int/revoke serial_number=<serial_number>
Example:
$ vault write pki_int/revoke \
serial_number="48:97:82:dd:f0:d3:d9:7e:53:25:ba:fd:f6:77:3e:89:e5:65:cc:e7"
Key Value
--- -----
revocation_time 1532539632
revocation_time_rfc3339 2018-07-25T17:27:12.165206399Z
»Step 6: Remove Expired Certificates
Keep the storage backend and CRL by periodically removing certificates that have expired and are past a certain buffer period beyond their expiration time.
To remove revoked certificate and clean the CRL.
$ vault write pki_int/tidy tidy_cert_store=true tidy_revoked_certs=true
»Next steps
Check out the Streamline Certificate Management with HashiCorp Vault webinar recording.
Also, refer to the Vault PKI Secrets Engine Integration tutorial for an example of Nomad using the PKI secrets engine to generate and renew the X.509 certificates it uses. To automate the process, this tutorial leverages the Consul Template tool.