[Guide] Multi-Tenant Pattern with ACL Namespaces (0.11) (#5103)
* WIP - ACL Namespace * WIP - ACL Namepaces * WIP * WIP * WIP * WIP * WIP * Added UI screenshots * Added summary at the end * Added the Web UI steps in Step 5 * Update multi-tenant.html.md Updated text to ensure that we use the final "ship" name of namespaces (namespaces vs. ACL Namespaces) and introduced some industry-specific terminology (highlighting this is about Secure Multi-Tenancy)
This commit is contained in:
parent
50edc43df0
commit
56636735bc
BIN
website/source/assets/images/vault-multi-tenant-1.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-2.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-3.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-4.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-5.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-5.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-6.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-6.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-7.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-7.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant-8.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant-8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
website/source/assets/images/vault-multi-tenant.png
(Stored with Git LFS)
Normal file
BIN
website/source/assets/images/vault-multi-tenant.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -59,6 +59,10 @@ guide demonstrates how to selectively filter out secret engines from being
|
|||
replicated across clusters. This feature can help organizations to comply with
|
||||
***General Data Protection Regulation (GDPR)***.
|
||||
|
||||
- [Multi-Tenant Pattern with ACL
|
||||
Namespaces](/guides/operations/multi-tenant.html) guide discuss a pattern to
|
||||
isolate secrets using ACL Namespaces.
|
||||
|
||||
- [Vault Auto-unseal using AWS Key Management Service (KMS)](/guides/operations/autounseal-aws-kms.html) guide demonstrates an example of
|
||||
how to use Terraform to provision an instance that utilizes an encryption key
|
||||
from AWS Key Management Service (KMS).
|
||||
|
|
854
website/source/guides/operations/multi-tenant.html.md
Normal file
854
website/source/guides/operations/multi-tenant.html.md
Normal file
|
@ -0,0 +1,854 @@
|
|||
---
|
||||
layout: "guides"
|
||||
page_title: "Secure Multi-Tenancy with Namepaces - Guides"
|
||||
sidebar_current: "guides-operations-multi-tenant"
|
||||
description: |-
|
||||
This guide provides guidance in creating a multi-tenant environment.
|
||||
---
|
||||
|
||||
# Secure Multi-Tenancy with Namespaces
|
||||
|
||||
~> **Enterprise Only:** The namespaces feature is a part of _Vault Enterprise Pro_.
|
||||
|
||||
Everything in Vault is path-based, and often uses the terms `path` and
|
||||
`namespace` interchangeably. The application namespace pattern is a useful
|
||||
construct for providing Vault as a service to internal customers, giving them
|
||||
the ability to implement secure multi-tenancy within Vault in order to provide
|
||||
isolation and ensure teams can self-manage their own environments.
|
||||
|
||||
|
||||
## Reference Material
|
||||
|
||||
- [Vault Deployment Reference Architecture](/guides/operations/reference-architecture.html)
|
||||
- [Policies](/guides/identity/policies.html) guide
|
||||
|
||||
|
||||
## Estimated Time to Complete
|
||||
|
||||
10 minutes
|
||||
|
||||
|
||||
## Personas
|
||||
|
||||
The scenario described in this guide introduces the following personas:
|
||||
|
||||
- **`operations`** is the cluster-level administrator with privileged policies
|
||||
- **`org-admin`** is the organization-level administrator
|
||||
- **`team-admin`** is the team-level administrator
|
||||
|
||||
## Challenge
|
||||
|
||||
When Vault is primarily used as a central location to manage secrets, multiple
|
||||
organizations within a company may need to be able to manage their secrets in a
|
||||
self-serving manner. This means that a company needs to implement a ***Vault as
|
||||
a Service*** model allowing each organization (tenant) to manage their own
|
||||
secrets and policies. The most importantly, tenants should be restricted to work
|
||||
only within their tenant scope.
|
||||
|
||||
![Multi-Tenant](/assets/images/vault-multi-tenant.png)
|
||||
|
||||
## Solution
|
||||
|
||||
Create a **namespace** dedicated to each team, organization, or app where
|
||||
they can perform all necessary tasks within their tenant namespace.
|
||||
|
||||
Each namespace can have its own:
|
||||
|
||||
- Policies
|
||||
- Mounts
|
||||
- Tokens
|
||||
- Identity entities and groups
|
||||
|
||||
~> Tokens are locked to a namespace or child-namespaces. Identity groups can
|
||||
pull in entities and groups from _other_ namespaces.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To perform the tasks described in this guide, you need to have a **Vault
|
||||
Enterprise** environment.
|
||||
|
||||
-> **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.
|
||||
|
||||
|
||||
## Steps
|
||||
|
||||
**Scenario:** In this guide, you are going to create a namespace dedicated to
|
||||
the Education organization which has Training and Certification teams. Delegate
|
||||
operational tasks to the team admins so that the Vault cluster operators won't
|
||||
have to be involved.
|
||||
|
||||
![Scenario](/assets/images/vault-multi-tenant-2.png)
|
||||
|
||||
In this guide, you are going to perform the following steps:
|
||||
|
||||
1. [Create namespaces](#step1)
|
||||
1. [Write policies](#step2)
|
||||
1. [Setup entities and groups](#step3)
|
||||
1. [Test the organization admin user](#step4)
|
||||
1. [Test the team admin user](#step5)
|
||||
|
||||
|
||||
### <a name="step1"></a>Step 1: Create namespaces
|
||||
(**Persona:** operations)
|
||||
|
||||
#### CLI command
|
||||
|
||||
To create a new namespace, run: **`vault namespace create <namespace_name>`**
|
||||
|
||||
1. Create a namespace dedicated to the **`education`** organizations:
|
||||
|
||||
```plaintext
|
||||
$ vault namespace create education
|
||||
````
|
||||
|
||||
1. Create child namespaces called `training` and `certification` under the
|
||||
`education` namespace:
|
||||
|
||||
```plaintext
|
||||
$ vault namespace create -namespace=education training
|
||||
|
||||
$ vault namespace create -namespace=education certification
|
||||
````
|
||||
|
||||
1. List the created namespaces:
|
||||
|
||||
```plaintext
|
||||
$ vault namespace list
|
||||
education/
|
||||
|
||||
$ vault namespace list -namespace=education
|
||||
certification/
|
||||
training/
|
||||
```
|
||||
|
||||
#### API call using cURL
|
||||
|
||||
To create a new namespace, invoke **`sys/namespaces`** endpoint:
|
||||
|
||||
```shell
|
||||
$ curl --header "X-Vault-Token: <TOKEN>" \
|
||||
--request POST \
|
||||
<VAULT_ADDRESS>/v1/sys/namespaces/<NS_NAME>
|
||||
```
|
||||
|
||||
Where `<TOKEN>` is your valid token, and `<NS_NAME>` is the desired namespace
|
||||
name.
|
||||
|
||||
1. Create a namespace for the **`education`** organization:
|
||||
|
||||
```plaintext
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--request POST \
|
||||
http://127.0.0.1:8200/v1/sys/namespaces/education
|
||||
```
|
||||
|
||||
1. Now, create a child namespace called **`training`** and **`certification`**
|
||||
under `education`. To do so, pass the top-level namespace name in the
|
||||
**`X-Vault-Namespace`** header.
|
||||
|
||||
```shell
|
||||
# Create a training namespace under education
|
||||
# NOTE: Top-level namespace is in the API endpoint
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--header "X-Vault-Namespace: education" \
|
||||
--request POST \
|
||||
http://127.0.0.1:8200/v1/education/sys/namespaces/training
|
||||
|
||||
# Create a certification namespace under education
|
||||
# NOTE: Pass the top-level namespace in the header
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--header "X-Vault-Namespace: education" \
|
||||
--request POST \
|
||||
http://127.0.0.1:8200/v1/sys/namespaces/certification
|
||||
```
|
||||
|
||||
1. List the created namespaces:
|
||||
|
||||
```plaintext
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--request LIST
|
||||
http://127.0.0.1:8200/v1/sys/namespaces | jq
|
||||
{
|
||||
...
|
||||
"data": {
|
||||
"keys": [
|
||||
"education/"
|
||||
]
|
||||
},
|
||||
...
|
||||
|
||||
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--request LIST
|
||||
http://127.0.0.1:8200/v1/education/sys/namespaces | jq
|
||||
{
|
||||
...
|
||||
"data": {
|
||||
"keys": [
|
||||
"certification/",
|
||||
"training/"
|
||||
]
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
#### Web UI
|
||||
|
||||
1. Open a web browser and launch the Vault UI (e.g. http://127.0.01:8200/ui)
|
||||
and then login.
|
||||
|
||||
1. Select **Access**.
|
||||
|
||||
1. Select **Namespaces** and then click **Create a namespace**.
|
||||
|
||||
1. Enter **`education`** in the **Path** field.
|
||||
|
||||
1. Click **Save**.
|
||||
|
||||
1. To create child namespaces, select the down-arrow on the upper left corner of
|
||||
the UI, and select **education** under **CURRENT NAMESPACE**.
|
||||
|
||||
![NS Selection](/assets/images/vault-multi-tenant-1.png)
|
||||
|
||||
1. Under the **Access** tab, select **Namespaces** and then click **Create a namespace**.
|
||||
|
||||
1. Enter **`training`** in the **Path** field, and click **Save**.
|
||||
|
||||
1. Select **Create a namespace** again, and then enter **`certification`** in
|
||||
the **Path** field, and click **Save**.
|
||||
|
||||
|
||||
|
||||
### <a name="step2"></a>Step 2: Write Policies
|
||||
(**Persona:** operations)
|
||||
|
||||
In this scenario, there is an organization-level administrator who is a
|
||||
superuser within the scope of the **`education`** namespace. Also, there is a
|
||||
team-level administrator for **`training`** and **`certification`**.
|
||||
|
||||
|
||||
#### Policy for education admin
|
||||
|
||||
**Requirements:**
|
||||
|
||||
- Create and manage namespaces
|
||||
- Create and manage policies
|
||||
- Enable and manage secret engines
|
||||
- Create and manage entities and groups
|
||||
- Manage tokens
|
||||
|
||||
**`edu-admin.hcl`**
|
||||
|
||||
```shell
|
||||
# Manage namespaces
|
||||
path "sys/namespaces/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# Manage policies via API
|
||||
path "sys/policies/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# Manage policies via CLI
|
||||
path "sys/policy/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# List policies via CLI
|
||||
path "sys/policy" {
|
||||
capabilities = ["read", "update", "list"]
|
||||
}
|
||||
|
||||
# Enable and manage secrets engines
|
||||
path "sys/mounts/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# List available secret engines
|
||||
path "sys/mounts" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
|
||||
# Create and manage entities and groups
|
||||
path "identity/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Manage tokens
|
||||
path "auth/token/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Policy for training admin
|
||||
|
||||
**Requirements:**
|
||||
|
||||
- Create and manage child-namespaces
|
||||
- Create and manage policies
|
||||
- Enable and manage secret engines
|
||||
|
||||
**`training-admin.hcl`**
|
||||
|
||||
```shell
|
||||
# Manage namespaces
|
||||
path "sys/namespaces/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# Manage policies via API
|
||||
path "sys/policies/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# Manage policies via CLI
|
||||
path "sys/policy/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# List policies via CLI
|
||||
path "sys/policy" {
|
||||
capabilities = ["read", "update", "list"]
|
||||
}
|
||||
|
||||
# Enable and manage secrets engines
|
||||
path "sys/mounts/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# List available secret engines
|
||||
path "sys/mounts" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
```
|
||||
|
||||
Now, let's deploy the policies!
|
||||
|
||||
|
||||
#### CLI command
|
||||
|
||||
To target a specific namespace, you can do one of the following:
|
||||
|
||||
* Set **`VAULT_NAMESPACE`** so that all subsequent CLI commands will be
|
||||
executed against that particular namespace
|
||||
|
||||
```plaintext
|
||||
$ export VAULT_NAMESPACE=<namespace_name>
|
||||
$ vault policy write <policy_name> <policy_file>
|
||||
```
|
||||
|
||||
* Specify the target namespace with **`-namespace`** flag
|
||||
|
||||
```plaintext
|
||||
$ vault policy write -namespace=<namespace_name> <policy_name> <policy_file>
|
||||
```
|
||||
|
||||
Since you have to deploy policies onto "`education`" and "`education/training`"
|
||||
namespaces, use "`-namespace`" flag instead of environment variable.
|
||||
|
||||
Create **`edu-admin`** and **`training-admin`** policies.
|
||||
|
||||
```shell
|
||||
# Create edu-admin policy under 'education' namespace
|
||||
$ vault policy write -namespace=education edu-admin edu-admin.hcl
|
||||
|
||||
# Create training-admin policy under 'education/training' namespace
|
||||
$ vault policy write -namespace=education/training training-admin training-admin.hcl
|
||||
```
|
||||
|
||||
#### API call using cURL
|
||||
|
||||
To target a specific namespace, you can do one of the following:
|
||||
|
||||
* Pass the target namespace in the **`X-Vault-Namespace`** header
|
||||
|
||||
* Prepend the API endpoint with namespace name (e.g.
|
||||
**`<namespace_name>`**`/sys/policies/acl`)
|
||||
|
||||
|
||||
Create **`edu-admin`** and **`training-admin`** policies.
|
||||
|
||||
```shell
|
||||
# Create a request payload
|
||||
$ tee edu-payload.json <<EOF
|
||||
{
|
||||
"policy": "path \"sys/namespaces/education/*\" {\n capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\", \"sudo\"]\n } ... "
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create edu-admin policy under 'education' namespace
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--header "X-Vault-Namespace: education" \
|
||||
--request PUT \
|
||||
--data @edu-payload.json \
|
||||
https://vault.rocks/v1/sys/policies/acl/edu-admin
|
||||
|
||||
# Create a request payload
|
||||
$ tee training-payload.json <<EOF
|
||||
{
|
||||
"policy": "path \"sys/namespaces/education/training/*\" {\n capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\", \"sudo\"]\n } ... "
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create training-admin policy under 'education/training' namespace
|
||||
# This example directs the target namespace in the API endpoint
|
||||
$ curl --header "X-Vault-Token: ..." \
|
||||
--request PUT \
|
||||
--data @training-payload.json \
|
||||
https://vault.rocks/v1/education/training/sys/policies/acl/training-admin
|
||||
```
|
||||
|
||||
|
||||
#### Web UI
|
||||
|
||||
1. In the Web UI, make sure that the **CURRENT NAMESPACE** is set to
|
||||
**education** in the upper left menu.
|
||||
|
||||
1. Click the **Policies** tab, and then select **Create ACL policy**.
|
||||
|
||||
1. Toggle **Upload file** sliding switch, and click **Choose a file** to select your
|
||||
**`edu-admin.hcl`** file you authored. This loads the policy and sets the
|
||||
**Name** to be `edu-admin`.
|
||||
|
||||
1. Click **Create Policy** to complete.
|
||||
|
||||
1. Set the **CURRENT NAMESPACE** to be **education/training** in the upper left
|
||||
menu.
|
||||
![Namespace](/assets/images/vault-multi-tenant-6.png)
|
||||
|
||||
1. In the **Policies** tab, select **Create ACL policy**.
|
||||
|
||||
1. Toggle **Upload file**, and click **Choose a file** to select your
|
||||
**`training-admin.hcl`** file you authored.
|
||||
|
||||
1. Click **Create Policy**.
|
||||
|
||||
|
||||
### <a name="step3"></a>Step 3: Setup entities and groups
|
||||
(**Persona:** operations)
|
||||
|
||||
Bob who is an organization-level administrator (superuser) has two accounts:
|
||||
**`bob`** and **`bsmith`**. You will create an entity, **Bob Smith** to
|
||||
associate those two accounts.
|
||||
|
||||
Also, you are going to create a group for the team-level administrator, **Team
|
||||
Admin**, and add Bob Smith entity as a group member so that Bob can inherit the
|
||||
`training-admin` policy to manage the child namespace if he ever has to take
|
||||
over.
|
||||
|
||||
![Entities and Groups](/assets/images/vault-multi-tenant-3.png)
|
||||
|
||||
-> This step only demonstrates CLI commands and Web UI to create
|
||||
entities and groups. Refer to the [Identity - Entities and
|
||||
Groups](/guides/identity/identity.html) guide if you need the full details.
|
||||
|
||||
#### CLI Command
|
||||
|
||||
```shell
|
||||
# First, you need to enable userpass auth method
|
||||
$ vault auth enable -namespace=education userpass
|
||||
|
||||
# Create a user 'bob'
|
||||
$ vault write -namespace=education \
|
||||
auth/userpass/users/bob password="password"
|
||||
|
||||
# Create an entity for Bob Smith with 'edu-admin' policy attached
|
||||
# Save the generated entity ID in entity_id.txt file
|
||||
$ vault write -namespace=education -format=json identity/entity name="Bob Smith" \
|
||||
policies="edu-admin" | jq -r ".data.id" > entity_id.txt
|
||||
|
||||
# Get the mount accessor for userpass auth method and save it in accessor.txt file
|
||||
$ vault auth list -namespace=education -format=json \
|
||||
| jq -r '.["userpass/"].accessor' > accessor.txt
|
||||
|
||||
# Create an entity alias for Bob Smith to attach 'bob'
|
||||
$ vault write -namespace=education identity/entity-alias name="bob" \
|
||||
canonical_id=$(cat entity_id.txt) mount_accessor=$(cat accessor.txt)
|
||||
|
||||
# Create a group, "Training Admin" in education/training namespace
|
||||
$ vault write -namespace=education/training identity/group \
|
||||
name="Training Admin" policies="training-admin" \
|
||||
member_entity_ids=$(cat entity_id.txt)
|
||||
|
||||
# Enable userpass auth method in training namespace
|
||||
$ vault auth enable -namespace=education/namespace userpass
|
||||
|
||||
# Create a user 'bsmith'
|
||||
$ vault write -namespace=education/training \
|
||||
auth/userpass/users/bsmith password="password"
|
||||
|
||||
# Get the mount accessor for userpass auth method and save it in accessor2.txt file
|
||||
$ vault auth list -namespace=education/training -format=json \
|
||||
| jq -r '.["userpass/"].accessor' > accessor2.txt
|
||||
|
||||
# Add 'bsmith' to Bob Smith entity as its alias
|
||||
$ vault write -namespace=education identity/entity-alias name="bsmith" \
|
||||
canonical_id=$(cat entity_id.txt) mount_accessor=$(cat accessor2.txt)
|
||||
```
|
||||
|
||||
|
||||
#### Web UI
|
||||
|
||||
1. In the Web UI, make sure that the **CURRENT NAMESPACE** is set to
|
||||
**education** in the upper left menu.
|
||||
|
||||
1. Click the **Access** tab, and select **Enable new method**.
|
||||
|
||||
1. Select **Username & Password** from the **Type** drop-down menu.
|
||||
|
||||
1. Click **Enable Method**.
|
||||
|
||||
1. Click the Vault CLI shell icon (**`>_`**) to open a command shell. Enter the
|
||||
following command to create a new user, **`bob`**.
|
||||
|
||||
```plaintext
|
||||
vault write auth/userpass/users/bob password="password"
|
||||
```
|
||||
![Create Policy](/assets/images/vault-multi-tenant-4.png)
|
||||
|
||||
1. Click the icon (**`>_`**) again to hide the shell.
|
||||
|
||||
1. From the **Access** tab, select **Entities** and then **Create entity**.
|
||||
|
||||
1. Enter **`Bob Smith`** in the **Name** field, and **`edu-admin`** in the
|
||||
**Policies** field.
|
||||
|
||||
1. Click **Create**.
|
||||
|
||||
1. Select **Add alias**. Enter **`bob`** in the **Name** field and select
|
||||
**`userpass/ (userpass)`** from the **Auth Backend** drop-down list.
|
||||
|
||||
1. Click **Create**.
|
||||
|
||||
1. Click the **Access** tab and select **Entities**.
|
||||
|
||||
1. Select the **`bob-smith`** entity and copy its **ID** displayed under the
|
||||
**Details** tab.
|
||||
|
||||
1. Now, set the **CURRENT NAMESPACE** to **education/training**.
|
||||
![Namespace](/assets/images/vault-multi-tenant-6.png)
|
||||
|
||||
1. In the **Access** tab, select **Groups**, and select **Create group**.
|
||||
|
||||
1. Paste in the entity ID in the **Member Entity IDs** field you copied.
|
||||
|
||||
1. Enter **`Training Admin`** in the **Name** field, **`training-admin`** in the
|
||||
**Policies** field, and click **Create**.
|
||||
|
||||
1. Click the **Access** tab, and select **Enable new method**.
|
||||
|
||||
1. Select **Username & Password** from the **Type** drop-down menu.
|
||||
|
||||
1. Click **Enable Method**. Copy the mount accessor value which you will user later.
|
||||
![Namespace](/assets/images/vault-multi-tenant-8.png)
|
||||
|
||||
1. Click the Vault CLI shell icon (**`>_`**) to open a command shell. Enter the
|
||||
following command to create a new user, **`bsmith`**.
|
||||
|
||||
```plaintext
|
||||
vault write auth/userpass/users/bsmith password="password"
|
||||
```
|
||||
|
||||
1. Set the **CURRENT NAMESPACE** back to **education**.
|
||||
|
||||
1. In the command shell, enter the following command. Be sure to replace the
|
||||
`<Bob_Smith_entity_id>` with the value you copied at step 13, and
|
||||
`<mount_accessor>` with the value you copied at step 20.
|
||||
|
||||
```plaintext
|
||||
vault write identity/entity-alias name="bsmith" \
|
||||
canonical_id=<Bob_Smith_entity_id> mount_accessor=<mount_accessor>
|
||||
```
|
||||
|
||||
|
||||
### <a name="step4"></a>Step 4: Test the organization admin user
|
||||
(**Persona:** org-admin)
|
||||
|
||||
#### CLI Command
|
||||
|
||||
Log in as **`bob`** into the `education` namespace:
|
||||
|
||||
```plaintext
|
||||
$ vault login -namespace=education -method=userpass username="bob" password="password"
|
||||
|
||||
Key Value
|
||||
--- -----
|
||||
token 5ai0qpQeCdRHALzEY4Q8sW.28dk2
|
||||
token_accessor 9xXQmdx6Aq6zw1KX4gpzb.28dk2
|
||||
token_duration 768h
|
||||
token_renewable true
|
||||
token_policies ["default"]
|
||||
identity_policies ["edu-admin"]
|
||||
policies ["default" "edu-admin"]
|
||||
token_meta_username bob
|
||||
```
|
||||
|
||||
Notice that the user, `bob` only has `default` policy attached to his token
|
||||
(`token_policies`); however, he inherited the `edu-admin` policy from the `Bob
|
||||
Smith` entity (`identity_policies`).
|
||||
|
||||
Test to make sure that `bob` can create a namespace, enable secrets engine, and
|
||||
whatever else that you want to verify.
|
||||
|
||||
```shell
|
||||
# Set the target namespace as an env variable
|
||||
$ export VAULT_NAMESPACE="education"
|
||||
|
||||
# Create a new namespace called 'web-app'
|
||||
$ vault namespace create web-app
|
||||
Success! Namespace created at: education/web-app/
|
||||
|
||||
# Enable key/value v2 secrets engine at edu-secret
|
||||
$ vault secrets enable -path=edu-secret kv-v2
|
||||
Success! Enabled the kv-v2 secrets engine at: edu-secret/
|
||||
```
|
||||
|
||||
Optionally, you can create new policies to test that `bob` can perform the
|
||||
operations as expected. When you are done testing, unset the VAULT_NAMESPACE
|
||||
environment variable.
|
||||
|
||||
```plaintext
|
||||
$ unset VAULT_NAMESPACE
|
||||
```
|
||||
|
||||
#### API call using cURL
|
||||
|
||||
Log in as **`bob`** into the `education` namespace:
|
||||
|
||||
```plaintext
|
||||
$ curl --header "X-Vault-Namespace: education" \
|
||||
--request POST \
|
||||
--data '{"password": "password"}' \
|
||||
http://127.0.0.1:8200/v1/auth/userpass/login/bob | jq
|
||||
{
|
||||
...
|
||||
"auth": {
|
||||
"client_token": "5ai0qpQeCdRHALzEY4Q8sW.28dk2",
|
||||
"accessor": "9xXQmdx6Aq6zw1KX4gpzb.28dk2",
|
||||
"policies": [
|
||||
"default",
|
||||
"edu-admin"
|
||||
],
|
||||
"token_policies": [
|
||||
"default"
|
||||
],
|
||||
"identity_policies": [
|
||||
"edu-admin"
|
||||
],
|
||||
"external_namespace_policies": {
|
||||
"9dKXw": [
|
||||
"training-admin"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"username": "bob"
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice that the user, `bob` only has `default` policy attached to his token
|
||||
(`token_policies`); however, he inherited the `edu-admin` policy from the `Bob
|
||||
Smith` entity (`identity_policies`). Also, `training-admin` policy is listed
|
||||
under `external_namespace_policies` due to its membership to the Training Admin
|
||||
group in `education/training` namespace.
|
||||
|
||||
Verify that `bob` can perform the operations permitted by the `edu-admin`
|
||||
policy.
|
||||
|
||||
```shell
|
||||
# Create a new namespace called 'web-app'
|
||||
# Be sure to use generated bob's client token
|
||||
$ curl --header "X-Vault-Token: 5ai0qpQeCdRHALzEY4Q8sW.28dk2" \
|
||||
--request POST \
|
||||
http://127.0.0.1:8200/v1/education/sys/namespaces/web-app
|
||||
|
||||
# Enable key/value v2 secrets engine at edu-secret
|
||||
$ curl --header "X-Vault-Token: 5ai0qpQeCdRHALzEY4Q8sW.28dk2" \
|
||||
--request POST \
|
||||
--data '{"type": "kv-v2"}' \
|
||||
http://127.0.0.1:8200/v1/education/sys/mounts/edu-secret
|
||||
```
|
||||
|
||||
|
||||
#### Web UI
|
||||
|
||||
1. Open a web browser and launch the Vault UI (e.g. http://127.0.01:8200/ui). If
|
||||
you are already logged in, sign out.
|
||||
|
||||
1. At the **Sign in to Vault**, set the **Namespace** to **`education`**.
|
||||
|
||||
1. Select the **Userpass** tab, and enter **`bob`** in the **Username** field,
|
||||
and **`password`** in the **Password** field.
|
||||
![Login](/assets/images/vault-multi-tenant-5.png)
|
||||
|
||||
1. Click **Sign in**. Notice that the CURRENT NAMESPACE is set to **education**
|
||||
in the upper left corner of the UI.
|
||||
|
||||
1. To add a new namespace, select **Access**.
|
||||
|
||||
1. Select **Namespaces** and then click **Create a namespace**.
|
||||
|
||||
1. Enter **`web-app`** in the **Path** field, and then click **Save**.
|
||||
|
||||
1. Select **Secrets**, and then **Enable new engine**.
|
||||
|
||||
1. Select **KV** from the **Secrets engine type** drop-down list, and enter
|
||||
**`edu-secret`** in the **Path** field.
|
||||
|
||||
1. Click **Enable Engine** to finish.
|
||||
|
||||
|
||||
### <a name="step5"></a>Step 5: Test the team admin user
|
||||
(**Persona:** team-admin)
|
||||
|
||||
#### CLI Command
|
||||
|
||||
Log in as **`bsmith`** into the **`education/training`** namespace:
|
||||
|
||||
```plaintext
|
||||
$ vault login -namespace=education/training -method=userpass username="bsmith" password="password"
|
||||
|
||||
Key Value
|
||||
--- -----
|
||||
token 5YNNjDDl6D8iW3eGQIlU0q.9dKXw
|
||||
token_accessor 6TVkDhdvEQXO2JaD64TVLv.9dKXw
|
||||
token_duration 768h
|
||||
token_renewable true
|
||||
token_policies ["default"]
|
||||
identity_policies ["training-admin"]
|
||||
policies ["default" "training-admin"]
|
||||
token_meta_username bsmith
|
||||
```
|
||||
|
||||
Notice that the user, `bsmith` inherited the `training-admin` policy from the
|
||||
`Training Admin` group (`training_admin`) which `Bob Smith` entity is a member
|
||||
of.
|
||||
|
||||
Verify that `bsmith` can perform the operations permitted by the
|
||||
`training-admin` policy.
|
||||
|
||||
```shell
|
||||
# Set the target namespace as an env variable
|
||||
$ export VAULT_NAMESPACE="education/training"
|
||||
|
||||
# Create a new namespace called 'vault-training'
|
||||
$ vault namespace create vault-training
|
||||
Success! Namespace created at: education/training/vault-training/
|
||||
|
||||
# Enable key/value v1 secrets engine at team-secret
|
||||
$ vault secrets enable -path=team-secret -version=1 kv
|
||||
Success! Enabled the kv secrets engine at: team-secret/
|
||||
```
|
||||
|
||||
When you are done testing, unset the VAULT_NAMESPACE environment variable.
|
||||
|
||||
```plaintext
|
||||
$ unset VAULT_NAMESPACE
|
||||
```
|
||||
|
||||
#### API call using cURL
|
||||
|
||||
Log in as **`bsmith`** into the `education` namespace:
|
||||
|
||||
```plaintext
|
||||
$ curl --header "X-Vault-Namespace: education/training" \
|
||||
--request POST \
|
||||
--data '{"password": "password"}' \
|
||||
http://127.0.0.1:8200/v1/auth/userpass/login/bsmith | jq
|
||||
{
|
||||
...
|
||||
"auth": {
|
||||
"client_token": "5YNNjDDl6D8iW3eGQIlU0q.9dKXw",
|
||||
"accessor": "6TVkDhdvEQXO2JaD64TVLv.9dKXw",
|
||||
"display_name": "education-training-auth-userpass-bsmith",
|
||||
"policies": [
|
||||
"default",
|
||||
"training-admin"
|
||||
],
|
||||
"token_policies": [
|
||||
"default"
|
||||
],
|
||||
"identity_policies": [
|
||||
"training-admin"
|
||||
],
|
||||
"external_namespace_policies": {
|
||||
"28dk2": [
|
||||
"edu-admin"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"username": "bsmith"
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice that the user, `bsmith` inherited the `training-admin` policy from the
|
||||
`Training Admin` group which `Bob Smith` entity is a member of. Also,
|
||||
`edu-admin` policy is listed under `external_namespace_policies`.
|
||||
|
||||
Verify that `bsmith` can perform the operations permitted by the
|
||||
`training-admin` policy.
|
||||
|
||||
```shell
|
||||
# Create a new namespace called 'vault-training'
|
||||
# Be sure to use generated bsmith's client token
|
||||
$ curl --header "X-Vault-Token: 5YNNjDDl6D8iW3eGQIlU0q.9dKXw" \
|
||||
--request POST \
|
||||
http://127.0.0.1:8200/v1/education/training/sys/namespaces/web-app
|
||||
|
||||
# Enable key/value v1 secrets engine at team-secret
|
||||
$ curl --header "X-Vault-Token: 5YNNjDDl6D8iW3eGQIlU0q.9dKXw" \
|
||||
--request POST \
|
||||
--data '{"type": "kv"}' \
|
||||
http://127.0.0.1:8200/v1/education/training/sys/mounts/edu-secret
|
||||
```
|
||||
|
||||
#### Web UI
|
||||
|
||||
1. Open a web browser and launch the Vault UI (e.g. http://127.0.01:8200/ui). If
|
||||
you are already logged in, sign out.
|
||||
|
||||
1. At the **Sign in to Vault**, set the **Namespace** to **`education/training`**.
|
||||
|
||||
1. Select the **Userpass** tab, and enter **`bsmith`** in the **Username** field,
|
||||
and **`password`** in the **Password** field.
|
||||
|
||||
1. Click **Sign in**.
|
||||
|
||||
1. To add a new namespace, select **Access**.
|
||||
|
||||
1. Select **Namespaces** and then click **Create a namespace**.
|
||||
|
||||
1. Enter **`vault-training`** in the **Path** field, and then click **Save**.
|
||||
|
||||
1. Select **Secrets**, and then **Enable new engine**.
|
||||
|
||||
1. Select **KV** from the **Secrets engine type** drop-down list, and enter
|
||||
**`team-secret`** in the **Path** field.
|
||||
|
||||
1. Click **Enable Engine** to finish.
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
~> **Summary:** As this guide demonstrated, each namespace you created behaves
|
||||
as an **isolated** Vault environment. Once you sign into a namespace, there is
|
||||
no visibility into other namespaces regardless of its hierarchical relationship.
|
||||
Tokens, policies, and secrets engines are tied to its namespace; therefore, each
|
||||
client must acquire a valid token for each namespace to access their secrets.
|
||||
|
||||
|
||||
## Next steps
|
||||
|
||||
Refer to the [Sentinel Policies](/guides/identity/sentinel.html) guide if you
|
||||
need to write policies that allow you to embed finer control over the user
|
||||
access across those namespaces.
|
|
@ -38,6 +38,9 @@
|
|||
<li<%= sidebar_current("guides-operations-mount-filter") %>>
|
||||
<a href="/guides/operations/mount-filter.html">Mount Filter</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("guides-operations-multi-tenant") %>>
|
||||
<a href="/guides/operations/multi-tenant.html">Multi-Tenant: ACL Namespaces</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("guides-operations-autounseal-aws-kms") %>>
|
||||
<a href="/guides/operations/autounseal-aws-kms.html">Vault Auto-unseal with AWS KMS</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in a new issue