Vault
Implement identity entities and groups
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.
Note
If you are running Vault Enterprise or HCP Vault Dedicated, be sure to read the Why create entities? section at the end.
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
- jq to process the JSON output for readability
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Policy requirements
Unless you are running Vault for test or development purposes, such as dev mode (-dev),
or with a short lived HCP Vault Dedicated dev tier cluster, it is recommended that you authenticate
with Vault and acquire a tokens with an appropriate set of policies based on your role in
the organization.
If you are connecting to a non-development Vault server, your token must have a policy with 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.
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_ADDRenvironment 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_TOKENenvironment variable.$ export VAULT_TOKEN=<token>Set the
VAULT_NAMESPACEenvironment variable toadmin.$ export VAULT_NAMESPACE=adminThe
adminnamespace 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 statusto verify your connectivity to the Vault cluster.$ vault status Key Value --- ----- Recovery Seal Type shamir Initialized true Sealed false Total Recovery Shares 1 Threshold 1 Version 1.9.2+ent Storage Type raft ...snipped...Enable the key/value v2 secrets engine at the path
secret.$ vault secrets enable -path=secret kv-v2
The Vault Dedicated server is ready.
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. Bob can authenticate with Vault using either
one of their accounts. To manage the user's accounts and link them to identity
Bob Smith in the 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. In reality, the user bob might be a username that exists in
Active Directory, and bsmith might be Bob's username in GitHub. To mock the
behavior, you are going to enable the userpass auth method at two separate
paths: userpass-test and userpass-qa to mimic two different types of auth methods.
User lockout
As of Vault 1.13, the User lockout feature is enabled
by default for the userpass, approle, and ldap auth methods.
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.
Create bob and bsmith users with appropriate policies attached.
Create
basepolicy.$ vault policy write base -<<EOF path "secret/data/training_*" { capabilities = ["create", "read"] } EOFCreate
testpolicy.$ vault policy write test -<<EOF path "secret/data/test" { capabilities = [ "create", "read", "update", "delete" ] } EOFCreate
team-qapolicy.$ vault policy write team-qa -<<EOF path "secret/data/team-qa" { capabilities = [ "create", "read", "update", "delete" ] } EOFList all policies to verify that
base,testandteam-qapolicies exist.$ vault policy list base default team-qa test rootNote
If you are using HCP Vault Dedicated, you will also see the
hcp-rootpolicy.Enable the
userpassauth method atuserpass-test.$ vault auth enable -path="userpass-test" userpassCreate a new user named
bobinuserpass-testwhere the password istrainingandtestpolicy is attached.$ vault write auth/userpass-test/users/bob password="training" policies="test"Enable the
userpassauth method at another paths,userpass-qa.$ vault auth enable -path="userpass-qa" userpassCreate a new user named
bsmithinuserpass-qawhere the password istrainingandteam-qapolicy is attached.$ vault write auth/userpass-qa/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 Plugin Accessor ... ---- ---- -------- ... token/ token auth_token_c5943123 ... userpass-qa/ userpass auth_userpass_8c7b8e0f ... userpass-test/ userpass auth_userpass_264d4705 ... ...Each userpass auth methods has a unique Accessor value to identify it.
Run the following command to store the
userpass-testauth accessor value in a file namedaccessor_test.txt.$ vault auth list -format=json | jq -r '.["userpass-test/"].accessor' > accessor_test.txtThe resulting file contains the accessor value (
auth_userpass_XXXXX).Similarly, run the following command to store the
userpass-qaauth accessor value in a file namedaccessor_qa.txt.$ vault auth list -format=json | jq -r '.["userpass-qa/"].accessor' > accessor_qa.txtCreate an entity for
bob-smith, and store the returned entity ID in a file named,entity_id.txt.$ vault write -format=json identity/entity name="bob-smith" policies="base" \ metadata=organization="ACME Inc." \ metadata=team="QA" \ | jq -r ".data.id" > entity_id.txtThe resulting file contains the entity ID for
bob-smith(e.g.24204b50-22a6-61f5-bd4b-803f1a4e4726).Now, add the user
bobto thebob-smithentity by creating an entity alias. Set a custom metadata on thebobentity alias named, "account" and set its value to be "Tester Account".$ vault write identity/entity-alias name="bob" \ canonical_id=$(cat entity_id.txt) \ mount_accessor=$(cat accessor_test.txt) \ custom_metadata=account="Tester Account"Note
To set custom metadata on the entity alias, you must run Vault 1.9 or later. If you are running Vault version earlier than v1.9, run the command without
custom_metadata=account="Tester Account".Example output:
Key Value --- ----- canonical_id 24204b50-22a6-61f5-bd4b-803f1a4e4726 id ae2cdd0f-9807-7336-2265-5575c71837e7To view the created entity alias, use the returned entity alias ID.
$ vault read identity/entity-alias/id/<id>Example:
$ vault read identity/entity-alias/id/ae2cdd0f-9807-7336-2265-5575c71837e7 Key Value --- ----- canonical_id 971b5ab3-1931-8381-8605-1b9511572278 creation_time 2021-11-15T01:41:03.093366Z custom_metadata map[account:Tester Account] id 10340e8f-64fa-fe7d-0c88-b6172293f788 last_update_time 2021-11-15T01:41:03.093366Z local false merged_from_canonical_ids <nil> metadata <nil> mount_accessor auth_userpass_2cbfe431 mount_path auth/userpass-test/ mount_type userpass name bob namespace_id rootRepeat the step to add user
bsmithto thebob-smithentity. Set a custom metadata on thebobentity alias named, "account" and set its value to be "QA Eng Account".$ vault write identity/entity-alias name="bsmith" \ canonical_id=$(cat entity_id.txt) \ mount_accessor=$(cat accessor_qa.txt) \ custom_metadata=account="QA Eng Account"Example output:
Key Value --- ----- canonical_id 24204b50-22a6-61f5-bd4b-803f1a4e4726 id 6066f6af-bb1c-5310-58a1-fd9c8f151573Review the entity details.
$ vault read -format=json identity/entity/id/$(cat entity_id.txt) | jq -r ".data"Example output: The output should include the entity aliases, metadata (organization, and team), and base policy.
{ "aliases": [ { "canonical_id": "73503625-abcd-db22-08c3-c121d682d550", "creation_time": "2021-11-17T05:33:48.040506Z", "custom_metadata": { "account": "Tester Account" }, "id": "cf073e2e-41af-852f-848d-f67533c8a610", "last_update_time": "2021-11-17T05:33:48.040506Z", "local": false, "merged_from_canonical_ids": null, "metadata": null, "mount_accessor": "auth_userpass_0a6936a7", "mount_path": "auth/userpass-test/", "mount_type": "userpass", "name": "bob" }, { "canonical_id": "73503625-abcd-db22-08c3-c121d682d550", "creation_time": "2021-11-17T05:33:48.107834Z", "custom_metadata": { "account": "QA Eng Account" }, "id": "7add6763-ce53-d92a-c795-c8ae529ce6e7", "last_update_time": "2021-11-17T05:33:48.107834Z", "local": false, "merged_from_canonical_ids": null, "metadata": null, "mount_accessor": "auth_userpass_ef4f8068", "mount_path": "auth/userpass-qa/", "mount_type": "userpass", "name": "bsmith" } ], "creation_time": "2021-11-17T05:33:47.966585Z", "direct_group_ids": [ "49e8b9e8-8933-1e14-f05c-e1c9674b142b" ], "disabled": false, "group_ids": [ "49e8b9e8-8933-1e14-f05c-e1c9674b142b" ], "id": "73503625-abcd-db22-08c3-c121d682d550", "inherited_group_ids": [], "last_update_time": "2021-11-17T05:33:47.966585Z", "merged_entity_ids": null, "metadata": { "organization": "ACME Inc.", "team": "QA" }, "mfa_secrets": {}, "name": "bob-smith", "namespace_id": "root", "policies": [ "base" ] }
Security Consideration
Avoid storing any sensitive personally identifiable information (PII) in the entity metadata. The entity metadata is replicated to other clusters if Performance Replication is configured. This may be a great concern for the GDPR. Vault 1.9 introduced the ability to set custom metadata on each entity alias that does not overlap with the metadata set by Vault. If the auth method is local to the cluster, the metadata will not be replicated to other clusters in the same performance replication group. Therefore, it is recommended to leverage the custom metadata on the entity alias instead.
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, and store the generated client token inbob_token.txt.$ vault login -format=json -method=userpass -path=userpass-test \ username=bob | jq -r ".auth.client_token" > bob_token.txt Password (will be hidden):Enter the password
trainingwhen prompted, and pressreturn.The
testpolicy grants CRUD operations on thesecret/testpath. Test to make sure that you can write secrets in the path.$ VAULT_TOKEN=$(cat bob_token.txt) vault kv put secret/test owner="bob" Key Value --- ----- created_time 2021-11-06T02:12:02.104146Z custom_metadata <nil> deletion_time n/a destroyed false version 1Although the username
bobdoes not havebasepolicy attached, the token inherits the capabilities granted in the base policy becausebobis a member of thebob-smithentity, and the entity has base policy attached. Check to see that the bob's token inherited the capabilities.$ VAULT_TOKEN=$(cat bob_token.txt) vault token capabilities secret/data/training_test create, readThe
basepolicy grants create and read capabilities onsecret/training_*path; thereforebobis permitted to run create and read operations against any path starting withsecret/training_*.What about the
secret/team-qapath?$ VAULT_TOKEN=$(cat bob_token.txt) vault token capabilities secret/data/team-qa denyThe user
bobonly inherits capability from its associating entity's policy. The user can access thesecret/team-qapath only if they log in withbsmithcredentials.
Create an internal group
Reset the `VAULT_TOKEN` environment variable
Log back in with the token you used to configure the entity before proceed to create an internal group. (Refer to the Lab setup section.)
Now, you are going to create an internal group named engineers. Its member is
the bob-smith entity that you created in the create an
entity section.

