# Best practice for organizing a service's vault kv secrets

**URL:** <https://discuss.hashicorp.com/t/best-practice-for-organizing-a-services-vault-kv-secrets/64530>\
**Category:** Vault\
**Tags:** kv\
**Created:** [April 3, 2024, 7:36pm UTC](https://discuss.hashicorp.com/t/best-practice-for-organizing-a-services-vault-kv-secrets/64530 "2024-04-03T19:36:02Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jspencer](https://avatars.discourse-cdn.com/v4/letter/j/74df32/32.png) [@jspencer](https://discuss.hashicorp.com/u/jspencer)\
**Post date:** [April 3, 2024, 7:36pm UTC](https://discuss.hashicorp.com/t/best-practice-for-organizing-a-services-vault-kv-secrets/64530/1 "2024-04-03T19:36:02Z")

</div>

Hello! How do folks typically organize a service/application’s secrets in Vault KV? e.g. if we have a service named `app1`, you could put all the secrets for that service under a single item in the path `app1`, such that `vault kv get -format=json -mount=secret app1` returns this json blob (edited):

```auto
...
  "data": {
    "data": {
      "secret-key-1": "value1",
      "secret-key-2": "value2"
    },
...

```

Or we could put each secret as it’s own item under the path `app1/<item_name>`, so we could list all keys with `vault kv list -format=json -mount=secret app1` and then get a specific key with `vault kv get -format=json -mount=secret app1/secret-key-1`.

I think the later option of one secret per item is probably the safer route, because if using a single item for all secrets, it’d be too easy for an engineer to accidentally wipe out the whole json blob by using the `put` command instead of the `patch` command. We could protect against that via a policy, but when deploying a new service, the engineer needs access to the `put` command to create the initial vault item for that service.

A downside of using one item per secret is that the `key` becomes redundant, e.g. the path already has the key in it `app1/secret-key-1` and so when writing to that path, what do you put for the key? Maybe just `value` e.g. `vault kv write -format=json -mount=secret app1/secret-key-1 value=value1`. This feels kind of clunky though.

What have you typically seen done? One vault item per service with all secrets as key/value pairs in that item, or many vault items per service, with the secret being the value of a single key/value pair per item.

---

<div class="post-metadata">

**Author:** ![Matt\_Finnigan](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/matt_finnigan/32/29221_2.png) [@Matt\_Finnigan](https://discuss.hashicorp.com/u/Matt_Finnigan)\
**Post date:** [April 18, 2024, 4:10pm UTC](https://discuss.hashicorp.com/t/best-practice-for-organizing-a-services-vault-kv-secrets/64530/2 "2024-04-18T16:10:42Z")

</div>

This is a case of “figure out what works for you/your devs”, but there’s a couple of things you’re not taking into account that are important.

ACLs and metadata. You can set an ACL on a secret, not on a kv pair. Same with metadata. So, you want the kv pairs within a secret to be related enough that they can share security and any relevant metadata.

Also, with kv-v2, you have versioned secrets, so an accidental stomp shouldn’t be the end of the world, the data isn’t lost. But it does help make the point that kv pairs within a secret are within the blast radius of a whoopsie like that.

If you’re hung up on what string to put into the key if the secret name is already telling you exactly what’s in there, that’s not actually a problem. Call it whatever you (or your devs/customers) want to.

/edit- Hah, I think I answered this question similarly on Reddit, but having the answer here as well is useful for anyone else who finds this question on this forum.

---

<div class="post-metadata">

**Author:** ![jspencer](https://avatars.discourse-cdn.com/v4/letter/j/74df32/32.png) [@jspencer](https://discuss.hashicorp.com/u/jspencer)\
**Post date:** [April 18, 2024, 7:05pm UTC](https://discuss.hashicorp.com/t/best-practice-for-organizing-a-services-vault-kv-secrets/64530/3 "2024-04-18T19:05:57Z")

</div>

Thanks for the input Matt! Both here and on reddit 😁 That all makes sense. I think we will use the approach of one vault item per secret. So the json blob for each item will just have one secret (key/value pair). re: the key of the secret - you mentioned it doesn’t really matter (up to devs), which is true, but for us I think standardizing the key is helpful. We will be looping through all secrets from a service path and loading them in a nomad job file template stanza (via consul-template). Having a consistent key name to access each secret on will simplify the configuration and make it easier for our devs to copy/paste for onboarding services to vault and deploying new services. E.g. we loop through all secrets with `{{ range secrets "secret/service/test-service" }}` and then access the secret content with `{{ .Data.data.value }}`, assuming that `value` is the name of the sole key for each secret. I think you and others have already confirmed this but there isn’t a way with ACL policies to force a user to only be able to set the string `value` as the key for a secret, right? Or maybe ACL policy to prevent users from writing a secret with more than key/value pair? Thinking out loud here, thanks for any and all advice 🙏
