Consul template is not reading token in $HOME./vault
hayoade1 opened this issue · 30 comments
I tried following the example in vault-agent-k8s-demo using gke instead of minikube. Consul-template container keeps failing, and when I run "kubectl logs vault-agent-example consul-template", I see the following error in the logs:
2019/01/01 16:18:14.061809 [WARN] (view) vault.read(secret/myapp/config): vault.read(secret/myapp/config): Error making API request.
URL: GET http://xx.xxx.xx.xx:8200/v1/secret/myapp/config
Code: 400. Errors:
- missing client token (retry attempt 4 after "8s")
I'm able to see the token when I exec into the vault-agent container with the following commands
$ kubectl exec -it vault-agent-example --container vault-agent-auth sh
/# echo $(cat /home/vault/.vault-token)
Also, I'm able to successfully authenticate with the token obtain with the command above using the CLI.
The consul template container also works when I hard code a valid token in the nano example-k8s-spec.yml as an environment variable.
all files in the repo were unaltered except for the nano example-k8s-spec.yml file as I had to point the Vault url to my vault service.
@yhyakuna thanks for your comment. Its V1. See output of the command below:
secret/ kv kv_8c508b53 system system false replicated false map[version:1] key/value secret stor
@hayoade1 I was able to reproduce the error. It seems that .vault_token
is not a shared data in a GKE cluster while it was reachable from consul-template container in minikube.
To make this work, the sink
must be modified to write the token as a shared data. The current vault agent configuration (vault-agent-config.hcl
) is:
...
sink "file" {
config = {
path = "/home/vault/.vault-token"
}
}
@tdsacilowski Do you have other comment/insight on this? Is my assumption correct?
@yhyakuna and @tdsacilowski how can I configure the sink to write the token as a shared data? I do not see any info on it in the vault agent documentation.
Thank you for your assistance.
@hayoade1 Reviewing the example-k8s-spec.yml
, it is correctly setting the /home/vault
to be a shared storage between the vault-agent-auth and consul-template containers (see line 35 & 60), so there's no reason why the Consul Template cannot read the token from /home/vault/.vault_token
file. (It's not the sink
setting. The sink path needs to point to a shared storage so that other containers in the pod can read.)
So, I'm puzzled :(
...
containers:
# Vault container
- name: vault-agent-auth
image: vault
volumeMounts:
- name: vault-token
mountPath: /home/vault
...
# Consul Template container
- name: consul-template
image: hashicorp/consul-template
imagePullPolicy: Always
volumeMounts:
- name: vault-token
mountPath: /home/vault
...
The fact that this works fine with minikube, this must be a GKE issue???
I'm a kubernetes beginner myself, so need to do some more research on GKE. FYI, this article explains creating shared storage in a pod.
I tried what @hayoade1 did and set the VAULT_TOKEN environment variable in example-k8s-spec.yml
:
...
# Consul Template container
- name: consul-template
image: hashicorp/consul-template
imagePullPolicy: Alway
...
env:
- name: VAULT_TOKEN
value: $(cat /home/vault/.vault-token)
...
Now, I'm getting error performing token check
error instead of missing client token error. :(
@yhyakuna That didn't work when I tried it as well, but when I hardcoded a valid token in the the value field it worked. For example:
...
# Consul Template container
- name: consul-template
image: hashicorp/consul-template
imagePullPolicy: Alway
...
env:
- name: VAULT_TOKEN
value: <enter valid token>
...
This seems to be a GKE specific issue.
I just tested this successfully against a Kubernetes cluster running on Azure Kubernetes Services. :(
This isn't just a GKE specific issue. I am seeing exactly the same behaviour on AWS.
I know the token created by the vault container is valid because I can exec into that container and read secrets that are allowed for the role successfully.
Unfortunately I can't exec into the consul-template container since it doesn't allow that nor can I ask it cat the contents of the token file which should be mounted at /home/vault/.vault-token so I can prove that its there.
What I did try was explicitly setting the location of the token file in the HCL config ..
vault_agent_token_file = "/home/vault/.vault-token"
Interestingly that now returns a permissions error, but again its hard to debug cos I can't get into the consul-template container ...
* permission denied (retry attempt 6 after "32s")
2019/03/04 11:27:05.322460 [WARN] (view) vault.read(kv/digital/ukd_services/apikey): vault.read(kv/digital/ukd_services/apikey): Error making API request.
Ok, so using the hashicorp/consul-template:alpine image I can exec into the container and I can see that the .vault-token file is indeed mounted in /home/vault as expected.
For the purpose of testing, if I explicitly set the VAULT_TOKEN inside the consul-template container I see this ...
export VAULT_TOKEN=$(cat /home/vault/.vault-token)
2019/03/04 12:20:20.981041 [WARN] vault.token: renewer returned (maybe the lease expired)
2019/03/04 12:20:35.981163 [WARN] (view) lease expired or is not renewable (retry attempt 5 after "16s")
2019/03/04 12:20:51.995734 [WARN] vault.token: failed to renew: Error making API request.
@goffinf Thanks for the additional information! Seems like, this demo only works with Minikube and AKS cluster as-is. :(
I'll try your approach (vault_agent_token_file
) and investigate some more.
@yhyakuna (Yoko), I did get this working eventually. It appears in part to be related to the version of the image you use for consul-templates and likely the version of Vault installed.
In the end I used this image for the initContainer to get the Vault auth token and write it to the shared volume (vault:1.0.3). This is the HashiCorp Vault Agent which I configured to exit as soon as the token was writing to the sink.
For consul-template I used consul-template:0.19.6-dev-alpine (you can exec into the alpine ones) and I mounted vault-token at the path /home/consul-template rather than /home/vault (this seemed critical). After that everything just worked as expected.
I did try the latest consul-template images (0.20.0) but they just continuously return ‘missing client token’ or 403 unauthorised not matter what I tried so in the end I gave up since I do actually have a working solution now. I wondered whether it might have to do with whether v1 or v2 is set up for the Vault secrets backend, but that’s just a wild guess.
HTHs
Fraser.
@hayoade1 Unlike GKE, this demo worked smoothly against AKS cluster for me. I had to demo this on AKS a few weeks ago, so I'm very sure of that.
I've been so busy with other work that I haven't had a chance to try the consul-template:0.19.6-dev-alpine image, yet. Hope to find the time later this week.
@yhyakuna Looks like the consul-template image was recently updated. I will try again. wish me luck :)
@hayoade1 I think the error I was seeing when using the latest consul-template images (0.20.x) are likely because of the version of Vault that is running and support for either the v1 and/or v2 APIs. I don’t have any control over that in my situation since Vault is provided as a platform level service to me by our CloudOps team. If you have it within your gift to use the latest version of Vault I would definitely give the latest consul-templates image a go.
HtH
Fraser.
I'm having the same issue and I can confirm that in my case on minikube in it works only with consul-template:0.19.6-dev-alpine image. Both 0.19.5 and 0.20 don't work :(
If you're using vault kv-v2 you need to update the .Data.data format in the consul-template-config.hcl file
consul-template loads the vault token using the consul-template config (see: hashicorp/consul-template@72366c2)
The reason you can't exec into the consul-template image is because it's a scratch container (see: https://github.com/hashicorp/consul-template/blob/master/docker/scratch/Dockerfile)
Haven't tested on AKS or GKE but this should work regardless.
This was working for me perfectly before, but now I'm seeing the same issue (missing client token
).
I tried consul-template:0.19.6-dev-alpine
image as some of you suggested. When I invoked consul-template -template="<test.tpl>:<test.output>" -once
command inside the consul-template container, it worked fine which means that Cosul Template used the ~/.vault-token
as it should. So, the issue seems to be due to a race condition (consul-template executed before token was written)?
The approach @goffinf pointed out with initContainers
worked for me (tested with Minikube as well as AKS). So, I've updated the demo files.
The learn will be updated shortly.
@hayoade1 I just tested successfully against GKE cluster. So, I'm pretty convinced that this was a race condition issue. I'm now closing this, but if the solution doesn't work for you, feel free to re-open or create another issue report.
Thank you so much for bringing this to our attention!
yeah, this got broken in 0.20.0; hashicorp/consul-template#1182 (comment)
I am also getting the same error . Seems like consul template container is not able to read "/home/vault/.vault-token" . Is there any workaround available ?
Code: 403. Errors:
- permission denied (retry attempt 1 after "1s")
2019/04/25 12:08:20.470880 [WARN] (view) vault.read(secret/testapp/config): vault.read(secret/testapp/config): Error making API request.
URL: GET https://example.default.svc:8200/v1/sys/internal/ui/mounts/secret/testapp/config
yeah, go back to an older version of consul template (registry.hub.docker.com/sethvargo/consul-template:0.19.6.dev-alpine is the one I am using, for example).
@nitishnigam1989 and @jurgenweber I just tested with hashicorp/consul-template:0.20.0-alpine
but this demo worked fine. So, I have a couple of questions:
- Is your
secret
path is enabled withkv v1
orkv v2
? --> this demo assumes thatsecret
iskv v1
- @nitishnigam1989 Your error message indicates that you're trying to read from
secret/testapp/config
path instead ofsecret/myapp/config
(testapp
vs.myapp
) --> Did you make sure to update thesetup-k8s-auth.sh
andconsul-template-config.hcl
to read fromsecret/testapp/config
?
If using kv-v2
at secret
, please update the /configs-k8s/consul-template-config.hcl
as follow:
...
<p>Some secrets:</p>
{{- with secret "secret/data/myapp/config?version=1" }}
<ul>
<li><pre>username: {{ .Data.data.username }}</pre></li>
<li><pre>password: {{ .Data.data.password }}</pre></li>
</ul>
{{ end }}
</body>
</html>
EOH
}
@yhyakuna For my POC purpose, i was using secret path as secret/testapp/config [(not myapp)] so I did changed all references .Also changed consul-template-config.hcl to read from /secret/testapp/config.
I will again try with hashicorp/consul-template:0.20.0-alpine
and see if it works. Earlier I was using hashicorp/consul-template:alpine
image.
@jurgenweber Thanks a lot, Yes ,using "registry.hub.docker.com/sethvargo/consul-template:0.19.5.dev-alpine" image for consul-template worked well for me :) .
Hmmm... I was able to successfully test this demo with hashicorp/consul-template:alpine
as well, so I'm puzzled. :(
I have created a PR to resolve this in the later versions of consul-template; hashicorp/consul-template#1228
May not be the same problem, but I recently hit a problem where the owner + permissions of /vault/.vault-token made it readable only by root, and the consul-template container ran as uid 100, and therefore failed to read it.