Vault
Secure workflows with Azure Active Directory with OIDC auth method
Before a client can interact with Vault, it must authenticate with an auth method to acquire a token. This token has policies attached so that the behavior of the client can be governed.

Note
To learn the basics of Vault tokens, go through the Tokens tutorial.
Auth methods perform authentication to verify the user or machine-supplied information. Some auth methods are targeted towards users while others are targeted toward machines or apps.
Challenge
Vault supports a number of auth methods for users or system to prove their identity so that a token with appropriate policies can be obtained. Delegated authorization methods based on OAuth 2.0 are convenient for users and have become increasingly common.
Solution
If you use Azure Active Directory (AD), you can use Microsoft's identity platform and its implementation of OpenID Connect to verify the identity of a Vault user. By registering a Vault application in Azure, configuring Vault's OIDC auth method, and connecting the AD group with an external group in Vault, your Vault users can log into Vault by web browser. They will be redirected to Azure to complete login and then be routed back to Vault with a newly-created token.
Note
To learn how to configure authentication for system-assigned or user-assigned managed identities in Azure, go through documentation on the Azure Auth Method.
This tutorial uses the current user's email to authenticate to Azure AD. You can optionally edit the claims and Vault configuration to use Azure AD UserPrincipalName (UPN).
Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault 1.6 or later. Refer to the Vault install guide guide to install Vault. Make sure that your Vault server has been initialized and unsealed.
In this tutorial, make sure that Azure can access your Vault server to successfully redirect the authentication request.
Azure Active Directory
This tutorial uses Azure Active Directory. Make sure you have:
Configured an Azure AD tenant.
Permissions to configure application registrations and read group information.
Signed into Azure from the CLI with the correct tenant ID.
An Azure AD group you can use to connect to a Vault external group.
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 OIDC auth method
path "sys/auth/oidc" {
  capabilities = [ "create", "read", "update", "delete", "sudo" ]
}
# Configure the OIDC auth method
path "auth/oidc/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Write ACL policies
path "sys/policies/acl/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}
# List available secrets engines to retrieve accessor ID
path "sys/mounts" {
  capabilities = [ "read" ]
}
# Manage secrets engines
path "sys/mounts/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# List, create, update, and delete key/value secrets
path "secret/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
If you are not familiar with policies, complete the policies tutorial.
Lab setup
In another terminal, start a Vault dev server with
rootas the root token.$ vault server -dev -dev-root-token-id rootThe Vault dev server defaults to running at
127.0.0.1:8200. The server is initialized and unsealed.Insecure operation
Do not run a Vault dev server in production. This approach starts a Vault server with an in-memory database and runs in an insecure way.
Export an environment variable for the
vaultCLI to address the Vault server.$ export VAULT_ADDR=http://127.0.0.1:8200Export an environment variable for the
vaultCLI to address the Vault server through the OIDC interface.$ export VAULT_OIDC_ADDR=http://127.0.0.1:8250Export an environment variable for the
vaultCLI to authenticate with the Vault server.$ export VAULT_TOKEN=rootNote
For these tasks, you can use Vault's root token. However, it is recommended that root tokens are only used for enough initial setup or in emergencies. As a best practice, use an authentication method or token that meets the policy requirements.
The Vault server is ready.
Register Vault as a web app
An app registration allows Azure AD to identify Vault and the user.
Set the
AD_AZURE_DISPLAY_NAMEenvironment variable to a unique display name for Vault's app registration.$ export AD_AZURE_DISPLAY_NAME=vault-$(xxd -l 4 -p < /dev/random)Note
The example above uses
xxdand/dev/randomto generate a short unique string to use for the app name.Register a web app for Vault with two redirect URIs (also called
reply-urls). One URI is for Vault CLI access and the second is for UI access. Save the application ID to theAD_VAULT_APP_IDenvironment variable.$ export AD_VAULT_APP_ID=$(az ad app create \ --display-name ${AD_AZURE_DISPLAY_NAME} \ --web-redirect-uris "http://localhost:8250/oidc/callback" \ "${VAULT_ADDR}/ui/vault/auth/oidc/oidc/callback" | \ jq -r '.appId')Retrieve the application ID of the Microsoft Graph API, which allows you to access Azure service resources. This ID will be used to attach API permissions to the app registration.
$ export AD_MICROSOFT_GRAPH_API_ID=$(az ad sp list \ --filter "displayName eq 'Microsoft Graph'" \ --query '[].appId' -o tsv)Using the Microsoft Graph API ID, retrieve the ID of the permission for
GroupMember.Read.All.$ export AD_PERMISSION_GROUP_MEMBER_READ_ALL_ID=$(az ad sp show \ --id ${AD_MICROSOFT_GRAPH_API_ID} \ --query "oauth2PermissionScopes[?value=='GroupMember.Read.All'].id" -o tsv)Add the
GroupMember.Read.Allpermission to the application. This allows the application to read an Active Directory group and its users.$ az ad app permission add \ --id ${AD_VAULT_APP_ID} \ --api ${AD_MICROSOFT_GRAPH_API_ID} \ --api-permissions ${AD_PERMISSION_GROUP_MEMBER_READ_ALL_ID}=ScopeNOTE: If you would want to use UPN instead of email, you may need to add permissions such as
User.Readandprofile.Create a service principal to attach to the application. The service principal allows you to grant administrative consent from the Azure CLI.
$ az ad sp create --id ${AD_VAULT_APP_ID}Grant administrative consent for the application to access the Microsoft Graph API.
$ az ad app permission grant --id ${AD_VAULT_APP_ID} \ --api ${AD_MICROSOFT_GRAPH_API_ID} \ --scope ${AD_PERMISSION_GROUP_MEMBER_READ_ALL_ID}Retrieve the Azure tenant ID for the application and set it to the
AD_TENANT_IDenvironment variable.$ export AD_TENANT_ID=$(az ad sp show --id ${AD_VAULT_APP_ID} \ --query 'appOwnerOrganizationId' -o tsv)Reset the client secret for the application and set the password to the
AD_CLIENT_SECRETenvironment variable. You will need the secret to configure the OIDC auth method in Vault.$ export AD_CLIENT_SECRET=$(az ad app credential reset \ --id ${AD_VAULT_APP_ID} | jq -r '.password')
Update application group claims and ID tokens
To use AD groups to authenticate to Vault, you need to update the Vault application in Azure with a claim for group membership information.
Create a file named
manifest.jsonwith the specification for an ID token for an AD group.$ cat > manifest.json << EOF { "idToken": [ { "name": "groups", "additionalProperties": [] }, { "name": "email", "additionalProperties": [] } ] } EOFUpdate the application with the claims manifest in
manifest.jsonand setgroupMembershipClaimstoSecurityGroup. You can expand the group type to additional groups.$ az ad app update --id ${AD_VAULT_APP_ID} \ --set groupMembershipClaims=SecurityGroup \ --optional-claims @manifest.json
Create Vault policies for an example group
Every client token has policies attached to it to control its secret access. You must create the policies before defining them in the OIDC configuration.
Create an example Vault policy that allows an application development team to read and write secrets mounted at
secrets/.$ cat > kv-reader-policy.hcl << EOF path "secret/*" { capabilities = ["read", "list"] } EOFWrite the policy named
kv-readerto Vault.$ vault policy write kv-reader kv-reader-policy.hclEnable the key-value secrets engine at
secret/.$ vault secrets enable -path=secret -version=2 kvCreate a sample entry in the KV secrets engine.
$ vault kv put secret/azure hello=world
Configure Vault with the OIDC auth method
OIDC must be enabled and configured before it can be used. In this section, you
will configure OIDC for a role named app-dev, which application development
teams can use to log in and access secrets.
Set the
VAULT_LOGIN_ROLEenvironment variable toapp-dev. In your own configuration, you can change this role name.$ export VAULT_LOGIN_ROLE=app-devEnable the OIDC auth method on the Vault server.
$ vault auth enable oidcConfigure the OIDC auth method with the application ID, client secret, and tenant ID of your Vault application in Azure AD.
$ vault write auth/oidc/config \ oidc_client_id="${AD_VAULT_APP_ID}" \ oidc_client_secret="${AD_CLIENT_SECRET}" \ default_role="${VAULT_LOGIN_ROLE}" \ oidc_discovery_url="https://login.microsoftonline.com/${AD_TENANT_ID}/v2.0"Tip
Further information for configuring the OIDC auth method for use with Azure AD is available in the Azure Active Directory (AAD) section of the OIDC Provider Configuration documentation.
Add a role to Vault called
app-devthat uses the Vault policy to read secrets (kv-reader). It authenticates to Azure by a user's email. In addition, it passes thegroup_claimofgroupsthat were configured as part of the claims manifest. Theoidc_scopesshould be set to thehttps://graph.microsoft.com/.default, which is the Microsoft Graph API.$ vault write auth/oidc/role/${VAULT_LOGIN_ROLE} \ user_claim="email" \ allowed_redirect_uris="http://localhost:8250/oidc/callback" \ allowed_redirect_uris="${VAULT_ADDR}/ui/vault/auth/oidc/oidc/callback" \ policies="kv-reader" \ oidc_scopes="https://graph.microsoft.com/.default"Note
If you want to use UPN instead of user email, change the
user_claimfield toupn.Record the current Vault token.
$ echo $VAULT_TOKEN VAULT_TOKEN=hvs.REDACTEDYou will use this to re-authenticate with Vault to add additional OIDC configuration for external groups.
Unset the
VAULT_TOKENenvironment variable. When you authenticate with Azure you will receive a new token based on the OIDC configuration.$ unset VAULT_TOKENTry to log into the server with the OIDC auth method. If it is successful, the command launches a browser to Azure for you to log in and return a Vault token.
$ vault login -method=oidc role="app-dev" Complete the login via your OIDC provider. Launching browser to: https://login.microsoftonline.com/... Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token hvs.REDACTED token_accessor u58XsOYz2I5T1GmqwsaaOpsP.WEwzy token_duration 1h token_renewable true token_policies ["default" "kv-reader"] identity_policies [] policies ["default" "kv-reader"] token_meta_role app-devYou successful authenticated to Vault using Azure credentials. The
kv-readerpolicy was applied because this was configured as the default policy for theapp-devrole.As part of the
app-devrole, you should be able to accesssecret/.$ vault kv list secret Keys ---- azureThe secret created earlier is listed.
Set up Vault external group and AD group
With OIDC setup correctly, you will now create an Active Directory group for the security team to write secrets. Connect this Azure AD group to a Vault policy, which will allow any users in the Azure AD group to log into Vault by email and write secrets.
Export the token that was unset prior to testing the OIDC configuration.
$ export VAULT_TOKEN=<actual-token-value>Create a policy file named
secops.hcl.$ tee secops.hcl <<EOF # Manage k/v secrets path "/secret/*" { capabilities = ["create", "read", "update", "delete", "list"] } EOFCreate a policy named
secopswith the policy defined insecops.hcl.$ vault policy write secops secops.hclCreate an Azure AD group.
$ az ad group create \ --display-name hashicorp-secops-$AD_AZURE_DISPLAY_NAME \ --mail-nickname hashicorp-secops-$AD_AZURE_DISPLAY_NAMEAdd the user authenticated with the Azure CLI to the new AD group.
$ az ad group member add --group hashicorp-secops-$AD_AZURE_DISPLAY_NAME \ --member-id $(az ad signed-in-user show | jq -r .id)Create a role named
secops.$ vault write auth/oidc/role/secops \ user_claim="email" \ allowed_redirect_uris="http://localhost:8250/oidc/callback" \ allowed_redirect_uris="${VAULT_ADDR}/ui/vault/auth/oidc/oidc/callback" \ groups_claim="groups" \ policies="kv-reader" \ oidc_scopes="https://graph.microsoft.com/.default"Create an external group named
secopsin the Vault identity secrets engine that references thesecopspolicy and set the group ID in theVAULT_GROUP_IDenvironment variable.$ export VAULT_GROUP_ID=$(vault write \ -field=id -format=table \ identity/group \ name="secops" \ type="external" \ policies="secops")Retrieve Vault's OIDC accessor ID and set it to the
VAULT_OIDC_ACCESSOR_IDenvironment variable.$ export VAULT_OIDC_ACCESSOR_ID=$(vault auth list -format=json | \ jq -r '."oidc/".accessor')Retrieve the
objectIdActive Directory group you previously create and save it as an environment variable.$ AZ_GROUP_ID=$(az ad group show --group hashicorp-secops-$AD_AZURE_DISPLAY_NAME | jq .id -r)Create a group alias using the ID of the AD security group.
$ vault write identity/group-alias name="$AZ_GROUP_ID" \ mount_accessor="$VAULT_OIDC_ACCESSOR_ID" \ canonical_id="$VAULT_GROUP_ID"Unset the
VAULT_TOKENenvironment variable. When you authenticate with Azure you will receive a new token based on the OIDC configuration.$ unset VAULT_TOKENTry to log into the server with the OIDC auth method as a member of the AD group you configured with Vault. If it is successful, the command launches a browser to Azure for you to log in and return a Vault token.
$ vault login -method=oidc role="secops" Complete the login via your OIDC provider. Launching browser to: https://login.microsoftonline.com/...snip... Waiting for OIDC authentication to complete... Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token hvs.REDACTED token_accessor 6OACh6sPly1ogpRV5RY5zmos.CGhuZ token_duration 1h token_renewable true token_policies ["default" "kv-reader"] identity_policies ["secops"] policies ["default" "kv-reader" "secops"] token_meta_role secopsThe
secopspolicy is assigned through the AD group membership.As part of the
secopsrole that is connected to the AD group, you should be able to write secrets to thesecret/path.$ vault kv put secret/groups oidc=ftw === Secret Path === secret/data/groups ======= Metadata ======= Key Value --- ----- created_time 2023-01-09T15:22:21.854306825Z custom_metadata <nil> deletion_time n/a destroyed false version 1You are now able to write secrets based on the
secopspolicy assigned to the user.
Cleanup
To avoid unnecessary charges and having unused security resources in your Azure account, remove the following:
Delete the Vault Azure app.
$ az ad app delete --id $AD_VAULT_APP_IDDelete the Azure AD group
$ az ad group delete --group hashicorp-secops-$AD_AZURE_DISPLAY_NAMECreate an array of the local environment variables.
$ learnVariables=( \ AD_AZURE_DISPLAY_NAME \ AD_VAULT_APP_ID \ AD_MICROSOFT_GRAPH_API_ID \ AD_PERMISSION_GROUP_MEMBER_READ_ALL_ID \ AD_TENANT_ID \ AD_CLIENT_SECRET \ VAULT_LOGIN_ROLE \ VAULT_GROUP_ID \ VAULT_OIDC_ACCESSOR_ID \ )Unset the environment variables.
for v in ${learnVariables[@]}; do unset $v done
Summary
In this tutorial, you configured Vault's OIDC auth method to authenticate a user by using a group in Azure Active Directory. This allowed the user to read and list secrets from Vault.


