Overview
This article will describe how to make the kv
secrets engine(KV Version 1) easy to navigate on the UI for users with limited read/write capabilities.
Scenario
Users usually have read/write capability for only a subset of the paths in the kv
Version 1 secrets engine. For example, a user from "Group A" may only have access to read/write/list secrets under the path secret/dev/group_a/*
, like this:
path "secret/dev/group_a/*" {
"capabilities" = ["read", "create", "update", "list"]
}
path "sys/mounts" {
"capabilities" = [ "read" ]
}
On the UI, the user is presented with a "Not Authorized"/"Permission denied" page when clicking into the default kv
secrets engine at secret/
($VAULT_ADDR/ui/vault/secrets/secret/list). This is because they don't have any access to the secret
path. With access only to the path secret/dev/group_a/*
, the user cannot click into this tab to navigate to their delegated path, since the UI uses the API under the hood.
Solutions
There are a number of options to give a user access to easily navigate the UI to their designated path in the kv
secrets engine while maintaining limited privileges.
Option 1: Add List Capability for secret/*
The easiest and most user-friendly is to give the user list
capability to secret/*
. This will allow them to click through the paths leading to their designated path in the UI. While they'll be able to see the keys (listed) they will not be able to read the secret values associated with those keys unless they're given read
capability on the path. The policy above would be altered to look like this:
path "secret/dev/group_a/*" {
"capabilities" = ["read", "create", "update", "list"]
}
path "secret/*" {
"capabilities" = ["list"]
}
path "sys/mounts" {
"capabilities" = [ "read" ]
}
Option 2: Use Specific URL
If you desire to keep the unreadable keys hidden from the user as well, you can keep the original policy and the user can simply put the path in the URL in this format:
$VAULT_ADDR/ui/vault/secrets/secret/list/dev/group_a/
Option 3: Mount Multiple kv
Secrets Engines at Different Paths
Another option is to mount multiple kv
secrets engines at distinct paths and give each group of users access to read/write/list all secrets at their group's path. For example:
$ vault secrets enable -path=group_a_kv kv
Success! Enabled the kv secrets engine at: group_a_kv/
$ vault secrets enable -path=group_b_kv kv
Success! Enabled the kv secrets engine at: group_b_kv/
$ vault secrets list
Path Type Description
---- ---- -----------
cubbyhole/ cubbyhole per-token private secret storage
group_a_kv/ kv n/a
group_b_kv/ kv n/a
identity/ identity identity store
secret/ kv key/value secret storage
sys/ system system endpoints used for control, policy and debugging
At this point, you could tailor the policies for Group A members only to their instantiation of the kv backend:
path "group_a_kv/*" {
"capabilities" = ["read", "create", "update", "list"]
}
path "sys/mounts" {
"capabilities" = [ "read" ]
}
And do the same for Group B members:
path "group_b_kv/*" {
"capabilities" = ["read", "create", "update", "list"]
}
path "sys/mounts" {
"capabilities" = [ "read" ]
}