Vault Agent 1.4.2
vault-k8s annotations
annotations = {
"vault.hashicorp.com/agent-inject" = true
"vault.hashicorp.com/role" = "api-deployment"
"vault.hashicorp.com/agent-inject-secret-minitoken-mac-secret" = "secret/data/minitoken/mac_secret"
"vault.hashicorp.com/agent-inject-template-minitoken-mac-secret" = <<EOF
{{- with secret "secret/metadata/minitoken/mac_secret" -}}
{{ . }}
{{- end }}
EOF
}
Generated Vault Agent config
{
"auto_auth": {
"method": {
"type": "kubernetes",
"mount_path": "auth/kubernetes",
"config": {
"role": "api-deployment"
}
},
"sink": [
{
"type": "file",
"config": {
"path": "/home/vault/.vault-token"
}
}
]
},
"exit_after_auth": false,
"pid_file": "/home/vault/.pid",
"vault": {
"address": "<omitted>"
},
"template": [
{
"destination": "/vault/secrets/minitoken-mac-secret",
"contents": "{{- with secret \"secret/metadata/minitoken/mac_secret\" -}}\n{{ . }}\n{{- end }}\n",
"left_delimiter": "{{",
"right_delimiter": "}}"
}
]
}
Consul Template
{{- with secret "secret/metadata/minitoken/mac_secret" -}}
{{ . }}
{{- end }}
Sanity Check Template that works
{{- range secrets "secret/metadata/minitoken/" -}}
Found secret: {{ . }}
{{- end }}
Output of sanity check template
Found secret: mac_secret
Vault Agent logs
2020/07/21 23:44:26.312073 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 2 after "500ms")
2020/07/21 23:44:27.083082 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 3 after "1s")
2020/07/21 23:44:28.336913 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 4 after "2s")
2020/07/21 23:44:30.612501 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 5 after "4s")
2020/07/21 23:44:34.917585 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 6 after "8s")
2020/07/21 23:44:43.190042 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 7 after "16s")
2020/07/21 23:44:59.461971 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 8 after "32s")
2020/07/21 23:45:31.791564 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 9 after "1m0s")
2020/07/21 23:46:32.121237 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 10 after "1m0s")
2020/07/21 23:47:32.420788 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 11 after "1m0s")
2020/07/21 23:48:32.768307 [WARN] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (retry attempt 12 after "1m0s")
2020/07/21 23:49:33.023411 [ERR] (view) vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret (exceeded maximum retries)
2020/07/21 23:49:33.023617 [ERR] (runner) watcher reported error: vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret
2020-07-21T23:49:33.023Z [ERROR] template.server: template server error: error="vault.read(secret/metadata/minitoken/mac_secret): no secret exists at secret/data/metadata/minitoken/mac_secret"
2020-07-21T23:49:33.023Z [INFO] template.server: template server stopped
The secret call should be able to read Vault KV v2 metadata directly from the secret/metadata/<path> value.
It was reported that no secret exists when asking for metadata.
This is probably due to vault.read() injecting path segment /data: secret/data/metadata/<path>.
A sanity check listing the secrets in secret/metadata shows that the secret that we read exists (see Configuration section).
secret/metadata endpoint referring to secret via template.I have a suspicion the error occurs in addPrefixToVKVPath. @findkim @kyhavlov
imo, the code should check specifically for existing /metadata or /data prefixes, and add in the /data prefix when neither is present.
I found a workaround. (and probably another bug?)
We can exploit that evaluating whether to add prefix or not is done before cleaning the path.
This Consul template fetches metadata from Vault KV v2.
{{- with secret "secret/data/../metadata/minitoken/mac_secret" -}}
{{ . }}
{{- end }}
addPrefixToVKVPath decides to not alter the path because it has the /data prefix.
Then, at some point the request path gets cleaned to secret/metadata/minitoken/mac_secret.
The metadata endpoint is useful for fetching available secrets versions. It allows logic like iterating through a list of versions:
{{- with secret "secret/data/../metadata/minitoken/mac_secret" -}}
{{- range $key, $value := .Data.versions -}}
{{- with secret (printf "secret/minitoken/mac_secret?version=%s" $key) -}}
{{ . }}
{{- end }}
{{- end }}
{{- end }}
The exact template doesn't work though (vault.read(secret/minitoken/mac_secret.v1): no secret exists), but this is probably a separate issue.
Hey @terorie, thanks for the report.
I agree with your assessment that the addPrefixToVKVPath not handling metadata is the issue. Looks like this stopped working with changes to fix issues where it mistakenly saw random 'foodata' entries as matching 'data' and not fixing their path. This broke 'metadata' as it was a good case of that bug, but there was no test asserting that.
The fix needs to include both a way to recognize 'metadata' as a valid path and to be sure to add a test for it.
Great find @terorie, this was an overlook on my part and not considering the vault usage of metadata.
After digging into this a bit more, I noticed reading metadata was also not working in v0.24.1 due to the prepended /data/metadata/ path. It leads me to think metadata has not been supported for KVv2. Thanks for shedding light to this!
Thank you all so much for looking into this! vault-k8s has helped with automating secrets management on our Kubernetes clusters immensely. The quick developer response is the cherry on top.
@findkim I'm going to test the changes included in #1399 and report my findings. I'll also test out iterating versioned secrets with this using the aforementioned template. I might have another small bug there, but this is probably just wrong configuration on my end.
I could confirm that #1399 fixes iterating over KVv2 secrets versions.
Vault data:
```shell script
vault kv put secret/test_secret abc=def
vault kv get -version 1 secret/test_secret
vault kv put secret/test_secret abc=def
vault kv get -version 2 secret/test_secret
Consul Template config:
```hcl
vault {
address = "http://localhost:8200"
token = "token"
}
template {
destination = "./version-1-test.txt"
contents = <<EOF
{{- with secret "secret/data/test_secret?version=1" -}}
{{ .Data }}
{{- end }}
EOF
}
template {
destination = "./version-iteration-test.txt"
contents = <<EOF
{{- with secret "secret/metadata/test_secret" -}}
{{- range $key, $value := .Data.versions -}}
{{- with secret (printf "secret/data/test_secret?version=%s" $key) }}
{{ .Data }}
{{- end }}
{{- end }}
{{- end }}
EOF
}
Output: version-iteration-test.txt
map[data:map[abc:def] metadata:map[created_time:2020-07-27T00:02:46.006401578Z deletion_time: destroyed:false version:1]]
map[data:map[abc:def] metadata:map[created_time:2020-07-27T00:07:05.084323392Z deletion_time: destroyed:false version:2]]
Output: version-1-test.txt
map[data:map[abc:def] metadata:map[created_time:2020-07-27T00:02:46.006401578Z deletion_time: destroyed:false version:1]]
Glad to hear that #1399 works for you @terorie, and appreciate the testing on your end! It helped expedite the release for the fix v0.25.1 馃帀
Most helpful comment
Great find @terorie, this was an overlook on my part and not considering the vault usage of
metadata.