Policies for policies

I want to give my user (Kate) the ability to give other users the right to see her secrets (in secrets/kate) but NOT to write policies concerning other users secrets. Particularly I want Kate to be able to use jwt to give her gitlab repo access to her secrets, I have made this work for root but I am not making these permissions for all my many users)

This may be a good use case for using internal Identity Groups and fine-grained ACL policies.

Kate would be granted access to manage a particular Identity Group called “kates_group” which is only allowed to have the policy “kates_read_only_policy”

path "identity/group/name/kates_group" {
  capabilities = ["create", "read", "update"]
  allowed_parameters = {
    "policies" = ["kates_read_only_policy"] #note that I'm not 100% sure on the syntax here particularly if you want to pass in a list of policies
    "type" = ["internal"]
  }
}

This should allow Kate to add members to the group to grant read-only access to her secrets while also preventing Kate from accidentally changing the policy and granting access to someone else’s secrets.

Note that I’ve not tested this but it should in theory work assuming the fine-grained policies apply correctly. You may also need to add some additional permissions so that Kate can list out the Identity Groups and Entities.

Also, I’m not sure how well this will scale if you have a very large environment. In that case you may want to consider some external management tools such as Terraform to better manage configuration via workflows and/or code.

this could work (Kate is an LDAP user, I haven’t figured that out yet. But surely I (as root, or admin with power) have to make Kates_read_only_policy and kates_group , for every one of my thousands of potential users. I need users to be able to assign permissions on their own secrets , or why HAVE a central vault in the first place? I think I am fundamentally failing at concepts here.

Don’t sell yourself short. I’ve been using Vault for 4+ years and I’m still learning new ways to do things.

One other strategy that might be beneficial for you is to utilize templated policies. These can enable writing a single policy that can be assigned to many auth roles leveraging metadata variables. For example, your policy can be something like:

path "secret/users/{{ identity.entity.name }}/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

This one policy can then be assigned to all your users and they would have access to only their secrets within the secret mount in the users folder (other policies may need to be added to allow folder traversal through the UI).

Using this approach wouldn’t lend itself well to self-delegation of access but can be combined with the previous suggestion if that’s still a need.

also I think I have to put all the parameters which will be set, not just the ones I want to constrain, and “bound_claim” is a structure, and I can’t see how to write a policy for “you can put anything here”

A more complete example might help.

The following items would need to be setup to support what I’m talking about above:
Note: This assumes you have a dedicated Vault administrator or process creating these items. If you’re looking for full delegation then Vault Enterprise Namespaces + Sentinel policies may be more appropriate for your use case (we can get into that later if that’s of interest).

Need one of each of these:

  • JWT auth mount
  • Identity secrets mount
  • Templated user policy (grants users access to their own secrets)
  • JWT auth role, with templated user policy assigned. Apply your claims settings here - delegated users would not need to define this.

Need one per enrolled group of these:

  • Identity Group (External)
  • Identity Alias (ties the Identity Group to the JWT role - name should match desired group claim )

Need one per delegated secret set

  • Identity Group (Internal)
  • Policy to delegate secrets applied to owner (may be able to be templated, but I’m not sure. Should be able to be applied to the owner’s Identity Entity or their Identity Group (External) to reduce single points of process failure)
  • Policy for delegated secrets applied to Identity Group (Internal)

Once all that is setup then a secret set owner(s) should be able to manage group membership of the Identity Group (Internal) to delegate access to their secrets.

It’s a lot to setup (and if you’re new to Vault a lot to understand as well) and I would suggest looking for ways to automate it (Terraform is a good option for this) as there’s probably too much to do here by hand reliably.

progress!

path “auth/jwt/role/" {
capabilities = [“create”,“delete”,“read”,“update”]
allowed_parameters = {
“role_type” = [“jwt”]
"
” =
“policies” = [“Kate-read”]
}
}

works! wow.

But

path “auth/jwt/role/" {
capabilities = [“create”,“delete”,“read”,“update”]
allowed_parameters = {
“role_type” = [“jwt”]
"
” =
“policies” = ["{{identity.entity.aliases.auth_ldap_1661e681.name}-read"]
}
}

does not, while

path “secret/data/users/{{identity.entity.aliases.auth_ldap_1661e681.name}}/*” {
capabilities = [“create”, “update”, “read”, “delete”]
}

does, which suggests the templating is working, but not inside the allowed_parameters.

The log file is of no help, so I am guessingh blind at what I need to put.

what we really need is an “allowed_paths” option in a policy : so admin could create a policy giving permission to create new policies, but only ones that have a certain path

path "sys/policies/acl/*" {
    capabilities = [“create”,“delete”,“read”,“update”]
    allowed_paths = ["/secrets/users/{{ identity.entity.name }}"/*}
}

so anyone with this policy can create new policies but only with paths starting with (for example) /secrets/users/kate

2 Likes

Even in mid size organizations this feature would be needed. Unfortunately currently not only the above proposed 'allowed_paths feature is missing, but even the following fails:
A 'policy creator policy like:

path "sys/policies/acl/rd-platform-k8s-development/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
  allowed_parameters = {
    capabilities = ["create", "read", "update", "delete", "list", "sudo"]                               
  }
}

fails to grant permissions to create the following policy:

path "my-kv-store/*" {
  capabilities = ["read"]
}

However if the allowed_parameters is remove from the policy granting policy, it succeeds.
So to get this working, both: allowed_parameters and allowed_paths would need to be supported for acl-s. Not sure if this is already supported, but the policy granting policy would further need to support creating multiple rules for the same acl path, which differ only in the combination of allowed_parameter - allowed_paths.

Currently the only workaround is, to implement some SW, which has admin rights in vault and through which users with delegated rights can define policies, roles… and which enforces the policies vault unable to at the moment.