title: vault templating paths in policies results in permission denied
body: <p>I'm trying to create a policy that allows for users to access a portion of the secret hierarchy based on their usernames.  Rather than having a different policy for each user, I want to have one templated policy.  I think this should work, but I keep getting permission denied errors.  If I remove the templating and just hard-code the username in the policy path, secret retrieval works just fine, so it doesn't seem like it's any other part of the policy definition.</p>
  
  <p>This is all with Vault 1.3.1, against a dev server, but the problem first came up on a non-dev server, with GCP/GCE authentication and database secrets, so it doesn't seem to be specific to any of those things, either.</p>
  
  <p>Enable username/password authentication, and create a user that points to a new policy (to be defined later).</p>
  
  <pre><code>$ vault auth enable userpass
  Success! Enabled userpass auth method at: userpass/
  
  $ vault write auth/userpass/users/duvall policies=default,p2 password=duvall
  Success! Data written to: auth/userpass/users/duvall
  </code></pre>
  
  <p>Login as this user and take a look at the token metadata.</p>
  
  <pre><code>$ vault login -method userpass username=duvall password=duvall
  
  $ vault token lookup
  Key                 Value
  ---                 -----
  accessor            9ga3alRqZ6E3aSCEBNFWJY1X
  creation_time       1581468214
  creation_ttl        768h
  display_name        userpass-duvall
  entity_id           7513dc68-785b-d151-0efb-71315fc026dc
  expire_time         2020-03-15T00:43:34.707416501Z
  explicit_max_ttl    0s
  id                  s.YZRQ3uclh2rg2H7gh3qH84P3
  issue_time          2020-02-12T00:43:34.707423899Z
  meta                map[username:duvall]
  num_uses            0
  orphan              true
  path                auth/userpass/login/duvall
  policies            [default p2]
  renewable           true
  ttl                 767h50m35s
  type                service
  </code></pre>
  
  <p>Create the aforementioned policy with a path templated based on the metadata key <code>username</code>.</p>
  
  <pre><code>$ export VAULT_TOKEN=root
  
  $ echo 'path "secret/data/role-secrets/{{identity.entity.metadata.username}}/*" {capabilities = ["read"]}' | vault policy write p2 -
  Success! Uploaded policy: p2
  </code></pre>
  
  <p>Create a secret that matches the path in the policy.</p>
  
  <pre><code>$ vault kv put secret/role-secrets/duvall/s1 foo=bar
  Key              Value
  ---              -----
  created_time     2020-02-12T00:44:36.509412834Z
  deletion_time    n/a
  destroyed        false
  version          1
  </code></pre>
  
  <p>As the user, reading the secret results in failure.</p>
  
  <pre><code>$ export VAULT_TOKEN=s.YZRQ3uclh2rg2H7gh3qH84P3
  
  $ vault kv get secret/role-secrets/duvall/s1
  Error making API request.
  
  URL: GET http://127.0.0.1:8200/v1/sys/internal/ui/mounts/secret/role-secrets/duvall/s1
  Code: 403. Errors:
  
  * preflight capability check returned 403, please ensure client's policies grant access to path "secret/role-secrets/duvall/s1/"
  </code></pre>
  
  <p>Rewrite the policy to remove the templating.</p>
  
  <pre><code>$ export VAULT_TOKEN=root
  
  $ echo 'path "secret/data/role-secrets/duvall/*" {capabilities = ["read"]}' | vault policy write p2 -
  Success! Uploaded policy: p2
  </code></pre>
  
  <p>This time, reading the secret succeeds.</p>
  
  <pre><code>$ export VAULT_TOKEN=s.YZRQ3uclh2rg2H7gh3qH84P3
  
  $ vault kv get secret/role-secrets/duvall/s1
  ====== Metadata ======
  Key              Value
  ---              -----
  created_time     2020-02-12T00:44:36.509412834Z
  deletion_time    n/a
  destroyed        false
  version          1
  
  === Data ===
  Key    Value
  ---    -----
  foo    bar
  </code></pre>
  
  <p>I'm not sure how relevant this is, but ... adding a metadata list capability to the policy changes the read error from a "preflight capability check" to a more normal "permission denied".</p>
  
  <pre><code>$ echo 'path "secret/metadata/*" {capabilities = ["list"]}\npath "secret/data/role-secrets/{{identity.entity.metadata.username}}/*" {capabilities = ["read"]}' | VAULT_TOKEN=root vault policy write p2 -
  Success! Uploaded policy: p2
  
  $ vault kv get secret/role-secrets/duvall/s1
  Error reading secret/data/role-secrets/duvall/s1: Error making API request.
  
  URL: GET http://127.0.0.1:8200/v1/secret/data/role-secrets/duvall/s1
  Code: 403. Errors:
  
  * 1 error occurred:
          * permission denied
  </code></pre>