Optional secrets in template stanza

I have a secret which my application consumes via environment variable, but as far as the application is concerned, it is ok if the secret is not provided and it will behave accordingly. Unfortunately, if the secret is not set in vault, my nomad job won’t start. I’m currently setting the variable via a template like this:

MY_OPTIONAL_SECRET = “{{- with secret “secret/my/optional/key” }}{{.Data.value}}{{- end}}”

I can’t find anything in the documentation about if it’s possible to tell nomad not to complain if that secret key does not exist; is there a way that I’m not finding to just use an empty string if there’s nothing in the vault?

Hi @bjornicus,

The Nomad template block uses consul-template internally to perform the rendering and API calls. The documentation on the secret function includes the following which I believe would help solve you problem:

You can also guard against empty values using if or with blocks.

Specifically as you mention the use of an empty string I believe the following code example would be suited:

{{ with secret "secret/my/optional/key"}}
{{ if .Data.value }}
MY_OPTIONAL_SECRET = "{{ .Data.value }}"
{{ else }}
MY_OPTIONAL_SECRET = ""
{{ end }}
{{ end }}

Thanks,
jrasell and the Nomad team

1 Like

Hi @jrasell,

does this also work if the key "secret/my/optional/key"doesn’t exist in Vault to begin with?

I tried this and it did not work when the secret does not exist at all. Nomad output looks like this:

|Jun 28, '21 10:34:31 -0700 |Killing |Sent interrupt. Waiting 5s before force killing|
|---|---|---|
|Jun 28, '21 10:34:31 -0700 |Killing |Template failed: vault.read(secret/my/optional/keyy|
|Jun 28, '21 10:34:27 -0700 |Alloc Unhealthy |Task not running by deadline|
|Jun 28, '21 10:29:30 -0700 |Template |Missing: vault.read(secret/my/optional/key|
|Jun 28, '21 10:29:27 -0700 |Task Setup |Building Task Directory|
|Jun 28, '21 10:29:27 -0700 |Received |Task received by client|

but thanks for the link to the function documentation I was having trouble finding that. Now that I have that I think I might be able to use the secrets function to iterate over secrets in the path of interest and if the key matches with the one I want then do stuff; if nothing matches it won’t do anything. I’ll post back here if I get that to work.

That did work (although I did not test what happens if the root path doesn’t exist):

Plus  {{ range secrets "secret/my/optional/" }}
{{ if ( eq . "key" ) }}
MY_OPTIONAL_SECRET="{{- with secret "secret/my/optional/key" }}{{.Data.value}}{{- end}}"
{{ end }}
{{ end }}
2 Likes

Wish I found these notes earlier, struggled with the same issue. We ended up implementing similar guards using:

{{ if secrets "secret/my/optional/" | contains "mykey" }}
MY_OPTIONAL_SECRET="{{ with secret "secret/my/optional/mykey" }}{{.Data.value}}{{ end}}"
{{ end }}