Guide
Published8:00 AM UTC Feb 01, 2018
In this guide, we explain authentication—the Vault process in which a user or machine-supplied information is verified to create a token with pre-configured policy.
UPDATE: This guide from 2018 may have some outdated information. We recommend you first start with this continuously updated guide to Vault policies on HashiCorp Learn: Vault Policies
In Vault, you use policies to govern the behavior of clients and instrument Role-Based Access Control (RBAC) by specifying access privileges (authorization).
When you first initialize Vault, the root
policy gets created by default. The root
policy is a special policy that gives superuser access to everything in Vault. This allows the superuser to set up initial policies, tokens, etc.
In addition, there is another built-in policy,default
gets created. The default
policy is attached to all tokens and provides common permissions.
Everything in Vault is path based, and admins write policies to grant or forbid access to certain paths and operations in Vault. Vault operates on a secure by default standard, and as such as empty policy grants no permission in thesystem.
HashiCorp configuration language
Policies written in HCL format are often referred as ACL Policies. Sentinel is another framework for policy which is available in Vault Enterprise. Since Sentinel is an enterprise-only feature, this guide focuses on writing ACL policies as a foundation.
NOTE: HCL is JSON compatible; therefore, JSON can be used as completely valid input.
Reference Material
- Policies documentation
- Policy API documentation
- Getting Started guide on policies
Estimated time to completion
10 minutes
Personas
The scenario described in this guide introduces the following personas:
root
sets up initial policies foradmin
admin
is empowered with managing a Vault infrastructure for a team or organizationsprovisioner
configures secret backends and creates policies for client apps
Challenge
Since Vault centrally secures, stores, and controls access tp secrets across distributed infrastructure and applications, it is critical to control permissions before any user or machine can gain access.
Solution
Restrict the use of root policy, and write fine-grained policies to practice least privileged. For example, if an app gets AWS credentials from Vault, write policy grants to read
from AWS secret backend but not to delete
, etc.
Policies are attached to tokens and roles to enforce client permissions on Vault.
Prerequisities
To perform the tasks described in this guide, you need to have a Vault environment. Refer to the GettingStarted guide to install Vault. Make sure that your Vault server has been initialized and unsealed.
Policy Requirements
Since this guide demonstrates the creation of an admin
policy, log in withroot
token if possible. Otherwise, make sure that you have the followingpermissions:
# Manage auth backends broadly across Vaultpath "auth/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# List, create, update, and delete auth backendspath "sys/auth/*"{ capabilities = ["create", "read", "update", "delete", "sudo"]}# To list policies - Step 3path "sys/policy"{ capabilities = ["read"]}# Create and manage ACL policies broadly across Vaultpath "sys/policy/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# List, create, update, and delete key/value secretspath "secret/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# Manage and manage secret backends broadly across Vault.path "sys/mounts/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# Read health checkspath "sys/health"{ capabilities = ["read", "sudo"]}# To perform Step 4path "sys/capabilities"{ capabilities = ["create", "update"]}# To perform Step 4path "sys/capabilities-self"{ capabilities = ["create", "update"]}
Steps
AppRole is an authentication mechanism within Vault to allow machines or apps to acquire a token to interact with Vault. It uses Role ID and Secret ID for login.
The basic workflow is:

