NOTE: This tutorial showcases the Vault UI to configure the database secrets engine. The UI support for the database secrets engine is new in Vault 1.7, and currently, MongoDB is the only database the UI supports. For other database types and an earlier version of Vault, use either CLI or API to configure.
Data protection is a top priority, and database credential rotation is a critical part of any data protection initiative. When a system is attacked by hackers, continuous credential rotation becomes necessary and needs to be automated.
Vault's database secrets engine generates database credentials dynamically based on user-defined roles. The database administrator can pre-define the time-to-live (TTL) of the database credentials to enforce its validity so that they are automatically revoked when they are expired.
Each app instance can get unique credentials that they don't have to share. By making those credentials short-lived, you reduce the chance that they might be compromised. If an app was compromised, the credentials used by the app can be revoked rather than changing more global sets of credentials.
»Personas
The end-to-end scenario described in this tutorial involves two personas:
admin
with privileged permissions to configure secrets enginesVault clients
(users, apps, systems, etc.) read the secrets from Vault
»Prerequisites
To perform the tasks described in this tutorial, you need to have:
- Docker to run MongDB
- Vault 1.7 or later
»Start MongoDB
The tutorial requires a MongoDB database. Docker provides a MongoDB server image that satisfies this requirement.
NOTE: This tutorial works for an existing MongoDB database given appropriate credentials and connection information.
Create a MongoDB database with a root user named mdbadmin
with the password
hQ97T9JJKZoqnFn2NXE
.
$ docker run -d \
-p 0.0.0.0:27017:27017 -p 0.0.0.0:28017:28017 \
--name=mongodb \
-e MONGO_INITDB_ROOT_USERNAME="mdbadmin" \
-e MONGO_INITDB_ROOT_PASSWORD="hQ97T9JJKZoqnFn2NXE" \
mongo
The database is now available to experiment with the database secrets engine.
»Start Vault
In another terminal, start a Vault dev server with root
as the root token.
$ vault server -dev -dev-root-token-id=root
The 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 vault
CLI to address the Vault server.
$ export VAULT_ADDR=http://127.0.0.1:8200
Login with the root token.
$ vault login root
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 root
token_accessor n9CYvD0GK3iV6nwAOZQAy9Md
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
NOTE: 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.
»Scenario Introduction
In this tutorial, you will configure the MongoDB secrets engine and create a "tester" role that has read and write permissions.
- Enable the database secrets engine - admin task
- Configure MongoDB secrets engine - admin task
- Create a role - admin task
- Request MongoDB credentials - Vault clients to perform
This tutorial is running Vault in development mode, and use the root
token.
Be sure to read the Policy requirements section at the
end.
»Enable the database secrets engine
(Persona: admin)
The database secrets engine generates database credentials dynamically based on configured roles.
Enter http://127.0.0.1:8200/ui in a browser to launch the Vault UI.
Enter
root
in the Token field and click Sign In.Select Enable new engine.
Select Databases from the list, and then click Next.
Enter
mongodb
in the Path field.Click Enable Engine to complete.
The database secrets engine is enabled at mongodb/
.
»Configure MongoDB secrets engine
(Persona: admin)
The database secrets engine supports many databases through a plugin interface.
To use a MongoDB database with the secrets engine requires further
configuration with the mongodb-database-plugin
plugin and
connection information.
Select Create connection in the Connections tab for
mongodb
.Select MongoDB from the Database plugin drop-down list.
Enter
mongo-test
in the Connection Name field.Enter the following in the Connection url field:
mongodb://{{username}}:{{password}}@127.0.0.1:27017/admin?tls=false
Enter
mdbadmin
in the Username andhQ97T9JJKZoqnFn2NXE
in the Password text fields.Click Create database. When prompted, click Rotate and enable to continue.
This is an optional step; however, it is recommended to rotate the root user's password. Read the Database Root Credential Rotation tutorial to learn about rotating the root credential immediately after the initial configuration of each database.
Select mongodb.
Select the Overview tab.
Once you set up a database connection, the overview page displays the current configuration summary.
The Vault generated password has a default pattern which may not adhere to your organization's password requirements. Read the User Configurable Password Generation for Secret Engines tutorial to learn about configuring the Vault-generated database password schema.
»Create a role
(Persona: admin)
A role is a logical name within Vault that maps to database credentials. Some applications may need read-only permissions, and others may require read and write permissions. Practice the principle of least privilege and create a role appropriately for each database client.
In this step, you will create a "tester" role with time-to-live (TTL) set to 1 hour, and the maximum TTL is 24 hours. This allows Vault to revoke the credentials automatically once they reach the TTL.
In the
mongodb
overview page, select Create new.Enter
tester
in the Role name field.Enter
mongo-test
in the Database name field.Select dynamic from the Type of role drop-down list.
Read the Database Static Roles and Credential Rotation tutorial to learn about static roles.
Slide the toggle switch for Generated credential's Time-to-Live (TTL) and Generated credential's maximum Time-to-Live (Max TTL) to set the value to 1 hour and 24 hours respectively.
Enter the following in the Creation statement field.
{ "db": "admin", "roles": [ { "role": "readWrite" }, { "role": "read", "db": "foo" } ] }
The Create Role page should look as below:
Click Create Role to complete.
When you return to the mongo-test configuration page, the
tester
role is added to the Allowed roles list.
Now, it is ready to dynamically generate database credentials to connect with
the mongodb
database.
»Request MongoDB credentials
(Persona: Vault clients)
To connect to the MongoDB, Vault clients request Vault to dynamically generate the
database credentials based on its role. In this case, the tester
role.
This step uses the root
token for demonstration. In reality, Vault clients
would never use Vault's root
token. After learning the basic steps, continue
onto the Policy requirements section.
Return to the mongo-test configuration page by selecting mongodb > mongo-test.
Select the tester role.
Select Generate credentials.
This presents the generated lease. Click on the copy to clipboard icon to copy the generated username and password.
NOTE: From the mongodb overview page, enter the role name in the Get Credentials field and click Get Credentials to accomplish the same. The Get Credentials works for any role configured on the mongodb.
The MongoDB credentials are displayed as username and password. The credentials are identified within Vault by the lease ID.
Read the customize the generated username schema section for additional discussion.
»Validation
Connect to the MongoDB database using the Vault generated credentials.
$ docker exec -it mongodb mongo --username <username> --password <password>
Example:
$ docker exec -it mongodb mongo \
--username v-token-tester-fO7smPyTgCrySIgQNrst-1615451034 \
--password IePqQ26-EyIk6zEA637w
MongoDB shell version v4.4.4
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("aabf31e2-27f9-4ac5-9145-710dbd84ef8d") }
MongoDB server version: 4.4.4
You can list databases.
> show dbs;
admin 0.000GB
Enter exit
to exit out of the Docker container.
»Policy requirements
Each persona requires a different set of capabilities. These are expressed in policies. If you are not familiar with policies, complete the policies tutorial.
»Example policy for admin
The admin persona needs to be able to set up the database secrets engine.
- Enable the database secrets engine at
mongodb
(sys/mounts/mongodb
) - Configure the MongoDB connection (
mongodb/config/mongo-test
) - Create a role (
mongodb/roles/tester
)
In addition, the admin needs to set up so that the Vault clients can talk to Vault.
- Create policies for the Vault clients (
sys/policies/acl/<policy_name>
) - Enable an auth method for the Vault clients to login with Vault (
sys/auth/<auth_method>
) - Configure the auth method (
auth/<auth_method>
)
# Enable secrets engines at any path
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Manage the database secrets engine enabled at `mongodb` path
path "mongodb/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Create ACL policies for Vault clients
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
#-----------------------------------------
# Example: Use AppRole auth method
#-----------------------------------------
# Eanble approle auth method at 'approle'
path "sys/auth/approle" {
capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]
}
# List all enabled auth methods
path "sys/auth" {
capabilities = [ "read", "list" ]
}
# Create and manage roles
path "auth/approle/role/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
#------------------------------------------
# Create token for testing
#------------------------------------------
# Create tokens
path "auth/token/create" {
capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]
}
You should be able to complete this tutorial using a token with the above policy attached. If you are not familiar with creating policies, read the Vault Policies tutorial.
»Example policy for Vault clients
The Vault clients persona needs to be able to request credentials from Vault.
# Required: Get credentials from the database secrets engine for 'tester' role.
path "mongodb/creds/tester" {
capabilities = [ "read", "update"]
}
# Recommended: List all dynamic and static roles
path "mongodb/roles" {
capabilities = [ "list" ]
}
path "mongodb/static-roles" {
capabilities = [ "list" ]
}
»Test the policy
Create an
clients
policy.$ vault policy write clients -<<EOF # Required: Get credentials from the database secrets engine for 'tester' role. path "mongodb/creds/tester" { capabilities = [ "read", "update"] } # Recommended: List all dynamic and static roles path "mongodb/roles" { capabilities = [ "list" ] } path "mongodb/static-roles" { capabilities = [ "list" ] } EOF
Create a token with the
clients
policy attached.$ vault token create -policy=clients -ttl=8h
Example output:
Key Value --- ----- token s.ad3DG8zxyPcqq4cvrMzsIxr9 token_accessor lUcfmpppZVO1Sr6f6gwXznaF token_duration 8h token_renewable true token_policies ["clients" "default"] identity_policies [] policies ["clients" "default"]
Copy the generated
token
value. In this example, the token iss.ad3DG8zxyPcqq4cvrMzsIxr9
.Return to the Vault UI (http://127.0.0.1:8200/ui). Since you are logged in as
root
, sign out.Enter the generated token to sign in.
Select mongodb/.
Under Get Credentials, enter
tester
in the Role to use field.Click Get Credentials.
»Customize the generated username schema
NOTE: To customize the Vault-generated username format, you must run Vault 1.7 or later.
In the request MongoDB credentials section, you
saw the Vault generated username and password. The generated username looked
similar to v-token-tester-6iRIcGv8tLpu816oblPY-1556567086
. This may be less
obvious to differenciate a username from another when you are auditing the
database access.
Update the mongo-test
connection configuration to specify that the generated
database username to have the format of
mongo-<role_name>-<random_char_length_8>
.
In this tutorial, you created tester
role; therefore, the <role_name>
is
tester
.
Update the
mongo-test
connection configuration with username template.$ vault write mongodb/config/mongo-test \ plugin_name=mongodb-database-plugin \ allowed_roles="tester" \ connection_url="mongodb://{{username}}:{{password}}@127.0.0.1:27017/admin?tls=false" \ username="mdbadmin" \ password="hQ97T9JJKZoqnFn2NXE" \ username_template="mongo-test-{{.RoleName}}-{{random 8}}"
The
username_template
parameter specifies the username format ("mongo-test-{{.RoleName}}-{{random 8}}"
). The{{.RoleName}}
returns the role name (tester
) used to request a lease. The{{random 8}}
returns 8 random characters.Request a new set of credentials.
$ vault read mongodb/creds/tester
Example output:
Key Value --- ----- lease_id mongodb/creds/tester/JPQtefXthLkh7hE8vPpBY5Zw lease_duration 24h lease_renewable true password GHVxvy6gDf7zD9Kxk-8f username mongo-test-tester-vLjw7VJI
The generated username (
mongo-test-tester-vLjw7VJI
) adheres to the username template.
To customize the password rules, read the User Configurable Password Generation for Secret Engines tutorial.
»Next steps
There are some tools available to help integrate your applications with Vault's database secrets engine. Using those tools, the existing applications may require minimum to no code change to work with Vault.
Refer to the following tutorials:
- Direct Application Integration
- Using HashiCorp Vault C# Client with .NET Core
- Vault Agent Templates
- Vault Agent Caching