Enable multi factor authentication (MFA) login
Multi-Factor Authentication (MFA) is a mechanism for outsourcing the secondary authentication for your website (or other product) to a third party one-time key provider. With MFA a user is granted access to a website or application only after successfully presenting two or more pieces of evidence (or factors) to an authentication. MFA has been supported in Vault Enterprise with the Governance and Policy Module since Release Version 0.8.
Challenge
MFA is expected in any modern security product as a baseline feature. All Vault users (Community Edition practitioners, developers, admins, and operators) seek to secure highly sensitive information using strong security practices such as MFA. It is a key to zero-trust security framework. However, Vault Community Edition users are unable to get the benefit of security authentication best practices via MFA without switching to an Enterprise license.
Solution
Vault version 1.10.0 introduces a new Login MFA integration to allow for an additional authentication factor when authenticating to Vault.
The following MFA methods are currently supported:
- Time-Based One-Time Password (TOTP)
- Okta
- Duo
- PingIdentity
In the diagram, the workflow described in this tutorial for Two-Phase MFA is shown.
The admin persona configures the Vault and PingID environments.
The user persona uses the Vault API, CLI, or UI and the PingID application on an enrolled device.
The user persona attempts authentication with Vault.
Vault returns a message advising that the authentication requires MFA.
The PingID application returns a code which can be used as an extra authentication factor.
The user persona validates their authentication with the code returned from the PingID application.
Vault verifies the code through its MFA method integration, and if successful, the authentication attempt succeeds and the user persona receives a token.
Note
The Login MFA integration introduced in version 1.10.0 is a new solution, and should not be confused with the legacy open source MFA or Enterprise Step Up MFA solutions. The solution covered in this tutorial is the preferred way to enable MFA for auth methods in all editions of Vault version 1.10.0 or greater.
Target audience
This tutorial is for demonstrating workflows both to Vault admins who enable and configure authentication methods and MFA methods, and to users who are authenticating with Vault.
It uses the PingIdentity MFA method, and shares some detail on configuring the PingOne Identity Repository, but you can use any of the supported MFA methods and their associated resources to configure the production solution that you require.
Prerequisites
This lab was tested on macOS using an x86_64 based processor. If you are running macOS on an Apple silicon-based processor, use a x86_64 based Linux virtual machine in your preferred cloud provider.
To perform the steps in this tutorial, you need the following:
- Docker
- Working internet connection from Docker host
- PingIdentity PingOne account you can use a trial account to follow the steps in this tutorial.
- PingID application installed; this tutorial uses PingID for mobile on iOS.
- openssl CLI tool
- jq for parsing JSON responses
Scenario introduction
You will assume two personas in this tutorial to experience an end-to-end example usage of MFA when authenticating to Vault:
As the admin persona, you will first configure PingID for Enterprise using for example, the PingOne identity repository. You will then generate a properties file for integration with PingFederate and other clients that you will use when enabling the MFA method for Vault.
You will also enable an instance of the username and password auth method for authentication.
As the user persona, you will authenticate to Vault with the Username and Password auth method to validate that it is functional.
You will also enroll your application and device in the PingID application for the user persona using the PingID website.
Note
It is important that the username in PingID matches the username for the Vault auth method. You must also use the same domain name you used to sign up for your PingID account in places where this tutorial uses example.com
.
As the admin persona, you will enable a MFA method that uses the PingOne service using the Two-Phase Login approach. You will then create a login enforcement for the username and password auth method so that all users who authenticate with Vault using the auth method must also provide an additional authentication factor from a PingID application.
As the user persona, you will authenticate to Vault with the Username and Password auth method again. This will prompt you to provide an additional factor from the PingID application in the application associated to your username.
Lab setup
Before you can begin the scenario, you need to prepare your local environment and the PingOne environment.
Vault server container
Start a Vault dev mode server Docker container.
$ docker run \ --cap-add=IPC_LOCK \ --detach \ --name learn-vault \ -p 8200:8200 \ --rm \ vault server -dev -dev-root-token-id root
The container will run detached, publish the Vault API port to localhost, and remove itself when stopped.
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.
Create an alias to use the vault
binary in the container from your Docker host.
$ alias vault='docker exec --env VAULT_ADDR=http://127.0.0.1:8200 learn-vault vault "$@"'
Export the VAULT_ADDR
environment variable locally to address the Vault server container. This is required for both future vault
CLI and HTTP API examples.
$ export VAULT_ADDR=http://127.0.0.1:8200
Validate that you can use the initial root token for authentication with Vault.
For consistency and convenience, set the initial root token value in the environment variable ROOT_TOKEN
:
$ ROOT_TOKEN=root
$ VAULT_TOKEN=$ROOT_TOKEN vault token lookup | grep policiespolicies [root]
Since the token lookup returns root policies, you can consider your access to the Vault server successful.
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.
If you experience any issues with this step, check the Docker logs with docker logs learn-vault
.
The Vault server is now ready for use.
PingOne setup
(As the admin persona)
You need to access your PingIdentity account and perform some initial setup tasks to prepare for the scenario steps. Sign into PingIdentity and during initial setup, choose the PingOne Identity Repository when prompted:
Next, under Setup, navigate to PingID → Client Integration.
Under Integrate with PingFederate and Other Clients click Download to download the pingid.properties
file. If there is not already a properties file available, you can click Generate to generate one prior to downloading.
Note
Keep the downloaded properties file at hand as it will be used later when enabling the Vault MFA method.
This tutorial uses the PingID mobile application for a second authentication factor.
You can now add the user persona alice as a user, and enroll the PingID device you will use as the user persona with the PingID application.
From the PingOne dashboard, click USERS, then click the Add Users button and Create New User.
Complete the required user details.
Click Save to add the user.
Click Dashboard and under Notifications, click the application portal URL found within the Configure Single Sign-on notification.
This will route you to the PingID user application, where you need to sign out from the admin persona account, and then sign in as the user persona.
Click your user avatar for the drop-down menu and click Sign Off.
Once signed in, you will be prompted to reset your password. Enter the current password and the new one and click Submit.
Click your user avatar for the drop-down menu. Click Devices to add your device on which you will use the PingID application.
Click the Add button and a dialog containing a QR code and pairing code will appear. Use the PingID application on your user persona device with the QR code or pairing code to enroll it.
Once your Vault server container is up and you are able to validate that your initial root token works, and your PingOne account is set up with an enrolled device, you can proceed to the scenario tasks.
Scenario tasks
Perform the scenario tasks as each persona to work through the scenario.
Enable username and password auth method
(As the admin persona)
Enable an instance of the username and password auth method using default path, and add the user persona as a user.
Enable the username and password auth method.
$ VAULT_TOKEN=$ROOT_TOKEN vault auth enable userpassSuccess! Enabled userpass auth method at: userpass/
Set the username and password auth method accessor value in the USERPASS_ACCESSOR
environment variable for use in configuring the MFA method later.
$ USERPASS_ACCESSOR=$(VAULT_TOKEN=$ROOT_TOKEN vault auth list | grep userpass | awk '{print $3}')
Add the user persona alice
to the user name and password auth method.
$ VAULT_TOKEN=$ROOT_TOKEN vault write auth/userpass/users/alice \ password=kQ3BlE+5M1libWJc
Successful output:
Success! Data written to: auth/userpass/users/alice
Create an entity and alias
(As the admin persona)
You need to create an Identity secrets engine entity and alias to correspond to the user persona. You will later make use of this entity alias when configuring the MFA method.
For convenience the value of the entity ID will be set in the ENTITY_ID
environment variable.
$ ENTITY_ID=$(VAULT_TOKEN=$ROOT_TOKEN vault write -format=json identity/entity name="alice" | jq -r ".data.id")
Check that ENTITY_ID
contains the value.
$ echo $ENTITY_ID929e93d3-6fa3-878c-5ab3-4f668e973b8c
Create the entity alias; remember that the name
value must match the name of both the entity you just created, and the user you created in PingID.
$ VAULT_TOKEN=$ROOT_TOKEN vault write identity/entity-alias \ name="alice" \ canonical_id="$ENTITY_ID" \ mount_accessor="$USERPASS_ACCESSOR"
Successful output:
Key Value--- -----canonical_id f4661ef1-f7b0-5e35-4038-947e14ec754fid 43815b7b-7499-ce28-60bc-65c1850f9180
Tip
If you are unfamiliar with Identity, entities, and aliases, review the Identity: Entities and Groups tutorial.
Authenticate to Vault
(As the user persona)
Use the username and password auth method to authenticate to Vault.
$ vault login -method userpass username=alice password=kQ3BlE+5M1libWJc
Successful output:
Success! You are now authenticated. The token information displayed belowis 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.CAESIAXGggoMOCvroQj8Tyd2MbWeXqpX_ANZe5c9Ad0W9OxaGh4KHGh2cy42TDRKOGl1Z3FzSnBSNDRHbTRLTzBROU0token_accessor ZmJytU3gqTa1jilXFdGuIn4stoken_duration 768htoken_renewable truetoken_policies ["default"]identity_policies []policies ["default"]token_meta_username alice
You are successfully authenticated to Vault as the user persona, alice.
Notice that you are not yet prompted for any additional authentication methods.
Enable MFA method
(As the admin persona)
Now that the user persona can authenticate with the username and password auth method, let's enable the MFA method and create a login enforcement on the auth method.
First, you need to convert the PingOne pingid.properties
file that you downloaded earlier into a suitable base64 representation for use when configuring the MFA method. You can use the openssl
tool for this purpose.
$ PINGID_PROPERTIES="$(openssl base64 -A -in pingid.properties)"
Next, enable the MFA method.
Write the MFA configuration to enable it. For convenience and later reference, the method_id
value will be set in the environment variable METHOD_ID
.
$ METHOD_ID=$(VAULT_TOKEN=$ROOT_TOKEN vault write -field method_id \ identity/mfa/method/pingid \ username_template="{{identity.entity.aliases.$USERPASS_ACCESSOR.name}}@example.com" \ settings_file_base64=$PINGID_PROPERTIES)
IMPORTANT
in this example, the user is alice@example.com
, but your user persona's actual domain value should match the domain you used when signing up and creating your own account in PingID. If these values do not match, you will likely encounter a 'username may be incorrect' error.
The method_id
value is now set in the environment variable:
$ echo $METHOD_ID745b06da-4d08-cf0a-2ae3-4512f506a179
Note
If you encounter a permission denied error here, be sure to login again with the root token as previously directed.
Create login enforcement
Create a login enforcement by specifying the mfa_method_id
value and tie it to the username and password auth method by specifying the accessor as the value of auth_method_accessors
.
$ VAULT_TOKEN=$ROOT_TOKEN vault write identity/mfa/login-enforcement/learn \ mfa_method_ids="$METHOD_ID" \ auth_method_accessors="$USERPASS_ACCESSOR"
Successful output:
Success! Data written to: identity/mfa/login-enforcement/learn
Note
The mfa_method_ids
parameter is an array. You can specify more than one MFA method, and they will be ORed together, meaning that a successful authentication from any of those methods will qualify as an acceptable additional factor.
There are other possible fields that can be used for specifying what to enforce the MFA method on as well: auth_method_types
, identity_group_ids
, or identity_entity_ids
. Review the MFA Login documentation for full details on how to use them.
Authenticate to Vault
Now that the MFA method is enabled, and the login enforcement for authentications against the username and password auth method is defined, try another authentication attempt with the auth method.
(As the user persona)
Use the username and password auth method to authenticate to Vault.
$ vault login -method userpass username=alice password=kQ3BlE+5M1libWJc
Sucessful output:
Asking Vault to perform MFA validation with upstream service. You should receive a push notification in your authenticator app shortly
The CLI automatically passes the MFA method details during authentication. You should receive a push notification from PingID and as soon as you slide up to approve it, you will be authenticated and receive a token.
You should receive a push notification from the PingID application.
Use the PingID application to acknowledge the request.
Key Value--- -----token hvs.CAESIAIN8EdVhhZ38AT79WKyrC8Dy5c826Mv0QfREiYEcmX_Gh4KHGh2cy5wTEViNjNxSGdxWGR3amFaTFhUYVdRM2ktoken_accessor 6MwKJjrwjLSoOxPPsDNs9cKvtoken_duration 768htoken_renewable truetoken_policies ["default"]identity_policies []policies ["default"]token_meta_username alice
Success! You are now authenticated. The token information displayed belowis already stored in the token helper. You do NOT need to run "vault login"again. Future Vault requests will automatically use this token.WARNING! The following warnings were returned from Vault: * A login request was issued that is subject to MFA validation. Please make sure to validate the login by sending another request to mfa/validate endpoint.Key Value--- -----token n/atoken_accessor n/atoken_duration ∞token_renewable falsetoken_policies []identity_policies []policies []
The first authentication attempt demonstrates the response from Vault.
Authenticate again, but this time store the result in the environment variable MFA_REQID
:
$ MFA_REQID=$(curl \ --silent \ --request POST \ --data '{"password":"kQ3BlE+5M1libWJc"}' \ $VAULT_ADDR/v1/auth/userpass/login/alice \ | jq -r '.auth.mfa_requirement.mfa_request_id')
Check the value of MFA_REQID
:
$ echo $MFA_REQID953cdfee-f5c6-ab92-1b33-5c6e0b908f24
Use the PingID application to get a code for validating your Vault authentication attempt.
Note the passcode from your PingID application and set it as the value to the PCODE environment variable. For example, the value from the screenshot of the PingID application is used.
$ PCODE=358145
Validate the authentication.
$ curl \ --silent \ --data "{\"mfa_request_id\":\"$MFA_REQID\", \"mfa_payload\":{\"$METHOD_ID\":[\"$PCODE\"]}}" \ "$VAULT_ADDR/v1/sys/mfa/validate" | jq
You should receive a push notification from the PingID application.
Confirm the notification by sliding up in the application.
Successful output:
{ "request_id": "06987404-e1c4-70d1-9a77-410b1e977e35", "lease_id": "", "renewable": false, "lease_duration": 0, "data": null, "wrap_info": null, "warnings": null, "auth": { "client_token": "hvs.CAESIFbP0-3cADd60QBOkj3hDTlT0uhCM15iASRHvAe-452DGh4KHGh2cy5kZHJSQm9KQ25aNlFPWmdVWHZPdERyT0k", "accessor": "UIKNXc33lLlQAXt8isZ6t5vT", "policies": [ "default" ], "token_policies": [ "default" ], "metadata": { "username": "alice" }, "lease_duration": 2764800, "renewable": true, "entity_id": "6e9e0a0d-daf6-5cce-21b2-2b5680a26d58", "token_type": "service", "orphan": true, "mfa_requirement": null, "num_uses": 0 }}
The authentication is successful and a Vault token is received.
Vault validates your authentication and returns a token.
This demonstrates the Two-Phase approach to using Vault MFA methods.
You can also use the Single-Phase approach, and include an MFA code with your initial authentication attempt. Review the Login MFA documentation to learn more.
Clean Up
Stop the Docker container.
$ docker stop learn-vault
Unalias the
vault
alias.$ unalias vault
Unset the environment variables.
$ unset ENTITY_ID METHOD_ID MFA_REQID PCODE ROOT_TOKEN USERPASS_ACCESSOR VAULT_ADDR
Remove created files.
$ rm -f validate-payload.json
Summary
As the admin persona, you learned how to enable and configure Login MFA with the PingID MFA method.
As the user persona, you learned how to use a Login MFA method when authenticating to Vault.
You can learn more about Vault authentication and auth methods in the Manage Authentication Methods tutorial, and the Auth Methods documentation.