Virtual Event
Join us for the next HashiConf Digital October 12-15, 2020 Register for Free

Secrets Management

Build Your Own Certificate Authority (CA)

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.


The steps described in this guide are typically performed by a security engineer.


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.


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.

  1. Store CA outside the Vault (air gapped)
  2. Create CSRs for the intermediates
  3. Sign CSR outside Vault and import intermediate
  4. Issue leaf certificates from the Intermediate CA


To perform the tasks described in this guide, you need to have a Vault environment. Refer to the Getting Started guide to install Vault.

Or you can use the Vault Playground environment.

»Policy requirements

To perform all tasks demonstrated in this guide, 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 guide.

»Scenario Introduction

In this guide, 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 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 guide, you will perform the following:

  1. Generate Root CA
  2. Generate Intermediate CA
  3. Create a Role
  4. Request Certificates
  5. Revoke Certificates
  6. 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.

  1. First, enable the pki secrets engine at the pki path.

    $ vault secrets enable pki
  2. 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
  3. Generate the root certificate and save the certificate in CA_cert.crt.

    $ vault write -field=certificate pki/root/generate/internal \
            common_name="" \
            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).

  4. Configure the CA and CRL URLs.

    $ vault write pki/config/urls \
            issuing_certificates="" \

»Step 2: Generate Intermediate CA

Now, you are going to create an intermediate CA using the root CA you regenerated in the previous step.

  1. First, enable the pki secrets engine at the pki_int path.

    $ vault secrets enable -path=pki_int pki
  2. 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
  3. 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=" Intermediate Authority" \
            | jq -r '.data.csr' > pki_intermediate.csr
  4. 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
  5. 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:

allowed_domainsSpecifies the domains of the role (used with allow_bare_domains and allow-subdomains options)
allow_bare_domainsSpecifies if clients can request certificates matching the value of the actual domains themselves
allow_subdomainsSpecifies 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_domainsAllows names specified in allowed_domains to contain glob patterns (e.g. ftp*

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="" \
        allow_subdomains=true \

»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 domain based on the example-dot-com role.

$ vault write pki_int/issue/example-dot-com common_name="" ttl="24h"

Key                 Value
---                 -----
certificate         -----BEGIN CERTIFICATE-----

issuing_ca          -----BEGIN CERTIFICATE-----

private_key         -----BEGIN 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>


$ vault write pki_int/revoke \
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 guide 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 guide leverages the Consul Template tool.

»Help and Reference