Generate tokens for machine authentication with AppRole
Before a client can interact with Vault, it must authenticate against an auth method to acquire a token. This token has policies attached so that the behavior of the client can be governed.
Since tokens are the core method for authentication within Vault, there is a token auth method (often referred to as token store). This is a special auth method responsible for creating and storing tokens.
Auth methods
Auth methods perform authentication to verify the user or machine-supplied information. Some of the supported auth methods are targeted towards users while others are targeted toward machines or apps. For example, LDAP auth method enables user authentication using an existing LDAP server while AppRole auth method is recommended for machines or apps.
The GitHub auth method documentation explains how to configure the GitHub auth method for user authentication.
This introductory tutorial focuses on generating tokens for machines or apps by enabling the AppRole auth method.
User lockout
As of Vault 1.13, the User lockout feature is enabled
by default for the userpass
, approle
, and ldap
auth methods.
Personas
The end-to-end scenario described in this tutorial involves two personas:
admin
with privileged permissions to configure an auth methodapp
is the consumer of secrets stored in Vault
Challenge
Think of a scenario where a DevOps team wants to configure Jenkins to read
secrets from Vault so that it can inject the secrets to an app's environment
variables (e.g. MYSQL_DB_HOST
) at deployment time.
Instead of hardcoding secrets in each build script as plain text, Jenkins retrieves secrets from Vault.
As a user, you can authenticate with Vault using your LDAP credentials, and Vault generates a token. This token has policies granting you permission to perform the appropriate operations.
How can a Jenkins server programmatically request a token so that it can read secrets from Vault?
Solution
Enable AppRole auth method so that the Jenkins server can obtain a Vault token with appropriate policies attached. Since each AppRole has attached policies, you can write fine-grained policies limiting which app can access which path.
Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault environment. Refer to the Vault install guide to install Vault. Make sure that your Vault server has been initialized and unsealed.
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Policy requirements
Note
For the purpose of this tutorial, you can use the root
token to work
with Vault. However, it is recommended that root tokens are only used for just
enough initial setup or in emergencies. As a best practice, use tokens with
an appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this tutorial, your policy must include the following permissions:
# Mount the AppRole auth methodpath "sys/auth/approle" { capabilities = [ "create", "read", "update", "delete", "sudo" ]}# Configure the AppRole auth methodpath "sys/auth/approle/*" { capabilities = [ "create", "read", "update", "delete" ]}# Create and manage rolespath "auth/approle/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}# Write ACL policiespath "sys/policies/acl/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}# Write test data# Set the path to "secret/data/mysql/*" if you are running `kv-v2`path "secret/mysql/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}
If you are not familiar with policies, complete the policies tutorial.
Scenario introduction
AppRole is an authentication mechanism within Vault to allow machines or apps to acquire a token to interact with Vault. It uses RoleID and SecretID for login.
The basic workflow is:
Note
For the purpose of introducing the basics of AppRole, this tutorial walks you through a very simple scenario involving only two personas (admin and app). Please refer to the Advanced Features section for further discussions after completing the following steps.
In this tutorial, you are going to perform the following steps:
- Enable AppRole auth method
- Create a role with policy attached
- Get RoleID and SecretID
- Login with RoleID & SecretID
- 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.
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
The
admin
namespace is the top-level namespace automatically created by HCP Vault. All CLI operations default to use the namespace defined in this environment variable.Type
vault status
to verify your connectivity to the Vault cluster.$ vault statusKey Value--- -----Recovery Seal Type shamirInitialized trueSealed falseTotal Recovery Shares 1Threshold 1Version 1.9.2+entStorage Type raft...snipped...
Enable the K/V secrets engine
$ vault secrets enable --version=2 --path=secret kv
Create some test data.
$ vault kv put secret/mysql/webapp db_name="users" username="admin" password="passw0rd"
Example output:
Key Value--- -----created_time 2021-06-08T02:34:23.182299Zdeletion_time n/adestroyed falseversion 1
The HCP Vault Dedicated server is ready.
Step 1: Enable AppRole auth method
(Persona: admin)
The AppRole auth method must be enabled before it can be used.
Enable approle
auth method by executing the following command.
$ vault auth enable approleSuccess! Enabled approle auth method at: approle/
Step 2: Create a role with policy attached
(Persona: admin)
When you enabled the AppRole auth method, it gets mounted at the /auth/approle
path. In this example, you are going to create a role for the app
persona
(jenkins
in our scenario).
First, create a policy named jenkins
with following definition.
# Read-only permission on secrets stored at 'secret/data/mysql/webapp'path "secret/data/mysql/webapp" { capabilities = [ "read" ]}
Before creating a role, create a
jenkins
policy.$ vault policy write jenkins -<<EOF# Read-only permission on secrets stored at 'secret/data/mysql/webapp'path "secret/data/mysql/webapp" { capabilities = [ "read" ]}EOF
Output:
Success! Uploaded policy: jenkins
Creates a role named
jenkins
withjenkins
policy attached. The generated token's time-to-live (TTL) is set to 1 hour and can be renewed for up to 4 hours of its first creation. (NOTE: This example creates a role which operates in pull mode.)$ vault write auth/approle/role/jenkins token_policies="jenkins" \ token_ttl=1h token_max_ttl=4h
Output:
Success! Data written to: auth/approle/role/jenkins
To attach multiple policies, pass the policy names as a comma separated string:
token_policies="jenkins,anotherpolicy"
.The command to create a new AppRole is:
$ vault write auth/approle/role/<ROLE_NAME> [parameters]
There are a number of parameters that you can set on a role. If you want to limit the use of the generated secret ID, set
secret_id_num_uses
orsecret_id_ttl
parameter values. Similarly, you can specifytoken_num_uses
andtoken_ttl
. You may never want the app token to expire. In such a case, specify theperiod
so that the token generated by this AppRole is a periodic token. To learn more about periodic tokens, refer to the Tokens tutorial.Read the
jenkins
role you created to verify.$ vault read auth/approle/role/jenkins
Example output:
Key Value--- -----bind_secret_id truelocal_secret_ids falsesecret_id_bound_cidrs <nil>secret_id_num_uses 0secret_id_ttl 0stoken_bound_cidrs []token_explicit_max_ttl 0stoken_max_ttl 4htoken_no_default_policy falsetoken_num_uses 0token_period 0stoken_policies [jenkins]token_ttl 1htoken_type default
Step 3: Get RoleID and SecretID
The RoleID and SecretID are like a username and password that a machine or app uses to authenticate.
Since the example created a jenkins
role which operates in pull mode, Vault
will generate the SecretID. You can set properties such as usage-limit, TTLs,
and expirations on the SecretIDs to control its lifecycle.
To retrieve the RoleID, invoke the auth/approle/role/<ROLE_NAME>/role-id
endpoint. To generate a new SecretID, invoke the
auth/approle/role/<ROLE_NAME>/secret-id
endpoint.
Now, you need to fetch the RoleID and SecretID of a role.
Execute the following command to retrieve the RoleID for the
jenkins
role.$ vault read auth/approle/role/jenkins/role-idKey Value--- -----role_id 675a50e7-cfe0-be76-e35f-49ec009731ea
Execute the following command to generate a SecretID for the
jenkins
role.$ vault write -force auth/approle/role/jenkins/secret-idKey Value--- -----secret_id ed0a642f-2acf-c2da-232f-1b21300d5f29secret_id_accessor a240a31f-270a-4765-64bd-94ba1f65703c
The
-force
(or-f
) flag forces thewrite
operation to continue without any data values specified. Or you can set parameters such ascidr_list
.If you specified
secret_id_ttl
,secret_id_num_uses
, orbound_cidr_list
on the role in Step 2, the generated SecretID carries out the conditions.
Tip
The RoleID is similar to a username; therefore, you will get the same value
for a given role. In this case, the jenkins
role has a fixed RoleID. While
SecretID is similar to a password that Vault will generate a new value every
time you request it.
Step 4: Login with RoleID & SecretID
(Persona: app)
The client (in this case, Jenkins) uses the RoleID and SecretID passed by the admin to authenticate with Vault. If Jenkins did not receive the RoleID and/or SecretID, the admin needs to investigate.
Tip
Refer to the Advanced Features section for further discussion on distributing the RoleID and SecretID to the client app securely.
To login, use the auth/approle/login
endpoint by passing the RoleID and
SecretID.
Example:
$ vault write auth/approle/login role_id="675a50e7-cfe0-be76-e35f-49ec009731ea" \ secret_id="ed0a642f-2acf-c2da-232f-1b21300d5f29"
Example output:
Key Value--- -----token s.ncEw5bAZJqvGJgl8pBDM0C5htoken_accessor gIQFfVhUd8fDsZjC7gLBMnQutoken_duration 1htoken_renewable truetoken_policies ["default" "jenkins"]identity_policies []policies ["default" "jenkins"]token_meta_role_name jenkins
Vault returns a client token with default
and jenkins
policies attached.
Store the generated token value in an environment variable named, APP_TOKEN
.
Example:
$ export APP_TOKEN="s.ncEw5bAZJqvGJgl8pBDM0C5h"
Tip
To learn more about the Key/Value v2 secrets engine, read the Versioned Key/Value Secrets Engine tutorial.
Step 5: Read secrets using the AppRole token
(Persona: app)
Once receiving a token from Vault, the client can make future requests using this token.
Verify that you can access the secrets at secret/mysql/webapp
.
$ VAULT_TOKEN=$APP_TOKEN vault kv get secret/mysql/webapp====== Metadata ======Key Value--- -----created_time 2021-06-08T02:34:23.182299Zdeletion_time n/adestroyed falseversion 1====== Data ======Key Value--- -----db_name userspassword passw0rdusername admin
The app has a read-only access; therefore, the following delete command will fail.
$ VAULT_TOKEN=$APP_TOKEN vault kv delete secret/mysql/webapp
The error message indicates permission error.
Error deleting secret/mysql/webapp: Error making API request.URL: DELETE http://127.0.0.1:8200/v1/secret/data/mysql/webappCode: 403. Errors:* 1 error occurred: * permission denied
Response wrap the SecretID
The RoleID is equivalent to a username, and SecretID 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 client securely.
A common solution involves three personas instead of two: admin
, app
, and
trusted entity
. The trusted entity
delivers the RoleID and SecretID to the
client by separate means.
For example, Terraform as a trusted entity can deliver the RoleID onto the virtual machine. When the app runs on the virtual machine, the RoleID already exists on the virtual machine.
SecretID is like a password. To keep the SecretID confidential, use response wrapping so that only the expecting client can unwrap the SecretID.
In Step 3, you executed the following command to retrieve the Secret ID.
$ vault write -force auth/approle/role/jenkins/secret-id
Instead, use response wrapping by passing the -wrap-ttl
parameter.
$ vault write -wrap-ttl=60s -force auth/approle/role/jenkins/secret-idKey Value--- -----wrapping_token: s.yzbznr9NlZNzsgEtz3SI56pXwrapping_accessor: Smi4CO0Sdhn8FJvL8XvOT30ywrapping_token_ttl: 1mwrapping_token_creation_time: 2021-06-07 20:02:01.019838 -0700 PDTwrapping_token_creation_path: auth/approle/role/jenkins/secret-id
Send this wrapping_token
to the client so that the response can be unwrapped
and obtain the SecretID.
$ VAULT_TOKEN="s.yzbznr9NlZNzsgEtz3SI56pX" vault unwrapKey Value--- -----secret_id c4086c73-4569-90c9-fd73-72c879e3b7b4secret_id_accessor 3a2e9483-a7d2-dc19-7480-b1a025daecccsecret_id_ttl 0s
Tip
To learn more about the wrapping token, read the Cubbyhole Response Wrapping tutorial.
Limit the SecretID usages
Treat the SecretID like a password and force it to be regenerated after a number of use.
To do so, update the role definition with secret_id_num_uses
set.
$ vault write auth/approle/role/jenkins token_policies="jenkins" \ token_ttl=1h token_max_ttl=4h \ secret_id_num_uses=10
In this example, a SecretID of the jenkins
role can be used for up to 10
times to authenticate and fetch a client token. After the number of uses is
reached, the SecretID expires and you would need to generate a new one. This is
similar to forcing a password rotation.