Enterprise Only: Control Groups requires Vault Enterprise with the Governance & Policy Module.
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.
»Personas
The end-to-end scenario described in this tutorial 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/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 tutorial, you need to have a Vault Enterprise environment.
NOTE: To explore Vault Enterprise features, you can sign up for a free 30-day trial from here.
This tutorial 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 tutorial demonstrates the creation of policies, log in with a highly
privileged token such as root
. Otherwise, required permissions to perform the
steps in this tutorial are.
# Create and manage ACL policies
path "sys/policies/acl/*"
{
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# To enable secrets 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" ]
}
»Scenario Introduction
The scenario in this tutorial is that a user, Bob Smith
has
read-only permission on the "EU_GDPR_data/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
Author a policy named read-gdpr-order.hcl
.
Bob needs read
permissions on EU_GDPR_data/data/orders/*
.
path "EU_GDPR_data/data/orders/*" {
capabilities = [ "read" ]
}
Now, add control group to this policy:
path "EU_GDPR_data/data/orders/*" {
capabilities = [ "read" ]
control_group = {
factor "authorizer" {
identity {
group_names = [ "acct_manager" ]
approvals = 1
}
}
}
}
For the purpose of this tutorial, the number of approvals
is set to
1
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 named
acct_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 have create
and update
permission on the
sys/control-group/authorize
endpoint so that they can approve the request.
»Step 2: Deploy the policies
Deploy the read-gdpr-order
and acct_manager
policies that you wrote.
Create a new policy named read-gdpr-order
.
$ vault policy write read-gdpr-order read-gdpr-order.hcl
Create a new policy named acct_manager
.
$ vault policy write acct_manager acct_manager.hcl
»Step 3: Setup entities and a group
This step only demonstrates CLI commands and Web UI to create entities and groups. Refer to the Identity - Entities and Groups tutorial 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 tutorial, use the userpass
auth method to
create user bob
and ellen
so that the scenario can be easily tested.
The following command uses jq
tool
to parse JSON output.
Enable the
userpass
auth method.$ vault auth enable userpass
Create a new user,
bob
with password, "training".$ vault write auth/userpass/users/bob password="training"
Create a new user,
ellen
with password, "training".$ 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 theentity_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 theentity_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 addEllen Wright
entity as a member.$ vault write identity/group name="acct_manager" \ policies="acct_manager" \ member_entity_ids=$(cat entity_id_ellen.txt)
»Step 4: Verification
Now, let's see how the control group works.
First, enable the key/value secrets engine at
EU_GDPR_data
.$ vault secrets enable -path=EU_GDPR_data -version=2 kv
Write some mock data.
$ vault kv put EU_GDPR_data/orders/acct1 \ order_number="12345678" product_id="987654321"
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: s.h9jGEBexp0o7vQhmImZKAAKo wrapping_accessor: HDUlEfkrbrfPOlfUnwgar025 wrapping_token_ttl: 24h wrapping_token_creation_time: 2019-05-10 16:38:36 -0700 PDT wrapping_token_creation_path: EU_GDPR_data/data/orders/acct1
The response includes
wrapping_token
andwrapping_accessor
. Copy thiswrapping_accessor
value.NOTE: You will need this
wrapping_token
andwrapping_accessor
values.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=
To approve the request:
$ vault write sys/control-group/authorize accessor=
Example:
Check the current status.
$ vault write sys/control-group/request accessor=HDUlEfkrbrfPOlfUnwgar025 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=HDUlEfkrbrfPOlfUnwgar025 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 using 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 s.h9jGEBexp0o7vQhmImZKAAKo Key Value --- ----- refresh_interval 768h order_number 12345678 product_id 987654321
»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/data/orders/*
" path.
Refer to the Sentinel Properties documentation for the list of available properties associated with control groups.