Path capability includes create, but kv put is denied?!


Could use some help with a weird policy issue.

So, I have cert auth enabled, with an attached policy “cert_policy”:

path "myca/machine/{{}}/*" {
  capabilities = ["create", "update"]

auth_cert_2e0d6a5d is the auth accessor as per vault auth list.

KV engine was mounted myca/machine: vault secrets enable -version=2 -path=myca/machine kv

Then as a client I auth to Vault using a cert from the CA, where the CN is the machine full hostname. For the example, the machine hostname is my.fqdn.

vault token capabilities myca/machine/my.fqdn/ shows, as expected, “create, update”.

But when I try to insert in the KV:

vault kv put myca/machine/my.fqdn/whatever foo=bar
Error writing data to myca/machine/data/my.fqdn/whatever: Error making API request.

URL: PUT https://vault:8200/v1/myca/machine/data/my.fqdn/whatever
Code: 403. Errors:

* 1 error occurred:
	* permission denied

I’m puzzled. Any hint about I’m doing wrong here? Thanks!

Update, I managed to make it work, I modified the policy path to add “/data/” after the mount point, like so:

path "myca/machine/data/{{}}/*" {
  capabilities = ["create", "update"]

So I had completely missed that for kv-v2 you need the /data/ after the mount point, in the policy and also when calling vault token capabilities.

However, vault kv put cannot have the /data/ in it, I guess it’s implicit. I find this very, very unintuitive.

1 Like

As you say for k/v version 2 the API is different to version 1 and as a result there isn’t a direct mapping between the secret’s path and the API call - to allow for versioning you now have additional prefixes such as /data/ and /undelete/, etc. (see KV - Secrets Engines - HTTP API | Vault by HashiCorp).

If you use the vault read or vault write commands via the CLI you would have to include those extra prefixes as needed, so to make the common cases easier the CLI also includes the convenience commands like vault kv get. Behind the scenes they are converting the supplied secret path into the correct API request, as well as handling the returned data structure.

As the permissions functionality only operates on actual API paths (which is needed so you can control permissions for get current version/previous version/delete version separately) you need to remember to include the correct prefixes as per the API calls.


That makes sense, thank you @stuart-c !

1 Like