hashicorp/vault-guides

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.

@hayoade1 Could you check and see which kv version is mounted at secret/?

vault secrets list -detailed

Since Consul Template doesn't seem to fully support kv-v2, this guide was written for kv. So, that might be the issue.

@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.

@goffinf (Fraser), thank you so much for this info!

@yhyakuna can you confirm that the demo works for AKS? I'm still getting missing token errors :( , and I tried @goffinf 's suggestion to I'm getting errors pertaining to the consul template image consul-template:0.19.6-dev-alpine. Can you also confirm that it is correct?

@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 :(

rezda commented

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:

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 with kv v1 or kv v2? --> this demo assumes that secret is kv v1
  • @nitishnigam1989 Your error message indicates that you're trying to read from secret/testapp/config path instead of secret/myapp/config (testapp vs. myapp) --> Did you make sure to update the setup-k8s-auth.sh and consul-template-config.hcl to read from secret/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.