Vault supports multiple authentication methods and also allows enabling the same type of authentication method on different mount paths. Each Vault client may have multiple accounts with various identity providers that are enabled on the Vault server.
Vault clients can be mapped as entities and their corresponding accounts with authentication providers can be mapped as aliases. In essence, each entity is made up of zero or more aliases. Identity secrets engine internally maintains the clients who are recognized by Vault.
»Personas
The steps described in this tutorial are typically performed by operations persona.
»Challenge
Bob has accounts in both Github and LDAP. Both Github and LDAP auth methods are enabled on the Vault server that he can authenticate using either one of his accounts. Although both accounts belong to Bob, there is no association between the two accounts to set some common properties.
»Solution
Create an entity representing Bob, and associate aliases representing each of his accounts as the entity member. You can set additional policies and metadata on the entity level so that both accounts can inherit.
When Bob authenticates using either one of his accounts, the entity identifier will be tied to the authenticated token. When such tokens are put to use, their entity identifiers are audit logged, marking a trail of actions performed by specific users.
»Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault environment. Refer to the Getting Started tutorial to install Vault. Make sure that your Vault server has been initialized and unsealed.
NOTE: An interactive tutorial is also available if you do not have a Vault environment to perform the steps described in this tutorial. Click the Show Terminal button to start.
»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 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:
# Configure auth methods
path "sys/auth" {
capabilities = [ "read", "list" ]
}
# Configure auth methods
path "sys/auth/*" {
capabilities = [ "create", "update", "read", "delete", "list", "sudo" ]
}
# Manage userpass auth methods
path "auth/userpass/*" {
capabilities = [ "create", "read", "update", "delete" ]
}
# Manage github auth methods
path "auth/github/*" {
capabilities = [ "create", "read", "update", "delete" ]
}
# Display the Policies tab in UI
path "sys/policies" {
capabilities = [ "read", "list" ]
}
# Create and manage ACL policies from UI
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Create and manage policies
path "sys/policies/acl" {
capabilities = [ "read", "list" ]
}
# Create and manage policies
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# List available secrets engines to retrieve accessor ID
path "sys/mounts" {
capabilities = [ "read" ]
}
# Create and manage entities and groups
path "identity/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
If you are not familiar with policies, complete the policies tutorial.
»Step 1: Create an Entity with Alias
You are going to create a new entity with base policy assigned. The entity defines two entity aliases with each has a different policy assigned.
Scenario: A user, Bob Smith at ACME Inc. happened to have two sets of
credentials: bob
and bsmith
. He can authenticate with Vault using either one
of his accounts. To manage his accounts and link them to identity Bob Smith
in
QA team, you are going to create an entity for Bob.
For the simplicity of this tutorial, you are going to work with the userpass
auth method. However, in reality, the user bob
might be a username exists in
Active Directory, and bsmith
might be Bob's username in GitHub.
»Scenario Policies
base.hcl
path "secret/data/training_*" {
capabilities = ["create", "read"]
}
test.hcl
path "secret/data/test" {
capabilities = [ "create", "read", "update", "delete" ]
}
team-qa.hcl
path "secret/data/team-qa" {
capabilities = [ "create", "read", "update", "delete" ]
}
NOTE: This scenario assumes that the K/V v2 secrets engine is enabled at
the secret
path. If you are not sure, refer to the Versioned Key/Value
Secrets Engine
tutorial.
Now, you are going to create bob
and bsmith
users with appropriate policies
attached.
Create
base
policy.$ vault policy write base base.hcl
Create
test
policy.$ vault policy write test test.hcl
Create
team-qa
policy.$ vault policy write team-qa team-qa.hcl
List all policies to verify that 'base', 'test' and 'team-qa' policies exist.
$ vault policy list base default team-qa test root
Enable the
userpass
auth method.$ vault auth enable userpass
Create a new user named
bob
in userpass where the password istraining
andtest
policy is attached.$ vault write auth/userpass/users/bob password="training" policies="test"
Create a new user named
bsmith
in userpass where the password istraining
andteam-qa
policy is attached.$ vault write auth/userpass/users/bsmith password="training" policies="team-qa"
Execute the following command to discover the mount accessor for the userpass auth method.
$ vault auth list -detailed Path Type Accessor ... ---- ---- -------- ... token/ token auth_token_bec8530a ... userpass/ userpass auth_userpass_70eba76b ...
In the output, locate the Accessor value for
userpass
.Run the following command to store the userpass accessor value in a file named
accessor.txt
.$ vault auth list -format=json | jq -r '.["userpass/"].accessor' > accessor.txt
Create an entity for
bob-smith
.$ vault write identity/entity name="bob-smith" policies="base" \ metadata=organization="ACME Inc." \ metadata=team="QA" Key Value --- ----- aliases <nil> id 631256b1-8523-9838-5501-d0a1e2cdad9c
Make a note of the generated entity ID (
id
).Now, add the user
bob
to thebob-smith
entity by creating an entity alias.$ vault write identity/entity-alias name="bob" \ canonical_id=<entity_id> \ mount_accessor=<userpass_accessor>
The
<userpass_accessor>
value is stored inaccessor.txt
.Example:
$ vault write identity/entity-alias name="bob" \ canonical_id="631256b1-8523-9838-5501-d0a1e2cdad9c" \ mount_accessor=$(cat accessor.txt) Key Value --- ----- canonical_id 631256b1-8523-9838-5501-d0a1e2cdad9c id 873f7b12-dec8-c182-024e-e3f065d8a9f1
Repeat the step to add user
bsmith
to thebob-smith
entity.Example:
$ vault write identity/entity-alias name="bsmith" \ canonical_id="631256b1-8523-9838-5501-d0a1e2cdad9c" \ mount_accessor=$(cat accessor.txt) Key Value --- ----- canonical_id 631256b1-8523-9838-5501-d0a1e2cdad9c id 55d46747-b99e-6a82-05f5-61bb60fd7d15
Review the entity details.
$ vault read identity/entity/id/<entity_id>
The output should include the entity aliases, metadata (organization, and team), and base policy.
Since the policies were written against
secret/
path, enable key/value secrets engine atsecret/
if it's not already done so.$ vault secrets enable -path=secret/ kv-v2
»Step 2: Test the Entity
To better understand how a token inherits the capabilities from the entity's
policy, you are going to test it by logging in as bob
.
First, login as
bob
.$ vault login -method=userpass username=bob password=training Key Value --- ----- token ac318416-0dc1-4311-67e4-b58381c86fde token_accessor 79cced7b-51df-9523-920f-a1579687516b token_duration 768h token_renewable true token_policies ["default" "test"] identity_policies ["base"] policies ["base" "default" "test"] token_meta_username bob
Upon a successful authentication, a token will be returned. Notice that the output displays
token_policies
andidentity_policies
. The generated token has bothtest
andbase
policies attached.The
test
policy grants CRUD operations on thesecret/test
path. Test to make sure that you can write secrets in the path.$ vault kv put secret/test owner="bob" Success! Data written to: secret/test
Although the username
bob
does not havebase
policy attached, the token inherits the capabilities granted in the base policy becausebob
is a member of thebob-smith
entity, and the entity has base policy attached. Check to see that the bob's token inherited the capabilities.$ vault token capabilities secret/data/training_test create, read
The
base
policy grants create and read capabilities onsecret/training_*
path; thereforebob
is permitted to run create and read operations against any path starting withsecret/training_*
.What about the
secret/team-qa
path?$ vault token capabilities secret/data/team-qa deny
The user
bob
only inherits capability from its associating entity's policy. The user can access thesecret/team-qa
path only if he logs in withbsmith
credentials.Log back in with the token you used to configure the entity before proceed to Step 3.
»Step 3: Create an Internal Group
NOTE: Log back in with the token you used to configure the entity before proceed to Step 3.
Now, you are going to create an internal group named engineers
. Its
member is bob-smith
entity that you created in Step 1.
The group policy, team-eng
defines the following in the team-eng.hcl
file.
path "secret/data/team/eng" {
capabilities = [ "create", "read", "update", "delete"]
}
Create a new policy named team-eng
.
$ vault policy write team-eng ./team-eng.hcl
Create an internal group named engineers
and add bob-smith
entity as a
group member and attach team-eng
.
$ vault write identity/group name="engineers" \
policies="team-eng" \
member_entity_ids=<entity_id> \
metadata=team="Engineering" \
metadata=region="North America"
Where <entity_id>
is the value you copied at Step 1.
Example:
$ vault write identity/group name="engineers" \
policies="team-eng" \
member_entity_ids="631256b1-8523-9838-5501..." \
metadata=team="Engineering" \
metadata=region="North America"
Key Value
--- -----
id 81bdac90-284a-7b8c-6289-5fa7693bcb4a
name engineers
Now, when you login as bob
or bsmith
, its generated token inherits the
group-level policy, team-eng
. You can perform similar tests demonstrated
in Step 2 to verify that.
»Summary
By default, Vault creates an internal group. When you create an
internal group, you specify the group members rather than group
alias. Group aliases are mapping between Vault and external identity
providers (e.g. LDAP, GitHub, etc.). Therefore you define group aliases only
when you create external groups. For internal groups, you specify
member_entity_ids
and/or member_group_ids
.
»Step 4: Create an External Group
It is common for organizations to enable auth methods such as LDAP, Okta and perhaps GitHub to handle the Vault user authentication, and individual user's group memberships are defined within those identity providers.
In order to manage the group-level authorization, you can create an external group to link Vault with the external identity provider (auth provider) and attach appropriate policies to the group.
»Example Scenario
Any user who belongs to training
team in GitHub organization,
example-inc
are permitted to perform all operations against the
secret/education
path.
NOTE: This scenario assumes that the GitHub organization, example-inc
exists as well as training
team within the organization.
Policy: education.hcl
path "secret/data/education" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
Create a new policy named
education
.$ vault policy write education education.hcl
Enable GitHub auth method.
$ vault auth enable github
Retrieve the mount accessor for the GitHub auth method and save it in a file named
accessor.txt
.$ vault auth list -format=json | jq -r '.["github/"].accessor' > accessor.txt
Configure to point to your GitHub organization (e.g. hashicorp).
$ vault write auth/github/config organization=example-inc
Create an external group named
education
. Be sure to copy the generated group ID.$ vault write identity/group name="education" \ policies="education" \ type="external" \ metadata=organization="Product Education"
Create a group alias where
canonical_id
is the group ID and the name is the actual GitHub team name. (NOTE: Use slugified team name.)$ vault write identity/group-alias name="training" \ mount_accessor=$(cat accessor.txt) \ canonical_id="<group_ID>"
»Summary
At this point, any GitHub user who belongs to training
team within the
example-inc
organization can authenticate with Vault. The generated token for
the user has education
policy attached.
»Help and Reference
This tutorial focuses on the creation of entities and groups in Vault. Refer to Vault Limits and Maximums to understand the known upper limits when working with Vault Identities.