Policy to read metadata only

I’m trying to write a policy to grant access to the metadata of a secret but not the actual data with a kv2 engine.

A read metadata outputs this policy:

$ vault kv metadata get --output-policy secret-engine/apath/FOO

path "secret-engine/metadata/apath/FOO" {
  capabilities = ["read"]
}

Which I generalize a bit to:

path "secret-engine/metadata/apath/*" {
  capabilities = ["read"]
}

When I setup that policy, and access the api, I get a permissions error unless I use or add a policy as something like:

path "secret-engine/*" {
  capabilities = ["read"]
}

Is what I’m trying to do not possible, or do I have an config error in my approach?

I see nothing wrong with the general approach, but since you haven’t shared the exact details of the API calls you are trying to make, or the exact details of the errors returned, it is difficult to be helpful.

Sorry if the detail was a little sparse, I was trying to get the problem reduced down to the essentials.

The literal endpoint accessed is basically a GET on “https://127.0.0.1:8200/v1/secret-engine/metadata/apath/FOO

When I access the kv2 read metadata api endpoint in my setup, with the only difference being in the policy mentioned above, the read either succeeds with the general policy, or fails with a 403 error with the “metadata” only policy.

With a little more testing, it seems like the basics of my problem were too boiled down. If multiple engines are involved, the policy fails across mounts:

path "engines/+/metadata/apath/*" {
  capabilities = ["read"]
}

doesn’t work, while works fine

path "engines/engine1/metadata/apath/*" {
  capabilities = ["read"]
}

Ah, that sounds familiar. The logic that Vault uses to determine which is the “most specific” policy path rule is weird. I actually think there’s a case for calling it defective. For example, a rule for any of these:

  • engines/*
  • engines/engine1/*
  • engines/engine1/metadata/*

would be considered “more specific” than the rule for engines/+/metadata/apath/* and would override it.

I think in my case it might be that the “+” specification seems to have some unexpected (maybe buggy?) interaction at the mount vs path split. Maybe I’ll file it as an issue.