DEC 06 2018 CHRISTIE KOEHLERhtml
HashiCorp Vault provides secrets management and protection of sensitive data. It provides a central place to secure, store, and control access to tokens, passwords, certificates, and encryption keys. There are challenges of centralized secrets management, particularly related to applications. Applications don’t keep secrets and secrets are often shared among different applications.git
Vault presents an answer to these problems in the form of github
Dynamic secrets allows us to golang
Vault applies a dynamic secret approach to public key certificates as well, acting as a signing intermediary to generate short lived certificates. This allows certificates to be generated on-demand, as needed, and rotated automatically.web
In this post we’ll look at the most common operator activities involved in certificate management using Vault. We’ll cover:json
Vault supports many secrets engines. To use a secrets engine, you enable it at a given api
$ vault secrets enable pki
Success! Enabled the pki secrets engine at: pki/複製代碼
The default is for engines to be enabled at a path named for their type (e.g. pki
for the PKI engine, as seen above). With few exceptions, secrets engines can be enabled at multiple paths by enabling each with a unique name. Enabled secrets engines cannot see each other’s data, even if they are of the same type.bash
To specify a mount point, use the -path
argument when enabling the engine.app
For example, to create a second PKI secrets engine to act as your intermediate signing authority, you would do the following, after creating the first engine pki
above:less
$ vault secrets enable -path=pki-inter pki
Success! Enabled the pki secrets engine at: pki-inter/複製代碼
To issue commands to this instance of the secrets engine, you’ll need to use the pki-inter
prefix rather than pki
. For example: vault write pki-inter/config/ca
instead of vault write pki/config/ca
.
Often it also makes sense to adjust the global maximum time-to-live (TTL) of tokens and leases for this secrets engine. The default is 30 days which might be too short. Individual roles can restrict this value to be shorter on a per-certificate basis.
Here’s how to adjust the TTL to one year:
$ vault secrets tune -max-lease-ttl=8760h pki
Success! Tuned the secrets engine at: pki/複製代碼
You’ll need to do this for each PKI engine you’ve enabled.
Each PKI secrets engine must be configured with a CA certificate and associated private key.
There are three methods for accomplishing this:
You’ll also need to configure a root CA. You can have Vault generate a self-signed root CA or provide the details for your root CA. There are separate end points for each.
To generate a self-signed root CA, use the pki/root/generate endpoint:
$ vault write pki/root/generate/internal \
common_name=my-website.com \
ttl=8760h複製代碼
To generate an intermediate CA, use the /pki/intermediate/generate/ endpoint:
$ vault write pki/intermediate/generate/internal common_name=example.com data=@pem_bundle.json複製代碼
To set a PEM-encoded certificate and private key bundle, use the pki/config/ca endpoint:
$ vault write pki/config/ca pem_bundle=@pem_bundle.json複製代碼
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.
A common and recommended 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. See Build Your Own Certificate Authority (CA) on HashiCorp Learn or our webinar Streamline Certificate Management for further details.
For each PKI engine that you enable you’ll need to configure the url values for issuing certificate endpoints and CRL distribution points that will be encoded into issued certificates:
$ 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複製代碼
Generating certificates requires you to supply a
Use the /pki/roles/:name endpoint to create and update roles:
$ vault write pki/roles/example-dot-com \
allowed_domains=example.com \
allow_subdomains=true max_ttl=72h
Success! Data written to: pki/roles/example-dot-com複製代碼
The roles endpoint accepts a number of parameters and nearly any issuing policy can be accommodated. If a client requests a certificate that is not allowed by the role, the request is denied.
Once a role has been created, you can use it to generate certificates with the pki/issue endpoint:
$ vault write pki/issue/example-dot-com \
common_name=my.example.com
Key Value
--- -----
certificate -----BEGIN CERTIFICATE-----複製代碼
A certificate can be renewed at any time by providing issue
with the same common name as an existing certificate. The original certificate will continue to be valid through its original time-to-live unless explicitly revoked.
If a certificate must be revoked, you can easily perform the revocation action which will cause the CRL (Certificate Revocation List) to be regenerated. When the CRL is regenerated, any expired certificates are removed from the CRL.
$ vault write pki/revoke serial_number=<serial_number>複製代碼
Operators can also trigger rotation of the CRLs directly with the pki/crl/rotate endpoint. Because this end point doesn’t ingest any data, you’ll need to use the vault read
command instead of write
:
$ vault read pki/crl/rotate
Key Value
--- -----
success true複製代碼
As with all Vault commands, you can also interact with the API directly, as such:
$ curl \
--header "X-Vault-Token: ..." \
http://127.0.0.1:8200/v1/pki/crl/rotate複製代碼
There’s also the Vault UI, available in version 0.10+, as well as Vault Enterprise.
Using the tidy endpoint, operators can optimize the storage backend and CRL by periodically removing certificates that have expired and are past a certain buffer period beyond their expiration time.
$ vault write pki/tidy tidy_cert_store=true tidy_revoked_certs=true複製代碼
Already you can see how generating PKI certificates with Vault saves operators time. A
To automate the process further, use a template rendering tool such as Consul Template.
Consul Template is a daemon that queries a Consul or Vault cluster and updates any number of specified templates on the file system. Rendering templates requires both a
When generating PKI certificates with Vault, the certificate, private key, and any intermediate certs are all returned as part of the same API call. Most applications require that this data be placed in separate files on the system.
Here are the templates we can use to retrieve the necessary certificate files and save them locally:
{{- /* /tmp/cert.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.certificate }}{{ end }}
{{- /* /tmp/ca.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.issuing_ca }}{{ end }}
{{- /* /tmp/key.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.private_key }}{{ end }}複製代碼
The with secret
directive queries Vault at the supplied API endpoint (「pki/issue/example-dot-com」) with the given parameters (「common_name=my.example.com」). This is equivalent to the Vault command we showed earlier for generating certificates: vault write pki/issue/example-dot-com
.
Consul Template writes the data returned by Vault into .Data.certificate
, .Data.issuing_ca
, and .Data.private_key
, which directly correspond to the data returned by the Vault API:
{
...
"data": {
"certificate": "-----BEGIN CERTIFICATE-----",
"issuing_ca": "-----BEGIN CERTIFICATE-----",
"private_key": "-----BEGIN RSA PRIVATE KEY-----",
...
},
}複製代碼
In this example, there are three different input templates. But, when run under the same Consul Template process, they are compressed into a single API call, sharing the resulting data.
Here is an example the corresponding Consul Template configuration:
template {
source = "/tmp/cert.tpl"
destination = "/opt/my-app/ssl/my-app.crt"
}
template {
source = "/tmp/ca.tpl"
destination = "/opt/my-app/ssl/ca.crt"
}
template {
source = "/tmp/key.tpl"
destination = "/opt/my-app/ssl/my-app.key"
}複製代碼
Use multiple template
blocks to define multiple templates. The source
directive indicates which source file on disk to use as the input template. The destination
directive indicates the path on disk where the source template will render.
Consul Template will fetch a new secret at
max_ttl=72h
. Because we did not specify a
ttl
when we created our certificate with
vault write pki/issue/example-dot-com
, it will have a
For more examples of using Consul template, see the examples directory in the project.
To learn more, see: