The PKI secrets engine generates dynamic X.509 certificates. With this secrets
engine, services can get certificates without going through the usual manual
process of generating a private key and CSR, submitting to a CA, and waiting for
a verification and signing process to complete. Vault's built-in authentication
and authorization mechanisms provide the verification functionality.
By keeping TTLs relatively short, revocations are less likely to be needed,
keeping CRLs short and helping the secrets engine scale to large workloads. This
in turn allows each instance of a running application to have a unique
certificate, eliminating sharing and the accompanying pain of revocation and
rollover.
In addition, by allowing revocation to mostly be forgone, this secrets engine
allows for ephemeral certificates. Certificates can be fetched and stored in
memory upon application startup and discarded upon shutdown, without ever being
written to disk.
Most secrets engines must be configured in advance before they can perform their
functions. These steps are usually completed by an operator or configuration
management tool.
Note that individual roles can restrict this value to be shorter on a
per-certificate basis. This just configures the global maximum for this
secrets engine.
Configure a CA certificate and private key. Vault can accept an existing key
pair, or it can generate its own self-signed root. In general, we recommend
maintaining your root CA outside of Vault and providing Vault a signed
intermediate CA.
The returned certificate is purely informative. The private key is safely
stored internally in Vault.
Update the CRL location and issuing certificates. These values can be updated
in the future.
$ 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"
Success! Data written to: pki/config/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"Success! Data written to: pki/config/urls
Configure a role that maps a name in Vault to a procedure for generating a
certificate. When users or machines generate credentials, they are generated
against this role:
$ vault write pki/roles/example-dot-com \
allowed_domains=my-website.com \
allow_subdomains=true \
max_ttl=72h
Success! Data written to: pki/roles/example-dot-com
$ vault write pki/roles/example-dot-com \ allowed_domains=my-website.com \ allow_subdomains=true \ max_ttl=72hSuccess! Data written to: pki/roles/example-dot-com
The output will include a dynamically generated private key and certificate
which corresponds to the given role and expires in 72h (as dictated by our
role definition). The issuing CA and trust chain is also returned for
automation simplicity.
To successfully deploy this secrets engine, there are a number of important
considerations to be aware of, as well as some preparatory steps that should be
undertaken. You should read all of these before using this secrets engine or
generating the CA to use with this secrets engine.
Vault storage is secure, but not as secure as a piece of paper in a bank vault.
It is, after all, networked software. If your root CA is hosted outside of
Vault, don't put it in Vault as well; instead, issue a shorter-lived
intermediate CA certificate and put this into Vault. This aligns with industry
best practices.
Since 0.4, the secrets engine supports generating self-signed root CAs and
creating and signing CSRs for intermediate CAs. In each instance, for security
reasons, the private key can only be exported at generation time, and the
ability to do so is part of the command path (so it can be put into ACL
policies).
If you plan on using intermediate CAs with Vault, it is suggested that you let
Vault create CSRs and do not export the private key, then sign those with your
root CA (which may be a second mount of the pki secrets engine).
In order to vastly simplify both the configuration and codebase of the PKI
secrets engine, only one CA certificate is allowed per secrets engine. If you
want to issue certificates from multiple CAs, mount the PKI secrets engine at
multiple mount points with separate CA certificates in each.
This also provides a convenient method of switching to a new CA certificate
while keeping CRLs valid from the old CA certificate; simply mount a new secrets
engine and issue from there.
A common pattern is to have one mount act as your root CA and to use this CA
only to sign intermediate CA CSRs from other PKI secrets engines.
This secrets engine aligns with Vault's philosophy of short-lived secrets. As
such it is not expected that CRLs will grow large; the only place a private key
is ever returned is to the requesting client (this secrets engine does not
store generated private keys, except for CA certificates). In most cases, if the
key is lost, the certificate can simply be ignored, as it will expire shortly.
If a certificate must truly be revoked, the normal Vault revocation function can
be used; alternately a root token can be used to revoke the certificate using
the certificate's serial number. Any revocation action will cause the CRL to be
regenerated. When the CRL is regenerated, any expired certificates are removed
from the CRL (and any revoked, expired certificate are removed from secrets
engine storage).
This secrets engine does not support multiple CRL endpoints with sliding date
windows; often such mechanisms will have the transition point a few days apart,
but this gets into the expected realm of the actual certificate validity periods
issued from this secrets engine. A good rule of thumb for this secrets engine
would be to simply not issue certificates with a validity period greater than
your maximum comfortable CRL lifetime. Alternately, you can control CRL caching
behavior on the client to ensure that checks happen more often.
Often multiple endpoints are used in case a single CRL endpoint is down so that
clients don't have to figure out what to do with a lack of response. Run Vault in HA mode, and the CRL endpoint should be available even if a particular node
is down.
»You must configure issuing/CRL/OCSP information in advance
This secrets engine serves CRLs from a predictable location, but it is not
possible for the secrets engine to know where it is running. Therefore, you must
configure desired URLs for the issuing certificate, CRL distribution points, and
OCSP servers manually using the config/urls endpoint. It is supported to have
more than one of each of these by passing in the multiple URLs as a
comma-separated string parameter.
Since its inception, this secrets engine has enforced SHA256 for signature
hashes rather than SHA1. As of 0.5.1, a minimum of 2048 bits for RSA keys is
also enforced. Software that can handle SHA256 signatures should also be able to
handle 2048-bit keys, and 1024-bit keys are considered unsafe and are disallowed
in the Internet PKI.
When a token expires, it revokes all leases associated with it. This means that
long-lived CA certs need correspondingly long-lived tokens, something that is
easy to forget. Starting with 0.6, root and intermediate CA certs no longer have
associated leases, to prevent unintended revocation when not using a token with
a long enough lifetime. To revoke these certificates, use the pki/revoke
endpoint.
Next, Vault must be configured with a CA certificate and associated private
key. We'll take advantage of the backend's self-signed root generation support,
but Vault also supports generating an intermediate CA (with a CSR for signing)
or setting a PEM-encoded certificate and private key bundle directly into the
backend.
Generally you'll want a root certificate to only be used to sign CA
intermediate certificates, but for this example we'll proceed as if you will
issue certificates directly from the root. As it's a root, we'll want to set a
long maximum life time for the certificate; since it honors the maximum mount
TTL, first we adjust that:
$vault secrets tune -max-lease-ttl=87600h pkiSuccessfully tuned mount 'pki'!
$vault secrets tune -max-lease-ttl=87600h pkiSuccessfully tuned mount 'pki'!
That sets the maximum TTL for secrets issued from the mount to 10 years. (Note
that roles can further restrict the maximum TTL.)
Generated certificates can have the CRL location and the location of the
issuing certificate encoded. These values must be set manually and typically to FQDN associated to the Vault server, but can be changed at any time.
$vault write pki/config/urls issuing_certificates="http://vault.example.com:8200/v1/pki/ca"crl_distribution_points="http://vault.example.com:8200/v1/pki/crl"Success! Data written to: pki/ca/urls
$vault write pki/config/urls issuing_certificates="http://vault.example.com:8200/v1/pki/ca"crl_distribution_points="http://vault.example.com:8200/v1/pki/crl"Success! Data written to: pki/ca/urls
The next step is to configure a role. A role is a logical name that maps to a
policy used to generate those credentials. For example, let's create an
"example-dot-com" role:
$vault write pki/roles/example-dot-com \ allowed_domains=example.com \ allow_subdomains=true max_ttl=72hSuccess! Data written to: pki/roles/example-dot-com
$vault write pki/roles/example-dot-com \ allowed_domains=example.com \ allow_subdomains=true max_ttl=72hSuccess! Data written to: pki/roles/example-dot-com
By writing to the roles/example-dot-com path we are defining the
example-dot-com role. To generate a new certificate, we simply write
to the issue endpoint with that role name: Vault is now configured to create
and manage certificates!
Vault has now generated a new set of credentials using the example-dot-com
role configuration. Here we see the dynamically generated private key and
certificate.
Using ACLs, it is possible to restrict using the pki backend such that trusted
operators can manage the role definitions, and both users and applications are
restricted in the credentials they are allowed to read.
If you get stuck at any time, simply run vault path-help pki or with a
subpath for interactive help output.
In the Quick Start guide, certificates were issued directly from the root
certificate authority. As described in the example, this is not a recommended
practice. This guide builds on the previous guide's root certificate authority
and creates an intermediate authority using the root authority to sign the
intermediate's certificate.
Take the signing request from the intermediate authority and sign it using
another certificate authority, in this case the root certificate authority
generated in the first example.
Generated certificates can have the CRL location and the location of the
issuing certificate encoded. These values must be set manually, but can be
changed at any time.
$vault write pki_int/config/urls issuing_certificates="http://127.0.0.1:8200/v1/pki_int/ca"crl_distribution_points="http://127.0.0.1:8200/v1/pki_int/crl"Success! Data written to: pki_int/ca/urls
$vault write pki_int/config/urls issuing_certificates="http://127.0.0.1:8200/v1/pki_int/ca"crl_distribution_points="http://127.0.0.1:8200/v1/pki_int/crl"Success! Data written to: pki_int/ca/urls
The next step is to configure a role. A role is a logical name that maps to a
policy used to generate those credentials. For example, let's create an
"example-dot-com" role:
$vault write pki_int/roles/example-dot-com \ allowed_domains=example.com \ allow_subdomains=true max_ttl=72hSuccess! Data written to: pki_int/roles/example-dot-com
$vault write pki_int/roles/example-dot-com \ allowed_domains=example.com \ allow_subdomains=true max_ttl=72hSuccess! Data written to: pki_int/roles/example-dot-com
By writing to the roles/example-dot-com path we are defining the
example-dot-com role. To generate a new certificate, we simply write
to the issue endpoint with that role name: Vault is now configured to create
and manage certificates!
Vault has now generated a new set of credentials using the example-dot-com
role configuration. Here we see the dynamically generated private key and
certificate. The issuing CA certificate and CA trust chain are returned as well.
The CA Chain returns all the intermediate authorities in the trust chain. The root
authority is not included since that will usually be trusted by the underlying
OS.