OSS Vault KVv2 and Policies

Hi,

I could not find a recent answer to this question, so i ask it again as things are moving fast here.

I have 2 secrets stores mounted in a KV
kv/service1

  • SVC1_KEY=value
  • RANDOM1_KEY=value
    kv/service2
  • SVC2_KEY=value
  • RANDOM2_KEY=value

I wonder if it is possible to set a policies that only allow reading of a specific key and only that one ?

I tried some policies like :

path "kv/data/service2/SVC2_KEY" {
  capabilities = ["read"]
}

If it is not possible, it would be a nice addition.

I usually bind a secret store to an application (this is all the secret the app need) but sometimes you also need to access a secret from another service. In this case you have 2 choices :

  • Allow the service to read all the secrets of the other service (not that good)
  • Extract that specific secret, put it on a “common” KV and rewrite our application logic to workaround this splitting
  • Or duplicate the secret accross different KV (which can be annoying if you want to rotate it)

How would you achieve this ?

I’m not sure what you mean by having 2 secrets stores mounted in a KV. Do you mean that “kv/service1” and “kv/service2” are separate secret mounts of the KVv2 type?

Because from your policies it looks like you have a single KVv2 store, with multiple folders - and that’s what you should use, in this case :wink:

Anyway. Also, yes, policies can be scoped to a single path (or item), or multiples. An example: our setup has a single KVv2 store mounted as “secret” - each application we run has it’s own slice of it, for instance:

secret/application/shinyapp-1
`- token
`- othertoken

secret/application/shinyapp-2
`- somesecret
`- anothersecret

Which means we have, for instance, secret/application/shinyapp-1/token and secret/application/shinyapp-2/anothersecret

Anyhow. The policies associated with that are also per-app; so shinyapp-2’s policy is simply:

path "secret/data/application/shinyapp-2/*"
  capabilities = ["read", "write"]
}

Which grants it the right to read and write anything under /secret/application/shinyapp-2/.

Now shinyapp-1 has a slightly different policy since (for whatever reason) it needs to be able to read the “anothersecret” token from shinappy-2 because shinyapp-2 can rotate that token any time it wants.

path "secret/data/application/shinyapp-1/*"
  capabilities = ["read", "write"]
}
path "secret/data/application/shinyapp-2/anothersecret"
  capabilities = ["read"]
}

This allows it to read the secret that “belongs” (by convention) to shinyapp-2.

We also store “common” credentials (such as API tokens for external services) under a path like secret/common/api/supercloudprovider/token - and we define a policy with read access, since it’s entirely possible for you to obtain a Vault token with multiple policies attached.

So, your question “how would I achieve this”: as above. Your policies are basically what restricts an app from acting on a given path; Vault KV doesn’t care, and your applications realistically just fetch a path from Vault, and as long as the policy allows you to do it then it’s all good.

Hope this helps :wink:

Yes, i have one KV with multiple path in it.

Policies to restrict access to specific path works properly. I want to restrict more (at the key level)

For example:

vault kv get -format=json -mount=kv service2

"data": {
      "SVC2_KEY": "value",
      "RANDOM2_KEY": "value"
    },

My goal is to have a policy to allow access to SVC_KEY1.

path "kv/data/service1" {
  capabilities = ["read"]
}
# This allow reading all values within the store.
# But this one do not work
path "kv/data/service2/SVC2_KEY" {
  capabilities = ["read"]
}
path "/kv/data/service1/SVC1_key" {
    capabilities = ["read"]
}

Should do the trick. If that doesn’t work,are you sure you’re using KV version 2? Because if it’s not, you need to take the data part out of the path.

Im using KVv2 and no it doesn’t work. Looks like policies are limited to path and are not working on data field.

Ah! You are right, I overlooked that part - so service2 and service1 are the actual paths with SVC2_KEY/RANDOM2_KEY for instance as values. And yes, you can’t policy down to individual data items inside a path.

We solved that problem by just having something like this:

vault kv get -format=json -mount=secret application/helloworld/token

"data": {
    "value": "supersecrettokengoeshere"
}

So that can have a policy attached to allow reading of /secret/data/application/helloworld/token - it’s a bit more work (but you can do a policy for secret/data/application/helloworld/* to allow for reading all items under that path so that makes some things easier).

As far as designing the structure goes, always treat it like you would a filesystem on disk, you can grant people access to files and folders, but not explicitly to the content in the files.

1 Like