2021-12-15 18:59:36 +00:00
---
layout: docs
page_title: Storing Server TLS certificates in Vault
description: >-
Configuring the Consul Helm chart to use TLS certificates issued by Vault for the Consul server.
---
# Storing Server TLS certificates in Vault
To use Vault to issue Server TLS certificates the following will be needed:
2022-01-11 01:02:17 +00:00
1. Bootstrap the Vault PKI engine and bootstrap it with any configuration required for your infrastructure.
2021-12-15 18:59:36 +00:00
1. Create Vault Policies that will allow the Consul server to access the certificate issuing url.
1. Create Vault Policies that will allow the Consul components, e.g. ingress gateways, controller, to access the CA url.
1. Create Kubernetes auth roles that link these policies to the Kubernetes service accounts of the Consul components.
### Bootstrapping the PKI Engine
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
First, we need to bootstrap the Vault cluster by enabling and configuring the PKI Secrets Engine to be able to serve
TLS certificates to Consul. The process can be as simple as the following, or more complicated such as in this [example](https://learn.hashicorp.com/tutorials/consul/vault-pki-consul-secure-tls)
which also uses an intermediate signing authority.
* Enable the PKI Secrets Engine:
2022-01-12 23:05:01 +00:00
2022-01-21 19:28:38 +00:00
```shell-session
$ vault secrets enable pki
```
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
* Tune the engine to enable longer TTL:
2022-01-12 23:05:01 +00:00
2022-01-21 19:28:38 +00:00
```shell-session
$ vault secrets tune -max-lease-ttl=87600h pki
```
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
* Generate the root CA
2022-01-12 23:05:01 +00:00
2022-01-21 19:28:38 +00:00
```shell-session
$ vault write -field=certificate pki/root/generate/internal \
common_name="dc1.consul" \
ttl=87600h
```
2022-01-12 23:05:01 +00:00
2022-01-21 19:28:38 +00:00
-> **Note:** Where `common_name` is comprised of combining `global.datacenter` dot `global.domain`.
2021-12-15 18:59:36 +00:00
### Create Vault Policies for the Server TLS Certificates
Next we will create a policy that allows `["create", "update"]` access to the
[certificate issuing URL](https://www.vaultproject.io/api/secret/pki#generate-certificate) so the Consul servers can
fetch a new certificate/key pair.
2022-01-21 19:01:48 +00:00
<CodeBlockConfig filename="consul-server-policy.hcl">
```HCL
2021-12-15 18:59:36 +00:00
path "pki/issue/consul-server" {
capabilities = ["create", "update"]
}
```
2022-01-21 19:01:48 +00:00
</CodeBlockConfig>
2021-12-15 18:59:36 +00:00
```shell-session
2022-01-12 23:05:01 +00:00
$ vault policy write consul-server consul-server-policy.hcl
2021-12-15 18:59:36 +00:00
```
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
-> **Note:** The PKI secret path referenced by the above Policy will be your `server.serverCert.secretName` Helm value.
### Create Vault Policies for the CA URL
Next, we will create a policy that allows `["read"]` access to the [CA URL](https://www.vaultproject.io/api/secret/pki#read-certificate),
this is required for the Consul components to communicate with the Consul servers in order to fetch their auto-encryption certificates.
2022-01-21 19:01:48 +00:00
<CodeBlockConfig filename="ca-policy.hcl">
```HCL
2021-12-15 18:59:36 +00:00
path "pki/cert/ca" {
capabilities = ["read"]
}
```
2022-01-21 19:01:48 +00:00
</CodeBlockConfig>
2021-12-15 18:59:36 +00:00
```shell-session
2022-01-12 23:05:01 +00:00
$ vault policy write ca-policy ca-policy.hcl
2021-12-15 18:59:36 +00:00
```
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
-> **Note:** The PKI secret path referenced by the above Policy will be your `global.tls.caCert.secretName` Helm value.
### Create Vault Roles for the PKI engine, Consul servers and components
Next, a Vault role for the PKI engine will set the default certificate issuance parameters:
```shell-session
2022-01-21 19:01:48 +00:00
$ vault write pki/roles/consul-server \
allowed_domains="<Allowed-domains-string>" \
allow_subdomains=true \
allow_bare_domains=true \
allow_localhost=true \
generate_lease=true \
max_ttl="720h"
2021-12-15 18:59:36 +00:00
```
To generate the `<Allowed-domains-string>` use the following script as a template:
```shell-session
#!/bin/sh
# NAME is set to either the value from `global.name` from your Consul K8s value file, or your $HELM_RELEASE_NAME-consul
export NAME=consulk8s
# NAMESPACE is where the Consul on Kubernetes is installed
export NAMESPACE=consul
# DATACENTER is the value of `global.datacenter` from your Helm values config file
export DATACENTER=dc1
echo allowed_domains=\"$DATACENTER.consul, $NAME-server, $NAME-server.$NAMESPACE, $NAME-server.$NAMESPACE.svc\"
```
2022-01-03 22:17:55 +00:00
Prior to creating Vault auth roles for the Consul server and the Consul components, ensure that the Vault Kubernetes auth method is enabled as described in [Vault Kubernetes Auth Method](/docs/k8s/installation/vault#vault-kubernetes-auth-method).
2021-12-15 18:59:36 +00:00
2022-01-12 16:46:55 +00:00
Finally, three Kubernetes auth roles need to be created, one for the Consul servers, one for the Consul clients, and one for the Consul components.
2021-12-15 18:59:36 +00:00
2022-01-12 16:46:55 +00:00
Role for Consul servers:
2021-12-15 18:59:36 +00:00
```shell-session
2022-01-12 16:56:33 +00:00
$ vault write auth/kubernetes/role/consul-server \
2021-12-15 18:59:36 +00:00
bound_service_account_names=<Consul server service account> \
bound_service_account_namespaces=<Consul installation namespace> \
policies=consul-server \
ttl=1h
```
To find out the service account name of the Consul server,
you can run:
2022-01-12 23:05:01 +00:00
2021-12-15 18:59:36 +00:00
```shell-session
2022-01-21 19:01:48 +00:00
$ helm template --release-name ${RELEASE_NAME} --show-only templates/server-serviceaccount.yaml hashicorp/consul
2021-12-15 18:59:36 +00:00
```
-> **Note:** Should you enable other supported features such as gossip-encryption be sure to append additional policies to
2022-01-12 23:05:01 +00:00
the Kube auth role in a comma separated value e.g. `policies=consul-server,consul-gossip`
2021-12-15 18:59:36 +00:00
2022-01-12 16:46:55 +00:00
Role for Consul clients:
2022-01-12 23:05:01 +00:00
2022-01-12 16:46:55 +00:00
```shell-session
2022-01-12 16:56:53 +00:00
$ vault write auth/kubernetes/role/consul-client \
2022-01-12 16:46:55 +00:00
bound_service_account_names=<Consul client service account> \
bound_service_account_namespaces=default \
policies=ca-policy \
ttl=1h
```
2022-01-12 16:57:09 +00:00
To find out the service account name of the Consul client, use the command below.
2022-01-12 16:46:55 +00:00
```shell-session
2022-01-21 19:01:48 +00:00
$ helm template --release-name ${RELEASE_NAME} --show-only templates/client-serviceaccount.yaml hashicorp/consul
2022-01-12 16:46:55 +00:00
```
2022-01-12 16:57:14 +00:00
-> **Note:** Should you enable other supported features such as gossip-encryption, ensure you append additional policies to
2022-01-12 16:46:55 +00:00
the Kube auth role in a comma separated value e.g. `policies=ca-policy,consul-gossip`
Role for CA components:
2021-12-15 18:59:36 +00:00
```shell-session
2022-01-12 16:57:02 +00:00
$ vault write auth/kubernetes/role/consul-ca \
2021-12-15 18:59:36 +00:00
bound_service_account_names="*" \
bound_service_account_namespaces=<Consul installation namespace> \
2022-01-12 16:46:55 +00:00
policies=ca-policy \
2021-12-15 18:59:36 +00:00
ttl=1h
```
The above Vault Roles will now be your Helm values for `global.secretsBackend.vault.consulServerRole` and
2022-01-11 01:02:17 +00:00
`global.secretsBackend.vault.consulCARole` respectively.
2021-12-15 18:59:36 +00:00
## Deploying the Consul Helm chart
Now that we've configured Vault, you can configure the Consul Helm chart to
use the Server TLS certificates from Vault:
2022-01-21 19:01:48 +00:00
<CodeBlockConfig filename="values.yaml">
2021-12-15 18:59:36 +00:00
```yaml
global:
secretsBackend:
vault:
enabled: true
consulServerRole: consul-server
consulClientRole: consul-client
consulCARole: consul-ca
tls:
2022-01-12 16:46:55 +00:00
enableAutoEncrypt: true
2021-12-15 18:59:36 +00:00
enabled: true
caCert:
secretName: "pki/cert/ca"
server:
serverCert:
secretName: "pki/issue/consul-server"
extraVolumes:
2022-01-12 23:05:01 +00:00
- type: "secret"
name: <vaultCASecret>
load: "false"
2021-12-15 18:59:36 +00:00
```
2022-01-21 19:01:48 +00:00
</CodeBlockConfig>
2021-12-15 18:59:36 +00:00
The `vaultCASecret` is the Kubernetes secret that stores the CA Certificate that is used for Vault communication. To provide a CA, you first need to create a Kubernetes secret containing the CA. For example, you may create a secret with the Vault CA like so:
2022-01-21 19:01:48 +00:00
```shell-session
$ kubectl create secret generic vault-ca --from-file vault.ca=/path/to/your/vault/
2021-12-15 18:59:36 +00:00
```