Skip to content

Instantly share code, notes, and snippets.

@stenio123
Last active October 11, 2018 20:28
Show Gist options
  • Save stenio123/30fcbad606b7901caecd29ba2ba0ca84 to your computer and use it in GitHub Desktop.
Save stenio123/30fcbad606b7901caecd29ba2ba0ca84 to your computer and use it in GitHub Desktop.
Using Vault to retrieve short lived certificates, and Consul Template to transparently manage the renewal

PKI Secret Engine

Create Limited Policy and Token for this demo

cat > pki.policy <<EOA
# 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" ]
}
EOA

vault policy write pki pki.hcl
vault token create -policy=pki -field=token

Enable and Configure CA - Root and Intermediate

For this demo we will allow users to operate with the intermediate, which is a best practice. If desired, the root could be used instead, but it would limit your flexibility of revoking the certificate.

echo $VAULT_ADDR
echo $VAULT_TOKEN

vault secrets enable pki

vault secrets tune -max-lease-ttl=87600h pki

# Generate the root certificate and save the certificate in 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).
# This assumes no root certificate exists. If it does, you will need to explicitly delete before recreating using this command.
vault write -field=certificate pki/root/generate/internal common_name="example.com" \
        ttl=87600h > CA_cert.crt

# Print the validity dates
openssl x509 -in CA_cert.crt -noout -dates

# Configure the CA and CRL URLs:
vault write pki/config/urls \
        issuing_certificates="$VAULT_ADDR/v1/pki/ca" \
        crl_distribution_points="$VAULT_ADDR/v1/pki/crl"
        
# Generate intermediate
vault secrets enable -path=pki_int pki
vault secrets tune -max-lease-ttl=43800h pki_int
vault write -format=json pki_int/intermediate/generate/internal \
        common_name="example.com Intermediate Authority" ttl="43800h" \
        | jq -r '.data.csr' > pki_intermediate.csr

# Sign intermediate with root
vault write -format=json pki/root/sign-intermediate csr=@pki_intermediate.csr \
        format=pem_bundle \
        | jq -r '.data.certificate' > intermediate.cert.pem
        
# Store intermediate - check for alternative approach here https://www.vaultproject.io/api/secret/pki/index.html#generate-intermediate
vault write pki_int/intermediate/set-signed [email protected]

Create Certificate Role

# 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 usages that they are valid for, and more.
vault write pki_int/roles/example-dot-com \
        allowed_domains="example.com" \
        allow_subdomains=true \
        generate_lease=true \
        max_ttl="720h"
        
# NOTE: Generate_lease is used to allow Consul template to renew this certificate. However if a large number of certificates is generated, this will have a performance impact. The default is false, not generating a Vault lease per certificate.

Request Certificate

# Request certificate
vault write pki_int/issue/example-dot-com common_name="test.example.com" ttl="24h"
#-> The response contains the PEM-encoded private key, key type and certificate serial number.

Revoke Certificate

vault write pki_int/revoke serial_number=<serial_number>

Using with Consul Template

In one terminal window, download and run consul template as a process. With this configuration it will request a short lived certificate, and renew it before half the ttl is reached

wget https://releases.hashicorp.com/consul-template/0.19.5/consul-template_0.19.5_linux_amd64.zip
unzip consul-template_0.19.5_linux_amd64.zip

cat > cert.pem.tpl <<EOA
{{ with secret "pki_int/issue/example-dot-com" "common_name=test2.example.com" "ttl=10s" }}
{{ .Data.certificate }}{{ end }}
EOA

# NOTE: Consul-template will issue error messages if you are using the root token. Please create a token with a limited policy as described above. This behavior is because consul-template will try to renew its own VAULT_TOKEN, and the root token cannot be renewed.

consul-template \
    -template "cert.pem.tpl:cert.pem:echo 'realoded cert!'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment