* Control Group guide * Fixed user policy list * Fixed a typo * Replaced the wrong screenshot * Added missing period
19 KiB
layout | page_title | sidebar_current | description |
---|---|---|---|
guides | Control Groups - Guides | guides-identity-control-groups | Vault Enterprise has a support for Control Group Authorization which adds additional authorization factors to be required before satisfying a request. |
Control Groups
~> Enterprise Only: Control Groups is a part of Vault Enterprise Premium.
Control Groups add additional authorization factors to be required before processing requests to increase the governance, accountability, and security of your secrets. When a control group is required for a request, the requesting client receives the wrapping token in return. Only when all authorizations are satisfied, the wrapping token can be used to unwrap the requested secrets.
Reference Material
Estimated Time to Complete
10 minutes
Personas
The end-to-end scenario described in this guide involves three personas:
admin
with privileged permissions to create policies and identities- processor with permission to approve secret access
- controller with limited permission to access secrets
Challenge
In order to operate in EU, a company must abide by the General Data Protection Regulation (GDPR) as of May 2018. The regulation enforces two or more controllers jointly determine the purposes and means of processing (Chapter 4: Controller and Processor).
Consider the following scenarios:
-
Anytime an authorized user requests to read data at "
EU_GDPR_data/orders/*
", at least two people from the Security group must approve to ensure that the user has a valid business reason for requesting the data. -
Anytime a database configuration is updated, it requires that one person from the DBA and one person from Security group must approve it.
Solution
Use Control Groups in your policies to implement dual controller authorization required.
Prerequisites
To perform the tasks described in this guide, you need to have a Vault Enterprise environment.
This guide assumes that you have some hands-on experience with ACL policies as well as Identities. If you are not familiar, go through the following guides first:
Policy requirements
Since this guide demonstrates the creation of policies, log in with a highly
privileged token such as root
.
Otherwise, required permissions to perform
the steps in this guide are:
# Create and manage ACL policies via CLI
path "sys/policy/*"
{
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# Create and manage ACL policies via Web UI
path "sys/policies/acl/*"
{
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# To enable secret engines
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete" ]
}
# Setting up test data
path "EU_GDPR_data/*"
{
capabilities = ["create", "read", "update", "delete", "list"]
}
# Manage userpass auth method
path "auth/userpass/*"
{
capabilities = ["create", "read", "update", "delete", "list"]
}
# List, create, update, and delete auth methods
path "sys/auth/*"
{
capabilities = ["create", "read", "update", "delete"]
}
# Create and manage entities and groups
path "identity/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
Steps
The scenario in this guide is that a user, Bob Smith
has
read-only permission on the "EU_GDPR_data/orders/*
" path; however,
someone in the acct_manager
group must approve it before he can actually
read the data.
As a member of the acct_manager
group, Ellen Wright
can authorize
Bob's request.
You are going to perform the following:
- Implement a control group
- Deploy the policies
- Setup entities and a group
- Verification
- ACL Policies vs. Sentinel Policies
-> Step 1, 2 and 3 are the tasks need to be performed by administrators or operators who have the privileges to create policies and configure entities and groups.
Step 1: Implement a control group
(Persona: admin)
-
Author a policy named,
read-gdpr-order.hcl
.Bob needs "
read
" permit on "EU_GDPR_data/orders/*
":path "EU_GDPR_data/orders/*" { capabilities = [ "read" ] }
Now, add control group to this policy:
path "EU_GDPR_data/orders/*" { capabilities = [ "read" ] control_group = { factor "authorizer" { identity { group_names = [ "acct_manager" ] approvals = 1 } } } }
For the purpose of this guide, the number of
approvals
is set to1
to keep it simple and easy to test. Any member of the identity group,acct_manager
can approve the read request. Although this example has only one factor (authorizer
), you can add as many factor blocks as you need. -
Now, write another policy for the
acct_manager
group namedacct_manager.hcl
.# To approve the request path "sys/control-group/authorize" { capabilities = ["create", "update"] } # To check control group request status path "sys/control-group/request" { capabilities = ["create", "update"] }
NOTE: The important thing here is that the authorizer (
acct_manager
) must havecreate
andupdate
permission on thesys/control-group/authorize
endpoint so that they can approve the request. -
Enable key/value secrets engine at
EU_GDPR_data
and write some mock data:# Enable kv-v1 at EU_GDPR_data $ vault secrets enable -path=EU_GDPR_data -version=1 kv # Write some mock data $ vault kv put EU_GDPR_data/orders/acct1 order_number="12345678" product_id="987654321"
Step 2: Deploy the policies
(Persona: admin)
Deploy the read-gdpr-order
and acct_manager
policies that you wrote.
CLI command
# Create read-gdpr-order policy
$ vault policy write read-gdpr-order read-gdpr-order.hcl
# Create acct_manager policy
$ vault policy write acct_manager acct_manager.hcl
API call using cURL
# Construct API request payload to create read-gdpr-read policy
$ tee payload-1.json <<EOF
{
"policy": "path \"EU_GDPR_data/orders/*\" {capabilities = [ \"read\" ]control_group = {factor \"authorizer\" ..."
}
EOF
# Create read-gdpr-order policy
$ curl --header "X-Vault-Token: ..." \
--request PUT \
--data @payload-1.json \
http://127.0.0.1:8200/v1/sys/policies/acl/read-gdpr-order
# Construct API request payload to create acct_manager policy
$ tee payload-2.json <<EOF
{
"policy": "path \"sys/control-group/authorize\" {capabilities = [\"create\", \"update\"]} ..."
}
EOF
# Create acct_manager policy
$ curl --header "X-Vault-Token: ..." \
--request PUT \
--data @payload-2.json \
http://127.0.0.1:8200/v1/sys/policies/acl/acct_manager
Web UI
Open a web browser and launch the Vault UI (e.g. http://127.0.0.1:8200/ui) and then login.
-
Click the Policies tab, and then select Create ACL policy.
-
Toggle Upload file, and click Choose a file to select your
read-gdpr-order.hcl
file you authored at Step 1.This loads the policy and sets the Name to be
read-gdpr-order
. -
Click Create Policy to complete.
-
Repeat the steps to create a policy for
acct_manager
.
Step 3: Setup entities and a group
(Persona: admin)
-> This step only demonstrates CLI commands and Web UI to create entities and groups. Refer to the Identity - Entities and Groups guide if you need the full details.
Now you have policies, let's create a user, bob
and an acct_manager
group with ellen
as a group member.
NOTE: For the purpose of this guide, use
userpass
auth method to create userbob
andellen
so that the scenario can be easily tested.
CLI command
The following command uses jq
tool
to parse JSON output.
# Enable userpass
$ vault auth enable userpass
# Create a user, bob
$ vault write auth/userpass/users/bob password="training"
# Create a user, ellen
$ vault write auth/userpass/users/ellen password="training"
# Retrieve the userpass mount accessor and save it in a file named, accessor.txt
$ vault auth list -format=json | jq -r '.["userpass/"].accessor' > accessor.txt
# Create Bob Smith entity and save the identity ID in the entity_id_bob.txt
$ vault write -format=json identity/entity name="Bob Smith" policies="read-gdpr-order" \
metadata=team="Processor" \
| jq -r ".data.id" > entity_id_bob.txt
# Add an entity alias for the Bob Smith entity
$ vault write identity/entity-alias name="bob" \
canonical_id=$(cat entity_id_bob.txt) \
mount_accessor=$(cat accessor.txt)
# Create Ellen Wright entity and save the identity ID in the entity_id_ellen.txt
$ vault write -format=json identity/entity name="Ellen Wright" policies="default" \
metadata=team="Acct Controller" \
| jq -r ".data.id" > entity_id_ellen.txt
# Add an entity alias for the Ellen Wright entity
$ vault write identity/entity-alias name="ellen" \
canonical_id=$(cat entity_id_ellen.txt) \
mount_accessor=$(cat accessor.txt)
# Finally, create acct_manager group and add Ellen Wright entity as a member
$ vault write identity/group name="acct_manager" \
policies="acct_manager" \
member_entity_ids=$(cat entity_id_ellen.txt)
Web UI
-
Click the Access tab, and select Enable new method.
-
Select Username & Password from the Type drop-down menu.
-
Click Enable Method.
-
Click the Vault CLI shell icon (
>_
) to open a command shell. Enter the following command to create a new user,bob
:$ vault write auth/userpass/users/bob password="training"
-
Enter the following command to create a new user,
ellen
:$ vault write auth/userpass/users/ellen password="training"
-
Click the icon (
>_
) again to hide the shell. -
From the Access tab, select Entities and then Create entity.
-
Populate the Name, Policies and Metadata fields as shown below.
-
Click Create.
-
Select Add alias. Enter
bob
in the Name field and selectuserpass/ (userpass)
from the Auth Backend drop-down list. -
Return to the Entities tab and then Create entity.
-
Populate the Name, Policies and Metadata fields as shown below.
-
Click Create.
-
Select Add alias. Enter
ellen
in the Name field and selectuserpass/ (userpass)
from the Auth Backend drop-down list. -
Click Create.
-
Select the
Ellen Wright
entity and copy its ID displayed under the Details tab. -
Click Groups from the left navigation, and select Create group.
-
Enter
acct_manager
in the Name, and again enteracct_manager
in the Policies fields. -
Enter the
Ellen Wright
entity ID in the Member Entity IDs field, and then click Create.
Step 4: Verification
(Persona: bob and ellen)
Now, let's see how the control group works.
CLI Command
-
Log in as
bob
.$ vault login -method=userpass username="bob" password="training"
-
Request to read "
EU_GDPR_data/orders/acct1
":$ vault kv get EU_GDPR_data/orders/acct1 Key Value --- ----- wrapping_token: 1f1411bc-2f18-551a-5e58-0fe44432e9a5 wrapping_accessor: bbb4deef-e06d-9b2a-64a9-56f815c69ee7 wrapping_token_ttl: 24h wrapping_token_creation_time: 2018-08-08 09:36:32 -0700 PDT wrapping_token_creation_path: EU_GDPR_data/orders/acct1
The response includes
wrapping_token
andwrapping_accessor
. Copy thiswrapping_accessor
value. -
Now, a member of
acct_manager
must approve this request. Log in asellen
who is a member ofacct_manager
group.$ vault login -method=userpass username="ellen" password="training"
-
As a user,
ellen
, you can check and authorize bob's request using the following commands.# To check the current status $ vault write sys/control-group/request accessor=<wrapping_accessor> # To approve the request $ vault write sys/control-group/authorize accessor=<wrapping_accessor>
Example:
# Check the current status $ vault write sys/control-group/request accessor=bbb4deef-e06d-9b2a-64a9-56f815c69ee7 Key Value --- ----- approved false authorizations <nil> request_entity map[name:Bob Smith id:38700386-723d-3d65-43b7-4fb44d7e6c30] request_path EU_GDPR_data/orders/acct1 # Approve the request $ vault write sys/control-group/authorize accessor=bbb4deef-e06d-9b2a-64a9-56f815c69ee7 Key Value --- ----- approved true
Now, the
approved
status istrue
. -
Since the control group requires one approval from a member of
acct_manager
group, the condition has been met. Log back in asbob
and unwrap the secret.Example:
# Log back in as bob - you can use the bob's token: vault login <bob_token> $ vault login -method=userpass username="bob" password="training" # Unwrap the secrets by passing the wrapping_token $ vault unwrap 1f1411bc-2f18-551a-5e58-0fe44432e9a5 Key Value --- ----- refresh_interval 768h order_number 12345678 product_id 987654321
API call using cURL
-
Log in as
bob
.$ curl --request POST \ --data '{"password": "training"}' \ http://127.0.0.1:8200/v1/auth/userpass/login/bob | jq
Copy the generated
client_token
value. -
Request to
EU_GDPR_data/orders/acct1
:$ curl --header "X-Vault-Token: <bob_client_token>" \ http://127.0.0.1:8200/v1/EU_GDPR_data/orders/acct1 | jq { ... "wrap_info": { "token": "20a2f2b3-8bea-4e16-980b-82724dcdc38b", "accessor": "9910cb38-600c-29d8-1c39-764a1c89a481", "ttl": 86400, "creation_time": "2018-08-08T10:13:06-07:00", "creation_path": "EU_GDPR_data/orders/acct1" }, ... }
The response includes
wrap_info
instead of the actual data. Copy theaccessor
value. -
Now, a member of
acct_manager
must approve this request. Log in asellen
who is a member ofacct_manager
group.$ curl --request POST \ --data '{"password": "training"}' \ http://127.0.0.1:8200/v1/auth/userpass/login/ellen | jq
Copy the generated
client_token
value. -
As a user,
ellen
, you can check the current status and then authorize bob's request. (NOTE: Be sure to replace<accessor>
with theaccessor
value you copied earlier.)# To check the current status using sys/control-group/request endpoint $ curl --header "X-Vault-Token: <ellen_client_token>" \ --request POST \ --data '{"accessor": "<accessor>"}' \ http://127.0.0.1:8200/v1/sys/control-group/request | jq { ... "data": { "approved": false, "authorizations": null, "request_entity": { "id": "38700386-723d-3d65-43b7-4fb44d7e6c30", "name": "Bob Smith" }, "request_path": "EU_GDPR_data/orders/acct1" }, ... } # Now, authorize the request using sys/control-group/authorize endpoint $ curl --header "X-Vault-Token: <ellen_client_token>" \ --request POST \ --data '{"accessor": "<accessor>"}' \ http://127.0.0.1:8200/v1/sys/control-group/authorize | jq { ... "data": { "approved": true }, ... }
Now, the
approved
status istrue
. -
The
bob
user should be able to unwrap the secrets.$ curl --header "X-Vault-Token: <bob_client_token>" \ --request POST \ --data '{"token": "<wrapping_token>"}' \ http://127.0.0.1:8200/v1/sys/wrapping/unwrap | jq { ... "data": { "order_number": "12345678", "product_id": "987654321" }, ... }
Web UI
The user, ellen
can approve the data access request via UI.
-
Open the Vault sign in page in a web browser (e.g. http://127.0.0.1:8200/ui/vault/auth?with=userpass). In the Userpass tab, enter
ellen
in the Username field, andtraining
in the Password field. -
Click Sign in.
-
Select the Access tab, and then Control Groups.
-
Enter the
wrapping_accessor
value in the Accessor field and click Lookup. -
Click Authorize. The message changes to "Thanks! You have given authorization."
Bob needs to request data access via CLI or API. Once the access request was approved, use the CLI or API to unwrap the secrets.
Step 5: ACL Policy vs. Sentinel Policy
Although the read-gdpr-order.hcl
was written as ACL policy, you
can implement Control Groups in either ACL or Sentinel policies.
Using Sentinel, the same policy may look something like:
import "controlgroup"
control_group = func() {
numAuthzs = 0
for controlgroup.authorizations as authz {
if "acct_manager" in authz.groups.by_name {
numAuthzs = numAuthzs + 1
}
}
if numAuthzs >= 1 {
return true
}
return false
}
main = rule {
control_group()
}
Deploy this policy as an Endpoint Governing Policy attached to
"EU_GDPR_data/orders/*
" path.
-> Refer to the Sentinel Properties documentation for the list of available properties associated with control groups.
Next steps
To protect your secrets, it may become necessary to write finer-grained policies to introspect different aspects of incoming requests. If you have not already done so, read Sentinel documentation to learn more about what you can accomplish writing policies as a code.