terraform-provider-vault: Vault provider is unable to access data with a non-root token

This issue was originally opened by @mperriere as hashicorp/terraform#16457. It was migrated here as a result of the provider split. The original body of the issue is below.


Hi there,

Terraform Version

0.10.6

Terraform Configuration Files

cat main.tf
provider "vault" {
  address = "http://${var.vault_host}:${var.vault_port}"
  skip_tls_verify = true
  token = "dc985ea7-57eb-77b5-17c9-ae86fe019c82"
}

data "vault_generic_secret" "key" {
  path = "secret/dev/onenext/db_user01"
}

output pwd {
 value = "${data.vault_generic_secret.key.data["pwd"]}"
}

cat variable.tf
variable vault_host {
 #default="consuldev.pipeline.aws"
 default="10.196.14.160"
}
variable vault_port {
 default="8200"
}
variable env {
 default="dev"
}
variable project_name {
 default="onenext"
}

Debug Output

terraform-0.10.6 apply data.external.read_token: Refreshing state… data.external.fetch_token: Refreshing state… Error refreshing state: 1 error(s) occurred:

  • provider.vault: failed to create limited child token: Error making API request.

URL: POST http://10.196.14.160:8200/v1/auth/token/create Code: 403. Errors:

  • permission denied

Expected Behavior

I’m trying to create a policy based for every project and env: we need a token for every project, in every environnment (DEV, PREP, PROD). Then i attach a token to it, write a secret inside the path defined in the policy, and finally i’m trying to read it from Terraform. The token should allow read access to the credentials, but it does not.

the rules are defined in a ansible playbook (outside terraform scope) path “secret/{{env}}/{{project_name}}/*” { capabilities = [“create”, “read”, “update”, “delete”, “list”] } path “secret/{{env}}/{{project_name}}” { capabilities = [“list”] } path “auth/token/lookup-self” { capabilities = [“read”] }

Next step, i’m creating a token attached to that policy: (sorry, ansible code too):

  • hashivault_token_create: display_name: “{{project_name}}-{{env}}” policies: [“{{project_name}}-{{env}}”] renewable: True token: “{{root_token}}”

This token is available, and can be queried on the Vault server: VAULT_TOKEN=dc985ea7-57eb-77b5-17c9-ae86fe019c82 vault token-lookup --address=http://127.0.0.1:8200 Key Value


accessor ec4ccd86-c6b9-b0e5-b337-5504ced231cd creation_time 1508927130 creation_ttl 2764800 display_name token-onenext-dev explicit_max_ttl 0 id dc985ea7-57eb-77b5-17c9-ae86fe019c82 meta <nil> num_uses 0 orphan false path auth/token/create policies [default onenext-dev] renewable true ttl 2761029

Next step. i’m writing a secret in the policy path. No issue there.

Now i’m trying to read it from the vault cli: this is ok, i can read the secret. This proves that the secret, policy and token are correctly defined:

VAULT_TOKEN=dc985ea7-57eb-77b5-17c9-ae86fe019c82 vault read --address=http://127.0.0.1:8200/ secret/dev/onenext/db_user01 Key Value


refresh_interval 768h0m0s pwd tai.s0dohM5r

Now i’m trying to do the same thing with terraform. I get that error:

PS: if i switch back to the root token in the provider vault definition, i can access to the secret.

It seems that terraform is trying to create a temporary token instead of using the one newly created to just read the secret key with the provided token.

Perhaps i did not understand the documentation? I did not find full usage examples on the internet, i don’t know what’s wrong here.

Steps to Reproduce

Please list the full steps required to reproduce the issue, for example: 2. terraform apply

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 20 (3 by maintainers)

Most upvoted comments

I wonder if creating a child token could be a configurable option, defaulting to current behavior.

Right now a child token is required to be created. I would love to see an option for the provider to allow disabling that requirement and just use the token that was provided.

I get that with the correct policy setup in place this should work fine. However, sometimes we are not in control of the policies. In that case it’s a bit frustrating when trying to provide a token that has perms necessary to do reads/writes but fails on trying to create a child token.

If people are open to this idea I don’t mind PR’ing it.

#775 was merged - please see PR for details.

When an upcoming release includes that change, you will be able to configure the vault provider to skip creation of the child token for situations like these where you are using Terraform with a less-privileged token that cannot create a child token.

provider "vault" {
  skip_child_token = true
}

I solved this by granting the update capability on the auth/token/create path to users that need to run terraform commands. It seems safer then digging out the root token in terms of security, accidents and audibility.

But I’m left wondering: Does create new security hole?

It also occurs to me that that ephemeral data like auth tokens are not really part of the terraform state. It’s different each time. The vault address is part of the state, changing it changes the outcome, and, unfortunately, the secrets fetched from vault are normally part of the state, but the auth token is not logically. (Even if it is treated as such in practice)

I think that terraform needs a way of dealing with such data and lot of the problems go away.

I solved this by granting the update capability on the auth/token/create path to users that need to run terraform commands. It seems safer then digging out the root token in terms of security, accidents and audibility.

But I’m left wondering: Does create new security hole?

It also occurs to me that that ephemeral data like auth tokens are not really part of the terraform state. It’s different each time. The vault address is part of the state, changing it changes the outcome, and, unfortunately, the secrets fetched from vault are normally part of the state, but the auth token is not logically. (Even if it is treated as such in practice)

I think that terraform needs a way of dealing with such data and lot of the problems go away.

That fixed the issue. The default policy that comes with terraform does not allow for the creation of a temp token. Therefore i create a copy of the default and added the policy of:

# Allow tokens to look up their own properties
path "auth/token/create" {
    capabilities = ["update"]
}