In this guide, you are going to perform the following steps:
- Enable AppRole auth backend
- Create a role with policy attached
- Get Role ID and Secret ID
- Read secrets using the AppRole token
Step 1 through 3 need to be performed by an admin
user. Step 4 and 5 describe the commands that an app
runs to get a token and read secrets from Vault.
The basic workflow of creating policies is:
This guide demonstrates basic policy authoring and management tasks.
- Write ACL policies in HCL format
- Create policies
- View existing policies
- Check capabilities of a token
Step 1: Write ACL policies in HCL format
Remember, empty policy grants no permission in the system. Therefore, ACLpolicies are defined for each path.
path "<PATH>" { capabilities = [ "<LIST_OF_CAPABILITIES>" ]}
-> The path can have a wildcard ("*
") specifying at the end to allow fornamespacing. For example, "secret/training_*
" grants permissions on anypath starts with "secret/training_
" (e.g. secret/training_vault
).
Define one or more capabilities on each path to control operations that arepermitted.
Capability | Associated HTTP verbs |
---|---|
create | POST/PUT |
read | GET |
update | POST/PUT |
delete | DELETE |
list | LIST |
Policy requirements
First step in creating policies is to gather policy requirements.
Example:
admin
is a type of user empowered with managing a Vault infrastructure fora team or organizations. Empowered with sudo, the Administrator is focused onconfiguring and maintaining the health of Vault cluster(s) as well asproviding bespoke support to Vault users.
admin
must be able to:
- Mount and manage auth backends broadly across Vault
- Mount and manage secret backends broadly across Vault
- Create and manage ACL policies broadly across Vault
- Read system health check
provisioner
is a type of user or service that will be used by an automatedtool (e.g. Terraform) to provision and configure a namespace within a Vaultsecret backend for a new Vault user to access and write secrets.
provisioner
must be able to:
- Mount and manage auth backends
- Mount and manage secret backends
- Create and manage ACL policies
Now, you are ready to author policies to fulfill the requirements.
Example policy for admin
admin-policy.hcl
# Manage auth backends broadly across Vaultpath "auth/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# List, create, update, and delete auth backendspath "sys/auth/*"{ capabilities = ["create", "read", "update", "delete", "sudo"]}# List existing policiespath "sys/policy"{ capabilities = ["read"]}# Create and manage ACL policies broadly across Vaultpath "sys/policy/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# List, create, update, and delete key/value secretspath "secret/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# Manage and manage secret backends broadly across Vault.path "sys/mounts/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# Read health checkspath "sys/health"{ capabilities = ["read", "sudo"]}
Example policy for provisioner
provisioner-policy.hcl
# Manage auth backends broadly across Vaultpath "auth/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}# List, create, update, and delete auth backendspath "sys/auth/*"{ capabilities = ["create", "read", "update", "delete", "sudo"]}# List existing policiespath "sys/policy"{ capabilities = ["read"]}# Create and manage ACL policiespath "sys/policy/*"{ capabilities = ["create", "read", "update", "delete", "list"]}# List, create, update, and delete key/value secretspath "secret/*"{ capabilities = ["create", "read", "update", "delete", "list"]}
Step 2: Create policies
Now, create admin
and provisioner
policies in Vault.
CLI command
To create policies:
$ vault policy write <POLICY_NAME> <POLICY_FILE>
Example:
# Create admin policy$ vault policy write admin admin-policy.hcl# Create provisioner policy$ vault policy write provisioner provisioner-policy.hcl
NOTE: To update an existing policy, simply re-run the same command bypassing your modified policy (*.hcl
).
API call using cURL
To create a policy, use /sys/policy
endpoint:
$ curl --header "X-Vault-Token: <TOKEN>" \ --request PUT \ --data <PAYLOAD> \ <VAULT_ADDRESS>/v1/sys/policy/<POLICY_NAME>
Where <TOKEN>
is your valid token, and <PAYLOAD>
includes policy name andstringfied policy.
Example:
Now, create admin
and provisioner
policies:
# Create admin policy$ curl --request PUT --header "X-Vault-Token: ..." --data @admin-payload.json \ https://vault.rocks/v1/sys/policy/admin$ cat admin-payload.json{ "policy": "path \"auth/*\" { capabilities = [\"create\", \"read\", \"update\", ... }"}# Create provisioner policy$ curl --request PUT --header "X-Vault-Token: ..." --data @provisioner-payload.json \ https://vault.rocks/v1/sys/policy/provisioner$ cat provisioner-payload.json{ "policy": "path \"auth/*\" { capabilities = [\"create\", \"read\", \"update\", ... }"}
-> NOTE: You can also use /sys/policies
endpoint which is used to manageACL, RGP, and EGP policies in Vault (RGP and EGP policies are enterprise-onlyfeatures). To list policies, invoke /sys/policies/acl
endpoint.
NOTE: To update an existing policy, simply re-run the same command bypassing your modified policy in the request payload (*.json
).
Step 3: View existing policies
Make sure that you see the policies you created in Step 2.
CLI command
The following command lists existing policies:
$ vault policy list
To view a specific policy:
$ vault policy read <POLICY_NAME>
Example:
# Read admin policy$ vault policy read admin# Mount and manage auth backends broadly across Vaultpath "auth/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}path "sys/auth/*"{ capabilities = ["create", "read", "update", "delete", "sudo"]}# Create and manage ACL policies broadly across Vaultpath "sys/policy/*"{ capabilities = ["create", "read", "update", "delete", "list", "sudo"]}...
API call using cURL
To list existing ACL policies, use the /sys/policy
endpoint.
$ curl --request LIST --header "X-Vault-Token: ..." https://vault.rocks/v1/sys/policy | jq
To read a specific policy, the endpoint path should be/sys/policy/<POLICY_NAME>
.
Example:
Read the admin policy:
$ curl --request GET --header "X-Vault-Token: ..." https://vault.rocks/v1/sys/policy/admin | jq{ "name": "admin", "rules": "# Mount and manage auth backends broadly across Vault\npath \"auth/*\"\n{\n ...", "request_id": "e8151bf3-8136-fef9-428b-1506042350cf", "lease_id": "", "renewable": false, "lease_duration": 0, "data": { ...
Step 4: Check capabilities of a token
Use the /sys/capabilities
endpoint to fetch the capabilities of a token on agiven path. This helps to verify what operations are granted based on thepolicies attached to the token.
CLI command
The command is:
$ vault token capabilities <TOKEN> <PATH>
Example:
First, create a token attached to admin
policy:
$ vault token create -policy="admin"Key Value--- -----token 79ecdd41-9bac-1ac7-1ee4-99fbce796221token_accessor 39b5e8b5-7bbf-6c6d-c536-ba79d3a80dd5token_duration 768h0m0stoken_renewable truetoken_policies [admin default]
Now, fetch the capabilities of this token on sys/auth/approle
path.
$ vault token capabilities 79ecdd41-9bac-1ac7-1ee4-99fbce796221 sys/auth/approleCapabilities: [create delete read sudo update]
The result should match the policy rule you wrote on sys/auth/*
path. You canrepeat the steps to generate a token for provisioner
and check itscapabilities on paths.
In the absence of token, it returns capabilities of current token invoking thiscommand.
$ vault token capabilities sys/auth/approleCapabilities: [root]
API call using cURL
Use the sys/capabilities
endpoint.
Example:
First, create a token attached to admin
policy:
$ curl --request POST --header "X-Vault-Token: ..." --data '{ "policies":"admin" }' \ https://vault.rocks/v1/auth/token/create{ "request_id": "870ef38c-1401-7beb-633c-ff09cca3db68", "lease_id": "", "renewable": false, "lease_duration": 0, "data": null, "wrap_info": null, "warnings": null, "auth": { "client_token": "9f3a9fbb-4e1a-87c3-9d4d-ee4d96d40af1", "accessor": "f8a269c0-153a-c1ea-ae97-e7e964814392", "policies": [ "root" ], "metadata": null, "lease_duration": 0, "renewable": false, "entity_id": "" }}
Now, fetch the capabilities of this token on sys/auth/approle
path.
# Request payload$ cat payload.json{ "token": "9f3a9fbb-4e1a-87c3-9d4d-ee4d96d40af1", "path": "sys/auth/approle"}$ curl --request POST --header "X-Vault-Token: ..." --data @payload.json \ https://vault.rocks/v1/sys/capabilities{ "capabilities": [ "create", "delete", "read", "sudo", "update" ], "request_id": "03f9d5e2-7e8a-4cd3-b9e9-034c058d3d06", "lease_id": "", "renewable": false, "lease_duration": 0, "data": { "capabilities": [ "create", "delete", "read", "sudo", "update" ] }, "wrap_info": null, "warnings": null, "auth": null}
The result should match the policy rule you wrote on sys/auth/*
path. You canrepeat the steps to generate a token for provisioner
and check itscapabilities on paths.
To check current token's capabilities permitted on a path, usesys/capabilities-self
endpoint.
$ curl --request POST --header "X-Vault-Token: ..." --data '{"path":"sys/auth/approle"}' \ https://vault.rocks/v1/sys/capabilities-self
Advanced features
The Role ID is equivalent to a username, and Secret ID is the corresponding password. The app needs both to log in with Vault. Naturally, the next question becomes how to deliver those values to the expecting client.
A common solution involves three personas instead of two: admin
, app
, and trusted entity
. The trusted entity
delivers the Role ID and Secret ID to the client by separate means.
For example, Terraform injects the Role ID onto the virtual machine. When the app runs on the virtual machine, the Role ID already exists on the virtual machine.

Secret ID is like a password. To keep the Secret ID confidential, useresponse wrapping so that the onlyexpected client can unwrap the Secret ID.
In Step 3, you executed the following command to retrieve the SecretID:
$ vault write -f auth/approle/role/jenkins/secret-id
Instead, use response wrapping by passing the -wrap-ttl
parameter:
$ vault write -wrap-ttl=60s -f auth/approle/role/jenkins/secret-idKey Value--- -----wrapping_token: 9bbe23b7-5f8c-2aec-83dc-e97e94a2e632wrapping_accessor: cb5bdc8f-0cdb-35ff-0e68-9de57a79c3bfwrapping_token_ttl: 1m0swrapping_token_creation_time: 2018-01-08 21:29:38.826611 -0800 PSTwrapping_token_creation_path: auth/approle/role/jenkins/secret-id
Send this wrapping_token
to the client so that the response can be unwrap andobtain the Secret ID.
$ VAULT_TOKEN=9bbe23b7-5f8c-2aec-83dc-e97e94a2e632 vault unwrapKey Value--- -----secret_id 575f23e4-01ad-25f7-2661-9c9bdbb1cf81secret_id_accessor 7d8a40b7-a6fd-a634-579b-b7d673ff86fb
NOTE: To retrieve the Secret ID alone, you can use jq
as follow:
$ VAULT_TOKEN=2577044d-cf86-a065-e28f-e2a14ea6eaf7 vault unwrap -format=json | jq -r ".data.secret_id"b07d7a47-1d0d-741d-20b4-ae0de7c6d964
Next steps
Read the AppRole with Terraform and Chef guide to better understand the role of trusted entities using Terraform and Chef as an example.
To learn more about response wrapping, go to the Cubbyhole Response Wrapping guide.