Enterprise Only: Sentinel requires Vault Enterprise Plus license. To explore Vault Enterprise features, you can sign up for a free 30-day trial from here.
Sentinel is a language framework for policy built to be embedded in Vault Enterprise to enable fine-grained, logic-based policy decisions which cannot be fully handled by the ACL policies.
If you are not yet familiar with using Sentinel policies in Vault, review Sentinel Policies.
»Challenge
Sentinel Endpoint Governing Policies (EGP) are flexible and provide rich capabilities and rules to enable uses like Multi Factor Authentication requirements or even per path policy delegation, but what if your use case requires policy rules that are informed by consulting the output of an HTTP API?
»Solution
The Sentinel http import enables the use of HTTP-accessible data from outside the runtime in Sentinel policy rules. At a basic level, the import uses an HTTP GET request and by default, any request response that is not a successful "200 OK" HTTP response causes a policy error. This behavior can be further customized to your particular use case.
In this tutorial, you will learn how to configure Vault server to allow additional enabled modules, start a dev mode Vault server with the Sentinel HTTP import enabled. Then, you will write a Sentinel EGP that uses the HTTP import to query the Vault server API to determine information about enabled secrets engines, permitting or denying certain operations based on the specific criteria described later in the example. Finally, you'll write working tests for the EGP and test the EGP.
»Prerequisites
To perform the tasks exactly as described here, you need to have a macOS or Linux computer with a Vault Enterprise binary at version 1.5.0 or higher.
NOTE: To explore Vault Enterprise features, you can sign up for a free 30-day trial.
You should have familiarity with Vault and Sentinel, and be comfortable authoring and deploying a Sentinel EGP for Vault to follow along with the example presented here.
»Token policy requirements
This tutorial requires two Vault tokens- one for the Vault admin who will be creating and testing the Sentinel EGP, and one to use within the EGP itself.
You will use the initial root token to create these tokens.
»Vault user token policies
You need to authenticate to Vault with a token that has sufficient capabilities to follow the example workflow.
CAUTION: Do not use the initial root token for any purpose other than creating the required tokens, as root tokens are not subject to Sentinel policy enforcement and will cause issues with policy development and testing.
The specific required policy capabilities for the token used by the admin user are as follows.
»Sentinel EGP token policy
The Sentinel EGP example in this tutorial makes a call to the /sys/mounts API to determine which secrets engines are enabled.
This is an authenticated API endpoint, so the EGP itself needs its own Vault token with the minimum required ACL policy capability to read from /sys/mounts
.
That policy is as follows.
This token will be referred to as the EGP token going forward in the tutorial.
»Step 1: Configure Vault
Before you can use the Sentinel HTTP import module, you need to configure Vault and define additional enabled modules. This is done with the additional_enabled_modules parameter.
For this tutorial, you will use a Vault server in dev mode and pass just the Sentinel specific configuration to it at runtime from the configuration file, vault-sentinel-configuration.hcl
.
Write the file out to the present working directory with this command.
»Step 2: Start a dev mode server
In the same terminal session where you created the configuration file, start the Vault dev mode server and pass the configuration file to the -config
flag like this.
Insecure operation: Do not run a Vault dev server in production. This approach is only used here to simplify the unsealing process for this demonstration.
»Step 3: Write ACL policies, create tokens and login
Let's write the two ACL policies and generate the tokens you will need, and then login to Vault with the admin token at this time.
Open a new terminal session or window in which to follow these steps, and export VAULT_ADDR
to properly address the dev mode server from this session.
Create the admin user policy.
Successful output example:
Create the EGP token policy.
Successful output example:
Next, create the tokens; typically tokens are issued from an enabled auth method, but to keep this tutorial brief, you can create them directly from the token store.
First, capture the admin user token value to the VAULT_ADMIN_TOKEN
environment variable.
You can run echo $VAULT_ADMIN_TOKEN
to see the environment variable value.
Then, capture the EGP token value to the VAULT_EGP_TOKEN
environment variable.
You can run echo $VAULT_EGP_TOKEN
to examine the environment variable value.
From here on out in this tutorial, you will use the admin token instead of the root token.
You can login with the admin token like this.
You are now ready to move on to writing, testing, and deploying the Sentinel EGP.
»Step 4: Write Sentinel EGP
After you configure Vault to allow additional Sentinel modules, create ACL policies and tokens, and login with the admin token, it is time to write the Sentinel EGP.
For this example, let's presume a simple scenario where the specific use case for Vault seeks to limit the number of Transit secrets engines that can be enabled at any one time to a single (1) instance.
Vault can limit the number of enabled secrets engines by leveraging Sentinel with the HTTP import to query its own API to determine the number of currently enabled secrets engines of a given type.
The Sentinel policy can then further choose to allow or deny enabling of new secrets engines based on the current count of enabled transit secrets engines.
»Example policy
Here is the example policy for review; details about the code follow.
Let's walk through the code to understand how this EGP works.
- The first two non-comment lines declare the http and json imports needed for making HTTP requests and processing JSON.
- Next, two param lines define parameter values for the Vault address and Vault token for the EGP itself. You should replace http://127.0.0.1:8200 with the address of your Vault server in the same URL format with port (ex. http://localhost:8200) and replace \$VAULT_EGP_TOKEN with the actual token value for your EGP token that you created in step 3.
- Then there are some print statements, useful for debugging as the information is only printed when the policy is violated and fails.
- The bulk of the EGP logic resides in a single function,
validate_transit_not_present()
. It makes the HTTP request to the Vault /sys/mounts API endpoint to query the state of enabled secrets engines by examining the type of each enabled engine. If one is discovered to have the type "transit", then the validated variable value will be returned as false, causing the main rule evaluation to fail, and permission to enable any additional transit secrets engines for a non-root token user will be denied. - Finally, the main rule sets some conditions for its evaluation based on request parameters; the request must be for the /sys/mounts path, it must be an update operation, and the data type for the operation needs to be transit. If the request matches these conditions, then
validate_transit_not_present
is called to determine if there is already an enabled transit secrets engine.
You can write transit-check.sentinel
for use with CLI commands to the present working directory with this command.
WARNING: If you will deploy the Sentinel EGP with the HTTP API or Web UI, you need to replace the $VAULT_EGP_TOKEN
value with that of your actual EGP token value prior to deploying the policy.
»Step 3: Test Sentinel EGP
You can test the Sentinel policy prior to deployment in order to validate syntax and to document expected behavior.
First, you need to download the Sentinel simulator.
Unzip the downloaded file.
Create a sub-folder named test
where the transit-check.sentinel
file is located.
Under the test
folder, create a sub-folder for transit-check
.
NOTE: The tests should be created under test/<policy_name>
folder.
Write a passing test case for the transit-check
policy, test/transit-check/success.json
.
This test will pass because it does not include an enabled transit secrets engine.
The optional test
definition adds more context to why the test should pass. The expected behavior is that the test passes because validate_transit_not_present
returns true
and main
returns true
.
Write a failing test for the transit-check
policy, test/transit-check/fail.json
.
This test will fail because it includes an enabled transit secrets engine.
The optional test
definition adds more context to why the test should fail. The expected behavior is that the test fails because validate_transit_not_present
returns false
and main
returns false
.
Now, you have written both success and failure tests.
Execute the test.
Successful output:
NOTE: If you want to see the tracing and log output for tests, run the command with a -verbose
flag.
»Step 6: Deploy Sentinel EGP
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 no matter what! |
Since this policy is tied to a specific path, the policy type that you are going to create is an Endpoint Governing Policy (EGP).
Ensure that you login with the admin token before completing these steps.
Store the Base64 encoded transit-check.sentinel
policy in an environment variable named POLICY
.
Create a policy transit-check
with enforcement level of hard-mandatory to reject all requests to secrets under the path kv/solar-sensitive
when UV index is 9 or higher.
You can read the policy by executing the following command:
Successful output:
»Verification
Once the policy is deployed, all operations which fail the policy rule assertions will be denied when the server determines that there is already a transit secrets engine enabled.
To confirm, first login with the admin token.
Now, enable one instance of the transit secrets engine.
Successful output example:
Then, attempt to enable another instance of the transit secrets engine at the path another-transit-secrets-engine.
Expected failure output:
You will note as previously mentioned, the debug print()
statement outputs are shown since the policy was violated.
Warning: As with ACL policies, root
tokens are NOT subject to
Sentinel policy checks. Therefore, use a non-root token for verification test.
»Step 7: Delete Sentinel Policy
To delete the transit-check
EGP, execute the following command.
Successful output example:
»Going even further with Vault Enterprise Namespaces
If you want to try a more advanced example involving the Vault Enterprise Namespaces feature, you can follow the guidance in Restrict Members of a Group with Sentinel to restrict the subgroups and entities of a group by requiring all subgroups and entities of a group to belong to the same namespace.
»Step 8: Cleanup
To clean up the example files and stop your Vault dev server follow these steps.
Remove the files.
Remove the Sentinel tests.
In the other terminal session where you started the Vault dev server, press CTRL+C to stop Vault.
»Troubleshooting
If you encounter an error such as this example while testing the EGP.
Note the Import "http" is not available portion of the error. This indicates that Vault is not configured to allow the HTTP import. Check the instructions in Step 1: Configure Vault and make sure you have configured and restarted your Vault.