Enforce access control with Sentinel policies
Enterprise Only
Sentinel requires Vault Enterprise license or an HCP Vault Plus tier cluster.
Challenge
ACL policies are path-based and present the following challenges:
- Cannot grant permissions based on logic other than paths
- Paths are merged in ACL policies which could potentially cause a conflict as the number of policies grows
What if the policy requirement was to grant read permission on secret/orders
path only if the request came from an IP address within a certain CIDR?
Solution
Use Sentinel Role Governing Policies (RGPs) and Endpoint Governing Policies (EGPs) to fulfill more complex policy requirements.
Sentinel can access properties of the incoming requests and make a decision based on a certain set of conditions. Available properties include:
- request - Information about the request itself (path, operation type, parameters, etc.)
- token - Information about the token being used (creation time, attached policies, etc.)
- identity - Identity entities and all related data
- mfa - Information about successful MFA validations
Sentinel is a language framework for policies built to be embedded in Vault Enterprise to enable fine-grained, logic-based policy decisions which cannot be fully handled by the ACL policies.
EGPs and RGPs can be defined using Sentinel:
- EGPs are tied to particular paths (e.g.
aws/creds/
) - RGPs are tied to particular tokens, identity entities, or identity groups
Note
This tutorial walks you through the authoring of Endpoint Governing Policies (EGPs) and Role Governing Policies (RGPs). For ACL policy authoring, refer to the Policies tutorial.
Personas
Sentinel policies provide a declarative way to grant or forbid access to certain paths and operations in Vault. Therefore, the steps described in this tutorial are performed by Vault admins or security operations.
Prerequisites
To perform the tasks described in this tutorial, you need to have:
- Vault Enterprise binary and license key or HCP Vault Dedicated Plus tier cluster available.
- jq binary installed in your system PATH.
- Git binary installed in your system PATH.
Policy requirements
Since this tutorial demonstrates the creation of policies, log in with highly
privileged token such as root
.
The specific required policy capabilities are as follows.
# To list policiespath "sys/policies/*"{ capabilities = ["list"]} # Create and manage EGPspath "sys/policies/egp/*"{ capabilities = ["create", "read", "update", "delete", "list"]} # Create and manage RGPspath "sys/policies/rgp/*"{ capabilities = ["create", "read", "update", "delete", "list"]}
Lab setup
Note
If you do not have access to an HCP Vault Dedicated cluster, visit the Create a Vault Cluster on HCP tutorial.
Launch the HCP Portal and login.
Click Vault in the left navigation pane.
In the Vault clusters pane, click vault-cluster.
Under Cluster URLs, click Public Cluster URL.
In a terminal, set the
VAULT_ADDR
environment variable to the copied address.$ export VAULT_ADDR=<Public_Cluster_URL>
Return to the Overview page and click Generate token.
Within a few moments, a new token will be generated.
Copy the Admin Token.
Return to the terminal and set the
VAULT_TOKEN
environment variable.$ export VAULT_TOKEN=<token>
Set the
VAULT_NAMESPACE
environment variable toadmin
.$ export VAULT_NAMESPACE=admin
Type
vault status
to verify your connectivity to the Vault cluster.$ vault status Key Value--- -----Recovery Seal Type shamirInitialized trueSealed falseTotal Recovery Shares 1Threshold 1Version 1.9.2+entStorage Type raft...snipped...
Enable the KV secrets engine setting the path to
secret
.$ vault secrets enable -path=secret -version=2 kv Success! Enabled the kv secrets engine at: secret/
The Vault Dedicated server is ready.
Write Sentinel policies
Anatomy of a Sentinel policy
import "<library>"<variable> = <value>main = rule { <conditions_to_evaluate>}
import
- Enables your policy to access reusable libraries. There are a set of built-in imports available to help define your policy rules.main
(required) - Every Sentinel policy must have amain
rule which is evaluated to determine the result of a policy.rule
- A first-class construct in Sentinel. It describes a set of conditions resulting in either true or false. Refer to the Boolean Expressions for the full list of available operators in writing rules.<variable>
- Variables are dynamically typed in Sentinel. You can define its value explicitly or implicitly by the host system or function.
Note
The Sentinel language supports many features such as functions, loops, slices, etc. You can learn about all of this in the Sentinel Language documentation.
Endpoint governing policies (EGPs)
Write endpoint governing policies (EGPs) that fulfill the following requirements:
Any incoming request against the "
kv-v2/*
" to be performed during the business hours (7:00 am to 6:00 pm during the work days).business-hrs.sentinel
$ tee business-hrs.sentinel <<EOFimport "time" # Expect requests to only happen during work days (Monday through Friday)# 0 for Sunday and 6 for Saturdayworkdays = rule { time.now.weekday > 0 and time.now.weekday < 6} # Expect requests to only happen during work hours (7:00 am - 6:00 pm)workhours = rule { time.now.hour > 7 and time.now.hour < 18} main = rule { workdays and workhours}EOF
Any
create
,update
anddelete
operations against Key/Value secret engine (mounted at "secret
") must come from an internal IP of122.22.3.4/32
CIDR.The
main
has conditional rule (when precond
) to ensure that the rule gets evaluated only if the request is relevant.cidr-check.sentinel
$ tee cidr-check.sentinel <<EOFimport "sockaddr"import "strings" # Only care about create, update, and delete operations against secret pathprecond = rule { request.operation in ["create", "update", "delete"] and strings.has_prefix(request.path, "secret/")} # Requests to come only from our private IP rangecidrcheck = rule { sockaddr.is_contained(request.connection.remote_addr, "122.22.3.4/32")} # Check the precondition before execute the cidrcheckmain = rule when precond { cidrcheck}EOF
Note
Refer to the Sentinel Properties documentation for available properties which Vault injects to Sentinel to allow fine-grained controls.
Simulate Sentinel policies
You can test the Sentinel policies prior to deployment in order to validate syntax and to document expected behavior.
Download the Sentinel simulator for your platform.
Example for MacOS:
$ wget https://releases.hashicorp.com/sentinel/0.18.11/sentinel_0.18.11_darwin_amd64.zip
Unzip the downloaded file.
$ unzip sentinel_0.18.11_darwin_amd64.zip -d /usr/local/bin
Write the test cases
Note
You can follow the instructions to write the test files, or
clone the
learn-vault-sentinel
repository which includes the test files.
$ git clone https://github.com/hashicorp-education/learn-vault-sentinel.git
Change the working directory to where the policy is located.
$ cd learn-vault-sentinel/sentinel
Create a sub-folder named
test
wherecidr-check.sentinel
andbusiness-hrs.sentinel
policies are located.Under the
test
folder, create a sub-folder forcidr-check
.$ mkdir -p test/cidr-check
Create a sub-folder for
business-hrs
under thetest
directory.$ mkdir -p test/business-hrs
Note
The test should be created under
/test/<policy_name>
folder.Write a passing test case in a file named
success.json
undertest/business-hrs
directory.test/business-hrs/success.json
$ tee test/business-hrs/success.json <<EOF{ "mock": { "time": { "now": { "weekday": 1, "hour": 12 } } }, "test": { "main": true }}EOF
Under
mock
, you specify the mock test data. In this example, theweekday
is set to1
which isMonday
andhour
is set to12
which isnoon
. Therefore themain
should returntrue
.Write a failing test in a file named
fail.json
undertest/business-hrs
.test/business-hrs/fail.json
$ tee test/business-hrs/fail.json <<EOF{ "mock": { "time": { "now": { "weekday": 0, "hour": 12 } } }, "test": { "main": false }}EOF
The mock data is set to
Sunday
atnoon
; therefore Therefore, themain
should returnfalse
.Similarly, write a passing test case for
cidr-check
policy,test/cidr-check/success.json
.test/cidr-check/success.json
$ tee test/cidr-check/success.json <<EOF{ "global": { "request": { "connection": { "remote_addr": "122.22.3.4" }, "operation": "create", "path": "secret/orders" } }}EOF
In this example, the
global
specifies thecreate
operation is invoked onsecret/orders
endpoint which initiated from an IP address122.22.3.4
. Therefore themain
should returntrue
.Write a failing test for
cidr-check
policy,test/cidr-check/fail.json
.test/cidr-check/fail.json
$ tee test/cidr-check/fail.json <<EOF{ "global": { "request": { "connection": { "remote_addr": "122.22.3.10" }, "operation": "create", "path": "secret/orders" } }, "test": { "precond": true, "main": false }}EOF
This test will fail because of the IP address mismatch. However, the
precond
should pass since the requested operation iscreate
and the targeted endpoint issecret/orders
.The optional
test
definition adds more context to why the test should fail. The expected behavior is that the test fails becausemain
returnsfalse
butprecond
should returntrue
.Now, you have written both success and failure tests.
├── business-hrs.sentinel├── cidr-check.sentinel└── test ├── business-hrs │ ├── fail.json │ └── success.json └── cidr-check ├── fail.json └── success.json
Execute the test.
$ sentinel test
Successful output:
PASS - business-hrs.sentinelPASS - test/business-hrs/fail.jsonPASS - test/business-hrs/success.jsonPASS - cidr-check.sentinelPASS - test/cidr-check/fail.jsonPASS - test/cidr-check/success.json
Note
If you want to see the tracing and log output for those tests, run the command with
-verbose
flag.
Deploy EGP policies
Sentinel policies have three enforcement levels:
Level | Description |
---|---|
advisory | The policy is allowed to fail. Can be used as a tool to educate new users. |
soft-mandatory | The policy must pass unless an override is specified. |
hard-mandatory | The policy must pass. |
Since both policies are tied to specific paths, the policy type that you are going to create is Endpoint Governing Policies (EGPs).
Store the Base64 encoded
cidr-check.sentinel
policy in an environment variable namedPOLICY
.$ POLICY=$(base64 -i cidr-check.sentinel)
Create a policy
cidr-check
with enforcement level of hard-mandatory to reject all requests coming from IP addressed that are not internal.$ vault write sys/policies/egp/cidr-check \ policy="${POLICY}" \ paths="secret/*" \ enforcement_level="hard-mandatory"
You can read the policy by executing the following command:
$ vault read sys/policies/egp/cidr-check
Successful output:
Key Value--- -----enforcement_level hard-mandatoryname cidr-checkpaths [secret/*]policy import "sockaddr"import "strings"# Only care about create, update, and delete operations against secret pathprecond = rule { request.operation in ["create", "update", "delete"] and strings.has_prefix(request.path, "secret/")}# Requests to come only from our private IP rangecidrcheck = rule { sockaddr.is_contained(request.connection.remote_addr, "122.22.3.4/32")}# Check the precondition before execute the cidrcheckmain = rule when precond { cidrcheck}
Repeat the steps to create a policy named
business-hrs
. First, encode thebusiness-hrs
policy.$ POLICY2=$(base64 -i business-hrs.sentinel)
Create a policy with soft-mandatory enforcement-level.
$ vault write sys/policies/egp/business-hrs \ policy="${POLICY2}" \ paths="kv-v2/*" \ enforcement_level="soft-mandatory"
To read the policy you just created, execute the following command.
$ vault read sys/policies/egp/business-hrs
Successful output:
Key Value--- -----enforcement_level soft-mandatoryname business-hrspaths [kv-v2/*]policy import "time"# Expect requests to only happen during work days (Monday through Friday)# 0 for Sunday and 6 for Saturdayworkdays = rule { time.now.weekday > 0 and time.now.weekday < 6}# Expect requests to only happen during work hours (7:00 am - 6:00 pm)workhours = rule { time.now.hour > 7 and time.now.hour < 18}main = rule { workdays and workhours}
Verification
Note
As with ACL policies, root
tokens are NOT subject to Sentinel policy
checks. Therefore, use a non-root token for verification test. For HCP Vault Dedicated,
the admin
token is subjet to Sentinel policy checks.
Create a
tester
policy which allows to operates on thesecret/*
path.$ vault policy write tester -<<EOFpath "secret/*" { capabilities = ["create", "read", "update", "delete", "list"]} path "kv-v2/*" { capabilities = ["create", "read", "update", "delete", "list"]}EOF
Create a token with the tester policy attached, and store the token in a
TEST_TOKEN
environment variable.$ export TEST_TOKEN=$(vault token create -policy="tester" -field=token) \ && echo $TEST_TOKEN
Example output:
hvs.CAESIHyhJlnhp1CJ7GoFTTl4ubjOe5nNB0oTIvuAC7mPL5K9Gh4KHGh2cy5DbFQwVVB6S2szaGxscm40cEpUMFZXQmw
Test the
cidr-check
EGP by sending request from an IP address other than122.22.3.4
will be denied.$ VAULT_TOKEN=$TEST_TOKEN \ vault kv put secret/accounting/test acct_no="29347230942"
Expected failure output:
Error writing data to secret/accounting/test: Error making API request.URL: PUT https://127.0.0.1:8200/v1/secret/accounting/testCode: 403. Errors:* 2 errors occurred:* egp standard policy "root/cidr-check" evaluation resulted in denial.The specific error was:<nil>A trace of the execution for policy "root/cidr-check" is available:Result: falseDescription: Check the precondition before execute the cidrcheckRule "main" (byte offset 442) = falsefalse (offset 314): sockaddr.is_contained(request.connection.remote_addr, "122.22.3.4/32")Rule "cidrcheck" (byte offset 291) = falseRule "precond" (byte offset 113) = truetrue (offset 134): request.operation in ["create", "update", "delete"]true (offset 194): strings.has_prefix(request.path, "secret/")* permission denied
Similarly, you will get an error if any request is made outside of the business
hours defined by the business-hrs
policy. However, the enforcement level set
on the business-hrs
policy is soft-mandatory, so it can be overridden.
Enable KV v2 secrets engine at
kv-v2
.$ vault secrets enable kv-v2
Send some test data.
$ VAULT_TOKEN=$TEST_TOKEN \ vault kv put kv-v2/test id="29347230942"
If the current time is outside of the business hours checked by the
business-hrs
policy, the request fails.Example output:
Error writing data to kv-v2/data/test: Error making API request.URL: PUT http://127.0.0.1:8200/v1/kv-v2/data/testCode: 403. Errors:* 2 errors occurred: * egp standard policy "root/business-hrs" evaluation resulted in denial.The specific error was:<nil>A trace of the execution for policy "root/business-hrs" is available:Result: falseDescription: <none>Rule "main" (root/business-hrs:14:1) = falseRule "workdays" (root/business-hrs:5:1) = trueRule "workhours" (root/business-hrs:10:1) = falseNote: specifying an override of the operation would have succeeded. * permission denied
Run the command again using the policy override flag (
-policy-override
).$ VAULT_TOKEN=$TEST_TOKEN \ vault kv put -policy-override kv-v2/test id="29347230942"
Because the policy enforcement level is set to soft-mandatory, the request completes successfully.
= Secret Path =kv-v2/data/test======= Metadata =======Key Value--- -----created_time 2023-08-11T23:16:55.485525Zcustom_metadata <nil>deletion_time n/adestroyed falseversion 1
Tip
If you are connecting with Vault through API, set
X-Vault-Policy-Override: true
in the request header.
Role governing policies (RGPs)
RGPs are tied to client tokens or identities which is similar to ACL policies. Vault server evaluates the RGP attached to the token to determine whether to accept or reject the request.
Scenario introduction
To demonstrate the use of RGP, you are going to create the following:
- Create ACL policies:
secrets
andadmin
, andsysops
- Enable a userpass auth method at
userpass-test/
and create a userjames
andbob
- Create an entity named
James Thomas
- Create an entity named
Bob Smith
- Create a RGP policy named
test-rgp
- Create a group named
sysops
withJames Thomas
andBob Smith
entities as its members - Attach
sysops
andtest-rgp
policies to the group
The sysops
group has the sysops
policy attached which grants permission to
manage all policies. All group members inherit the group-level policies. (If
you are not familiar with Vault Identities, refer to the Identity: Entities and
Groups tutorial.)
Use the role governing policy to restrict access to the admin
policy such that
James or a user with the Team Lead
role can manage the admin
policy. Other group
members can manage all other policies but not the admin
policy.
Create the demo resources
Prerequisite
You are going to run a script which uses jq
to parse JSON
outputs. Install jq if you don't have it.
Clone the
learn-vault-sentinel
repository.$ git clone https://github.com/hashicorp-education/learn-vault-sentinel.git
Change the working directory to
learn-vault-sentinel
.$ cd learn-vault-sentinel
Make sure that the
identity-setup.sh
file is executable.$ chmod +x identity-setup.sh
vault policy write secrets -<<EOFpath "secret/*" { capabilities = [ "create", "read", "update", "delete" ]}EOF vault policy write admin -<<EOFpath "auth/*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}EOF vault policy write sysops -<<EOFpath "sys/*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}EOF vault auth enable -path="userpass-test" userpassvault write auth/userpass-test/users/james password="training" policies="secrets"vault write auth/userpass-test/users/bob password="training" policies="secrets"vault auth list -format=json | jq -r '.["userpass-test/"].accessor' > accessor_test.txt # Create 'James Thomas' entityvault write -format=json identity/entity name="James Thomas" policies="admin" \ metadata=role="Team Lead" \ | jq -r ".data.id" > entity_id_james.txt vault write identity/entity-alias name="james" \ canonical_id=$(cat entity_id_james.txt) \ mount_accessor=$(cat accessor_test.txt) # Create Bob Smith entityvault write -format=json identity/entity name="Bob Smith" policies="admin" \ metadata=role="Kubernetes Expert" \ | jq -r ".data.id" > entity_id_bob.txt vault write identity/entity-alias name="bob" \ canonical_id=$(cat entity_id_bob.txt) \ mount_accessor=$(cat accessor_test.txt) # Add an RGP policycat <<EOF | base64 | vault write sys/policies/rgp/test-rgp policy=- enforcement_level="hard-mandatory"import "strings" precond = rule { strings.has_prefix(request.path, "sys/policies/acl/admin")} main = rule when precond { identity.entity.metadata.role is "Team Lead" or identity.entity.name is "James Thomas"}EOF # Create 'sysops' groupvault write -format=json identity/group name="sysops" \ policies="sysops, test-rgp" \ member_entity_ids="$(cat entity_id_james.txt), $(cat entity_id_bob.txt)" \ | jq -r ".data.id" > group_id_sysops.txt
Notice that the
test-rgp
RGP policy is attached to thesysops
group (line 58).Run the
identity-setup.sh
script.$ ./identity-setup.sh Success! Uploaded policy: secretsSuccess! Uploaded policy: adminSuccess! Uploaded policy: sysopsSuccess! Enabled userpass auth method at: userpass-test/Success! Data written to: auth/userpass-test/users/jamesSuccess! Data written to: auth/userpass-test/users/bobKey Value--- -----canonical_id 07f6868e-8a87-5141-1828-93097f59f424id 55972826-f3c8-2601-3acf-6568273672e2Key Value--- -----canonical_id 73decd4f-ae4c-1dc1-a1a9-a74068ef42c4id 20e36023-c181-cbbf-f225-df9592797f56Success! Data written to: sys/policies/rgp/test-rgp
Review the created identities and policies
Examine the
test-rgp
policy.$ vault policy read test-rgp
Output:
import "strings" precond = rule { strings.has_prefix(request.path, "sys/policies/acl/admin")} main = rule when precond { identity.entity.metadata.role is "Team Lead" or identity.entity.name is "James Thomas"}
The
precond
checks the incoming request endpoint. If the request is targeted tosys/policies/acl/admin
, Vault checks to see if the request was made by an entity named, James Thomas or has Team Lead role defined as its metadata. Refer to the Entity Properties documentation for the list of available properties.Review the James Thomas entity details. The entity ID is stored in the
entity_id_james.txt
file by the script.$ vault read identity/entity/id/$(cat entity_id_james.txt)
Example output:
James Thomas entity has Team Lead role defined in its metadata.
Key Value--- -----aliases [map[canonical_id:5e8cba9e-b663-97e9-5e1f-b68248e53534 creation_time:2022-09-14T01:34:53.174277Z custom_metadata:map[] id:857fedd9-038b-8c16-ddff-3b891336699b last_update_time:2022-09-14T01:34:53.174277Z local:false merged_from_canonical_ids:<nil> metadata:<nil> mount_accessor:auth_userpass_fb364660 mount_path:auth/userpass-test/ mount_type:userpass name:james]]creation_time 2022-09-14T01:34:53.081739Zdirect_group_ids [87d8a8df-cfac-f6be-0ee7-bcf227ab098b]disabled falsegroup_ids [87d8a8df-cfac-f6be-0ee7-bcf227ab098b]id 5e8cba9e-b663-97e9-5e1f-b68248e53534inherited_group_ids []last_update_time 2022-09-14T01:34:53.081739Zmerged_entity_ids <nil>metadata map[role:Team Lead]mfa_secrets map[]name James Thomasnamespace_id rootpolicies [admin]
Review the Bob Smith entity details. The entity ID is stored in
entity_id_bob.txt
.$ vault read identity/entity/id/$(cat entity_id_bob.txt)
Example output:
Bob's functional role is Kubernetes expert.
Key Value--- -----aliases [map[canonical_id:83e66ad6-e6ee-d6ed-8063-e88d90dd4de3 creation_time:2022-09-14T23:30:46.079077Z custom_metadata:map[] id:437cc7a4-2e6d-3b2b-0bd6-d0f57c8e3644 last_update_time:2022-09-14T23:30:46.079077Z local:false merged_from_canonical_ids:<nil> metadata:<nil> mount_accessor:auth_userpass_427c2404 mount_path:auth/userpass-test/ mount_type:userpass name:bob]]creation_time 2022-09-14T23:30:45.958557Zdirect_group_ids [2652cb82-c798-3a42-1fc7-9c4005190ec5]disabled falsegroup_ids [2652cb82-c798-3a42-1fc7-9c4005190ec5]id 83e66ad6-e6ee-d6ed-8063-e88d90dd4de3inherited_group_ids []last_update_time 2022-09-14T23:30:45.958557Zmerged_entity_ids <nil>metadata map[role:Kubernetes Expert]mfa_secrets map[]name Bob Smithnamespace_id rootpolicies [admin]
Verification
Login as
james
and store the generated token injames_token.txt
$ vault login -method=userpass -path=userpass-test -field=token \ username=james password=training > james_token.txt
Read the
admin
policy.$ VAULT_TOKEN=$(cat james_token.txt) vault policy read admin path "auth/*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}
The command successfully returns the policy.
Login as
bob
and store the generated token inbob_token.txt
$ vault login -method=userpass -path=userpass-test -field=token \ username=bob password=training > bob_token.txt
Try to read the
admin
policy.$ VAULT_TOKEN=$(cat bob_token.txt) vault policy read admin
Output:
Error reading policy named admin: Error making API request.URL: GET http://127.0.0.1:8200/v1/sys/policies/acl/adminCode: 403. Errors:* 2 errors occurred: * rgp standard policy "root/test-rgp" evaluation resulted in denial.The specific error was:<nil>A trace of the execution for policy "root/test-rgp" is available:Result: falseDescription: <none>Rule "main" (root/test-rgp:7:1) = falseRule "precond" (root/test-rgp:3:1) = true * permission denied
Neither the Bob's entity metadata or the name matched that the main rule returned false. Therefore, the request was denied.
Read the token details.
$ VAULT_TOKEN=$(cat bob_token.txt) vault token lookup Key Value--- -----accessor NfBU02DcEAVSJACJUkVmpOnKcreation_time 1663124784creation_ttl 768hdisplay_name userpass-test-bobentity_id 6090ff87-e3d8-09f1-b8d8-94ec9a7bb05bexpire_time 2022-10-15T20:06:24.77325-07:00explicit_max_ttl 0sexternal_namespace_policies map[]id hvs.CAESIEZ4R6stpJNirlgggzY0SknVO9YkFbUZ8OoUsuV32tL7Gh4KHGh2cy5Bc2NYaXVOQzJVemJTRjFzU1U2d0c2bjAidentity_policies [admin sysops test-rgp]issue_time 2022-09-13T20:06:24.773255-07:00meta map[username:bob]num_uses 0orphan truepath auth/userpass-test/login/bobpolicies [default secrets]renewable truettl 767h44m29stype service
The token details shows
admin
,sysops
andtest-rgp
policies listed asidentity_policies
. Although thesysops
policy permits access to thesys/*
path, thetest-rgp
does not permit to read theadmin
policy unless the entity's name is "James Thomas" or has "Team Lead" defined in the entity metadata.To verify, read the
sysops
policy with Bob's token.$ VAULT_TOKEN=$(cat bob_token.txt) vault policy read sysops path "sys/*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}
Bob can access other policies.
Challenge question
What can you do to allow Bob Smith to access the admin
policy?
One of the solutions is to change Bob's entity metadata to contain Team Lead
.
$ vault write identity/entity/id/$(cat entity_id_bob.txt) metadata=role="Team Lead"
Another possible solution is to update the test-rgp
policy to check for Bob
Smith
entity name.
test-rgp
import "strings" precond = rule { strings.has_prefix(request.path, "sys/policies/acl/admin")} main = rule when precond { identity.entity.metadata.role is "Team Lead" or identity.entity.name is "James Thomas" or identity.entity.name is "Bob Smith"}
Now, Bob should be able to read the admin
policy.
$ VAULT_TOKEN=$(cat bob_token.txt) vault policy read admin path "auth/*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}
Clean up
If you wish to clean up your environment after completing the tutorial, follow the steps in this section.
Delete the
business-hrs
policy.$ vault policy delete business-hrs
Delete the
cidr-check
policy.$ vault policy delete cidr-check
Delete the Sentinel test directory.
$ rm -r test
Unset the
VAULT_TOKEN
environment variable.$ unset VAULT_TOKEN
Unset the
VAULT_ADDR
environment variable.$ unset VAULT_ADDR
If you completed the Role Governing Policies (RGPs) section, run the
clean-up.sh
script provided by thelearn-vault-sentinel
repository.$ ./clean-up.sh
If you are running Vault locally in
-dev
mode, you can stop the Vault dev server by pressing Ctrl+C where the server is running. Or, execute the following command.$ pgrep -f vault | xargs kill
Summary
You learned the basics of endpoint governing policies (EGPs) and role governing policies (RGPs). To learn more about Sentinel policies in Vault, continue onto the following tutorials:
Help and reference
- Sentinel documentation
- Vault Sentinel documentation
- Security and Fundamentals at Scale with Vault
- Identity - Entities and Groups tutorial
- Sentinel Properties