Skip to main content

Hashicorp Consul - Vault Cert Management Part 3

Shen Zhen, China

Configure consul-template

Create Template Files

We can now use Consul-Template to automate certificate renewal for Consul when the TTL is expired. We can instruct consul-template to generate and retrieve those files from Vault using the following templates:

mkdir /opt/consul/templates

/opt/consul/templates/agent.crt.tpl (Master only)

Careful: The official documentation uses the common_name for the default datacenter consul.dc1. I use the name consul here and have to change the variable consul.consul accordingly. Otherwise the cert verification will fail. This name will be used a couple of times in the following commands - you need to change all of them according to your setup.

{{ with secret "pki_int/issue/consul-consul" "common_name=server.consul.consul" "ttl=24h" "alt_names=localhost" "ip_sans=127.0.0.1"}}
{{ .Data.certificate }}
{{ end }}

The template will use the pki_int/issue/consul-consul endpoint that Vault exposes to generate new certificates.

/opt/consul/templates/agent.key.tpl (Master only)

{{ with secret "pki_int/issue/consul-consul" "common_name=server.consul.consul" "ttl=24h" "alt_names=localhost" "ip_sans=127.0.0.1"}}
{{ .Data.private_key }}
{{ end }}

/opt/consul/templates/ca.crt.tpl (All Nodes)

{{ with secret "pki_int/issue/consul-consul" "common_name=server.consul.consul" "ttl=24h"}}
{{ .Data.issuing_ca }}
{{ end }}

Not sure if this is necessary - but since the Consul agent is running with the consul user (Master node only) I will change the user rights:

chown -R consul:consul /opt/consul/templates

Create consul-template Configuration

Now we need to create a configuration file consul_template.hcl that will instruct Consul-Template to retrieve the files needed for the agent, client and server, to configure TLS encryption:

Server Configuration

/opt/consul/templates/consul_template.hcl (Master only)

# This denotes the start of the configuration section for Vault. All values
# contained in this section pertain to Vault.
vault {
# This is the address of the Vault leader. The protocol (http(s)) portion
# of the address is required.
address = "http://localhost:8200"

# This value can also be specified via the environment variable VAULT_TOKEN.
# I am using the admin token created earlier
token = "s.MdNlboI0nff3Xpo97d1TfIxd"

unwrap_token = false

renew_token = false
}

# This block defines the configuration for a template. Unlike other blocks,
# this block may be specified multiple times to configure multiple templates.
template {
# This is the source file on disk to use as the input template. This is often
# called the "consul-template template".
source = "/opt/consul/templates/agent.crt.tpl"

# This is the destination path on disk where the source template will render.
# If the parent directories do not exist, consul-template will attempt to
# create them, unless create_dest_dirs is false.
destination = "/opt/consul/agent-certs/agent.crt"

# This is the permission to render the file. If this option is left
# unspecified, consul-template will attempt to match the permissions of the
# file that already exists at the destination path. If no file exists at that
# path, the permissions are 0644.
perms = 0700

# This is the optional command to run when the template is rendered. The
# command will only run if the resulting template changes.
command = "sh -c 'date && consul reload'"
}

template {
source = "/opt/consul/templates/agent.key.tpl"
destination = "/opt/consul/agent-certs/agent.key"
perms = 0700
command = "sh -c 'date && consul reload'"
}

template {
source = "/opt/consul/templates/ca.crt.tpl"
destination = "/opt/consul/agent-certs/ca.crt"
command = "sh -c 'date && consul reload'"
}

The configuration file for the server contains the information to retrieve the CA certificate as well as the certificate/key pair for the server agent:

  • address : The address of your Vault server. If Vault runs on the same node as Consul you can use http://localhost:8200
  • token : A valid Vault ACL token with appropriate permissions

Client Configuration

/opt/consul/templates/consul_template.hcl (Minions only)

# This denotes the start of the configuration section for Vault. All values
# contained in this section pertain to Vault.
vault {
# This is the address of the Vault leader. The protocol (http(s)) portion
# of the address is required.
address = "https://server.consul.consul:8201"

# This value can also be specified via the environment variable VAULT_TOKEN.
# I am using the admin token created earlier
token = "s.MdNlboI0nff3Xpo97d1TfIxd"

unwrap_token = false

renew_token = false
}

template {
source = "/opt/consul/templates/ca.crt.tpl"
destination = "/opt/consul/agent-certs/ca.crt"
command = "sh -c 'date && consul reload'"
}

The configuration file for the server contains the information to retrieve the CA certificate only, the certificates for client agents are automatically generated from Consul when using the auto_encrypt setting:

  • address : The address of your Vault server. Here you need to use the IP / domain + opened port of your Vault master
  • token : A valid Vault ACL token with appropriate permissions

To be able to access Vault from an external service I am using a Vault-generated certificate. On my test system, that runs both Consul and Vault on a single server, I can use the Consul cert itself. For this to work I needed to add the Consul server address - which is in my case server.consul.consul - to /etc/hosts to resolve the WAN IP of my Vault server. Now I am still running into issues since the Certificate Authority is not being recognized by my Linux machine. So I have to add it to the trusted-store:

ln -s /opt/consul/agent-certs/ca.crt /usr/local/share/ca-certificates/ca.crt
update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

Start consul-template

After configuration is completed, you can start consul-template. You must provide the file with the -config parameter:

consul-template -config "/opt/consul/templates/consul_template.hcl"

THis service will output a `` every 24h - according to our Cert TTL. Meaning that the Consul service has been restarted after the certificate was updated. You can verify the cert validity by running:

openssl x509 -text -noout -in /opt/consul/agent-certs/agent.crt 

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
55:...
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = consul.consul Intermediate Authority
Validity
Not Before: Dec 5 06:34:13 2022 GMT
Not After : Dec 6 06:34:43 2022 GMT
Subject: CN = server.consul.consul

...

Nomad Automation

We can run this job with Nomad on all clients (except the master) using the raw_exec driver. To enable raw exec, the Nomad client configuration must explicitly enable the raw_exec driver in the plugin's options:

/etc/nomad.d/client.hcl

plugin "raw_exec" {
config {
enabled = true
}
}
job "consul-cert-renewal" {

type = "system"

datacenters = ["All","your","datacenters"]

group "cert-renewal" {

task "consul-template" {
driver = "raw_exec"

config {
# When running a binary that exists on the host, the path must be absolute/
command = "/usr/bin/consul-template"
args = ["-config", "/opt/consul/templates/consul_template.hcl"]
}
}
}
}