The group policy, team-eng defines the following in the team-eng.hcl file.
team-eng.hcl
path "secret/data/team/eng" {
capabilities = [ "create", "read", "update", "delete"]
}
Create a new policy named
team-eng.$ vault policy write team-eng -<<EOF path "secret/data/team/eng" { capabilities = [ "create", "read", "update", "delete"] } EOFCreate an internal group named
engineersand addbob-smithentity as a group member and attachteam-eng.$ vault write identity/group name="engineers" \ policies="team-eng" \ member_entity_ids=$(cat entity_id.txt) \ metadata=team="Engineering" \ metadata=region="North America"Example output:
Key Value --- ----- id 0cd76d41-fe36-8c7b-4758-d36bbc212650 name engineersNow, when you login as
boborbsmith, its generated token inherits the group-level policy,team-eng. You can perform similar tests demonstrated in the test the entity section 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.
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.
Create a new policy named
education.$ vault policy write education -<<EOF path "secret/data/education" { capabilities = [ "create", "read", "update", "delete", "list" ] } EOFEnable GitHub auth method.
$ vault auth enable githubRetrieve the mount accessor for the GitHub auth method and save it in a file named
accessor_github.txt.$ vault auth list -format=json | jq -r '.["github/"].accessor' > accessor_github.txtConfigure to point to your GitHub organization.
Note
Use the actual Github organization name that exists to which you want to connect. The following uses a fictional organization name,
example-incas an example. If you do not change this value, the login attempt at the end of this section will not succeed.Example:
$ vault write auth/github/config organization=example-incCreate an external group, and store the generated group ID in
group_id.txt.Example:
$ vault write -format=json identity/group name="education" \ policies="education" \ type="external" \ metadata=organization="Product Education" | jq -r ".data.id" > group_id.txtCreate a group alias where
canonical_idis the group ID and the name must be an actual GitHub team name that exists.Note
The
namemust be an actual GitHub team name that exists in the Github organization that you configured earlier. Use slugified team name.$ vault write identity/group-alias name="training" \ mount_accessor=$(cat accessor_github.txt) \ canonical_id="$(cat group_id.txt)"Example output:
Key Value --- ----- canonical_id 66818a45-ef85-0ff3-6c1e-37faf12ea55e id 578944f0-dcfd-29fd-a763-d3f9431512d7Attempt to login as a GitHub user who is a member of the training group and enter the users personal access token.
$ vault login -format=json -method=github GitHub Personal Access Token (will be hidden):Example output:
WARNING! The VAULT_TOKEN environment variable is set! This takes precedence over the value set by this command. To use the value set by this command, unset the VAULT_TOKEN environment variable or set it to the token displayed below. { "request_id": "fcc10086-9033-dc21-2ddb-d420fbabc474", "lease_id": "", "lease_duration": 0, "renewable": false, "data": null, "warnings": null, "auth": { "client_token": "s.7QKSeasAME.mD5Ve", "accessor": "yUBG78LRdLiZNkBNNTe7OEp1.mD5Ve", "policies": [ "default", "education" ], "token_policies": [ "default" ], "identity_policies": [ "education" ], "metadata": { "org": "example-inc", "username": "bobbysmith_developer" }, "orphan": true, "entity_id": "58a16f6c-ee92-0cd2-f508-4b2fdb093c07", "lease_duration": 3600, "renewable": true, "mfa_requirement": null } }
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.
Clean up
If you wish to clean up your environment after completing the tutorial, follow the steps in this section.
Unset the
VAULT_TOKENenvironment variable.$ unset VAULT_TOKENUnset the
VAULT_ADDRenvironment variable.$ unset VAULT_ADDRYou can stop the Vault dev server by pressing Ctrl+C where the server is running. Or, execute the following command.
$ pgrep -f vault | xargs killFor Vault Dedicated, delete the Vault instance from the HCP Portal.
Why create entities?
This tutorial used a human user, Bob Smith as an example to demonstrate the use of entities and groups. However, this concept also applies to applications.
Consider a scenario where an application uses multiple auth methods to log in with Vault. Without an entity defined to tie those multiple auth identities back to the application, the Vault server has no way of knowing the same application logged into Vault using different auth methods. As a result, each login gets counted as a new client.
This may not be an issue for Vault Community Edition users; however, this can results in unexpectedly higher client counts that affects your Vault Enterprise or Vault Dedicated billing cost.
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.







