Possible to bootstrap namespace with non-root token?

I’m working to automate the creation and management of vault namespaces via terraform. Are root tokens the only possible way to bootstrap a new namespace? We are a large organization and delegating this work is a requirement. However handling of root tokens is highly restricted.

From the docs…

NOTE: The creation of namespaces should be performed by a user with a highly privileged token such as root to set up isolated environments for each organization, team, or application.

A namespace was created for me for our business unit at /it and I’m automating the creation of child namespaces like /it/printer_team. I need the ability to write a policy into the printer_team namespace and generate a token for that namespace.

Is it possible to use a non root token or is that a hard requirement?

Thanks,
Blake

1 Like

It’s possible with normal permissions on https://www.vaultproject.io/api-docs/system/namespaces/

Excellent! Thanks for the nudge in correct direction.

Ok I’m still struggling with how the pathing works for child namespaces. I’m creating policy in the /it namespace to allow writing of a policy in the /it/printer_team namespace. For testing I setup a overly broad policy like this.

path "*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

With my non root token I’m able to then write a policy to the child namespace.

vault policy write -ns=it/printer_team bootstrap_policy bootstrap_policy.hcl

So yes totally possible to grant this ability to write a policy in a child namespace. Just need to scope things to the correct path. Looking at the api we have sys/namespace so that looks like the next path to try.

Updated my policy to this as it should include all child namespace paths?

path "sys/namespaces/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

With my non root token having this policy it’s unable to write the bootstrap_policy to the child namespace.

vault policy write -ns=it/printer_team bootstrap_policy bootstrap_policy.hcl
vault policy write -ns=it/printer_team bootstrap_policy bootstrap_policy.hcl
Error uploading policy: Error making API request.

URL: PUT https://localhost:8200/v1/sys/policies/acl/bootstrap_policy
Code: 403. Errors:

* 1 error occurred:
	* permission denied

At this point I’m either not using the sys/namespaces path correctly or paths outside of sys/namespace need to be opened up to allow writing the bootstrap policy to a child namespace. Based on the learn.hashicorp namespace doc I also tried these below in the non root token’s policy without luck.

# Manage namespaces
path "sys/namespaces/it/printer_team/namespaces/*" {
   capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage policies
path "sys/namespaces/it/printer_team/policies/acl/*" {
   capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

Hopefully I’m just overlooking something with how these paths work. Are there considerations for paths being relative if you’re working from within a namespace already? Other considerations for nested namespaces and pathing?

Just to circle back on this a bit.

In this learn doc you can see that prepending the namespace in front of the path is how this works. The /sys/namespace path if for acting on the namespace and not applying policy.

When working with nested namespaces the path is relative to the current one.

Sharing a few more details and a good starter policy if you need to do this. The core problem that was causing me issues ended up being a bug in 1.1.5 version of vault that prevents the creation of a child token using sudo permissions. Only a root token can successfully create a token directly in a child namespace for that version (hashicorp support case 26506). This has been resolved and we confirmed that it works as expected in 1.3.2.

Using the + syntax for matching namespace names also greatly simplifies the configuration as seen below in this policy.

# Create and manage ACL policies
path "sys/policies/acl/*"
{
 capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# To list policies
path "sys/policies/acl"
{
 capabilities = ["list"]
}

# Manage namespaces
path "sys/namespaces/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage tokens
path "auth/token/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Create and manage ACL policies
path "+/sys/policies/acl/*"
{
 capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# To list policies
path "+/sys/policies/acl"
{
 capabilities = ["list"]
}

# Manage namespaces
path "+/sys/namespaces/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage tokens
path "+/auth/token/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
1 Like