Consul Template to write private key and cert back into Vault

Hello all,

I am interested in using Consul Template to create TLS certs on local servers but store the private key and cert back into Vault KV store.

I have the local file creation part working and private ke and cert files are generated and updated on the local host running CT.

{{- /* mylocal-cert.tpl */ -}}
{{ with secret "pki_int_ca/issue/server_tls_role" "common_name=mywebsite.domain.net"     "ttl=5m" }}
{{ .Data.certificate }}
{{ .Data.issuing_ca }}{{ end }}

But how can I write that back into Vault KV using the data I just obtained? Not sure of formatting or how I could use the output / variables from the secret and store back into Vault…

Forgive the rudimentary example, but something to the effect of:

{{- /* write-cert.tpl */ -}}
{{ secret "/certs/<domain-name>/" "value=<contents of certificate>" }}

Thanks in advance.

1 Like

consul-template is (IMO) not a good tool for working with PKI certificates because it doesn’t understand how to check whether a certificate is close to expiry, and only get a new one if needed.

I can just about imagine possible nested invocations of secret managing to satisfy the letter of your stated requirement, but it’ll be really ugly.

Could you expand upon why you want to write the certificate and key back to KV storage? Knowing a bit more context would make it possible to give a more confident suggestion as to whether to continue with consul-template versus switching to a different solution.

For the record, this works:

{{ with secret "pki/issue/example" "common_name=example.local" -}}
{{ $_ := secret "kv-v2/data/certificate" (print "certificate=" .Data.certificate) (print "private_key=" .Data.private_key) -}}
{{ .Data.private_key }}
{{ .Data.certificate }}
{{ end }}

but I have my doubts about how useful it actually is.

1 Like

I can not thank you enough for your prompt and thoughtful reply.

In general I am trying to automate TLS Certificate Lifecycle Management and currently reviewing several CLM tools which all feature HCP Vault plugins. There will be cases where we would issue a a single public TLS cert with 3rd party CA using Vault and then reuse that same cert across multiple load balancers and backend servers, such as for wildcard certs or other websites.

The thought is to generate the cert once and store back in Vault so that multiple backend webservers could make use of the cert, if necessary.

I do have the local cert file creation / distribution working with a test ttl of 5m and it is updating as expected with no problems. We are using CT for mTLS in other applications and it seems to work well in that use case.

I would appreciate any further insights, and thanks again for the reply.

The problem with the approach above, is that if you run that CT template on multiple hosts, or even just restart CT on a single host, each execution is going to generate a new certificate and overwrite the KV content.

I think the level of complexity to implement “did something already generate and store this certificate, if so re-use it, if not generate it and store it” is going to be too complex to be viable in CT, and even if you get it working, you still don’t have sensibly working renewals.

CT did recently add a new pkiCert function that claimed to address the renewals, but it appears it was implemented with a poor understanding of the requirements, as it seems to not provide any way to get the private key, or CA chain, making it fairly useless!

Personally, my belief is that for the case of certificate management, a simple Python (or insert your preferred general-purpose scripting language here) script is going to be more flexible and able to do a better job than CT.

1 Like

I agree 100%. I have a separate Terraform configuration that I am experimenting with that does request a cert and store back into KV, where we can then reuse that cert across several hosts if desired. I was looking to do the same using CT as another workflow pattern, but realize now that may not be the most practical approach. On the other hand, it does seem workable for a single cert per server.

Thanks much for your time and input. The code example you provided is extremely helpful and I’m sure will benefit others.