Database secrets engine with MongoDB
Data protection is a top priority, and database credential rotation is a critical part of any data protection initiative. When hackers attack a system, continuous credential rotation becomes necessary, and you should strive to automate the process.
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 expire.
Each app instance can get unique credentials that they don't have to share. By making those credentials short-lived, you reduce the chance of compromise. If an attacker compromises an app, 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
Note
This lab works on macOS using x86_64 based processors. If you are running macOS on an Apple silicon processor, consider using a x86_64 based Linux virtual machine in your preferred cloud provider.
To perform the tasks described in this tutorial, you need to have:
- Docker to run MongDB
- Vault installed
- jq installed
- ngrok installed and configured with an auth token (required for HCP Vault Dedicated)
Lab setup
Start MongoDB
The tutorial requires a MongoDB database. Docker provides a MongoDB server image that you will use in this lab.
Note
This tutorial also works for an existing MongoDB database given appropriate credentials and connection information.
Create a MongoDB database with a root user named
mdbadmin
with the passwordhQ97T9JJKZoqnFn2NXE
.$ 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 rootSuccess! 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 roottoken_accessor n9CYvD0GK3iV6nwAOZQAy9Mdtoken_duration ∞token_renewable falsetoken_policies ["root"]identity_policies []policies ["root"]
Note
For these tasks, you can use Vault's root token. That said, you should use root tokens primarily for initial setup or in emergencies. As a best practice, use an authentication method or token that meets the policy requirements.
Export an environment variable for the
root
token.$ export VAULT_TOKEN=root
Export an environment variable for the MongoDB address.
$ export MONGODB_URL=127.0.0.1:27017
You are ready to proceed with the tutorial.
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.
Open a web browser and launch the Vault UI (the address is the same as
VAULT_ADDR
).Enter the token in the Token field and click Sign In (the token is the same as
VAULT_TOKEN
).Select Enable new engine.
Select Databases from the list, and then click Next.
Enter
mongodb
in the Path field.Click Enable Engine to complete.
You enabled the database secrets engine at mongodb/
.
Configure MongoDB secrets engine
(Persona: admin)
The database secrets engine supports popular 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 replacing
<host:port>
with the value from theMONGODB_URL
environment variable.mongodb://{{username}}:{{password}}@<host:port>/admin?tls=false
Enter
mdbadmin
in the Username andhQ97T9JJKZoqnFn2NXE
in the Password text fields.Click Create database.
When prompted, click Enable without rotating to continue.
This is an optional step; you should rotate the root user's password in production use. The rest of this tutorial relies on the password you set when staring the MongoDB container, so you should skip this step to complete the tutorial.
Read the Database Root Credential Rotation tutorial to learn about rotating the root credential 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 just need read permissions, and others may require read and write permissions. Practice the principle of least privilege and create a role appropriately for each database client.
Note
Important: when you define the role in a production deployment, you must create user creation_statements and revocation_statements, which are valid for the database you've configured. If you do not specify statements appropriate to creating, revoking, or rotating users, Vault inserts generic statements which can be unsuitable for your deployment.
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.
Verify Generated credential's Time-to-Live (TTL) and Generated credential's maximum Time-to-Live (Max TTL) is to set the value to 1 hour and 1 day 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.
Vault can now dynamically generate database credentials useful for connecting to
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 do the same. The Get Credentials works for any role configured on the mongodb.
The MongoDB credentials are a username and a password. Vault identifies the credentials by their 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 mongosh --username <username> --password <password>
Example:
$ docker exec -it mongodb mongosh \ --username v-token-tester-fO7smPyTgCrySIgQNrst-1615451034 \ --password IePqQ26-EyIk6zEA637wMongoDB shell version v4.4.4connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodbImplicit 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, and you use ACL policies to enforce those capabilities. 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
)
An admin needs to set up the Vault clients so they can communicate with 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 pathpath "sys/mounts/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}# Manage the database secrets engine enabled at `mongodb` pathpath "mongodb/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}# Create ACL policies for Vault clientspath "sys/policies/acl/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}#-----------------------------------------# Example: Use AppRole auth method#-----------------------------------------# Enable approle auth method at 'approle'path "sys/auth/approle" { capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]}# List all enabled auth methodspath "sys/auth" { capabilities = [ "read", "list" ]}# Create and manage rolespath "auth/approle/role/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}#------------------------------------------# Create token for testing#------------------------------------------# Create tokenspath "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 rolespath "mongodb/roles" { capabilities = [ "list" ]}path "mongodb/static-roles" { capabilities = [ "list" ]}
Create a client policy
Select Policies and then Create ACL policy.
Enter
clients
in the Name field.Copy the policy and paste it into the Policy text box.
# Required: Get credentials from the database secrets engine for 'tester' role.path "mongodb/creds/tester" { capabilities = [ "read", "update"]}# Recommended: List all dynamic and static rolespath "mongodb/roles" { capabilities = [ "list" ]}path "mongodb/static-roles" { capabilities = [ "list" ]}
Click Create policy.
Log out of the Vault UI and switch to the terminal session you started in the Lab setup section.
Create a token with the
clients
policy attached.$ vault token create -policy=clients -ttl=8h
Example output:
Key Value--- -----token hvs.ad3DG8zxyPcqq4cvrMzsIxr9token_accessor lUcfmpppZVO1Sr6f6gwXznaFtoken_duration 8htoken_renewable truetoken_policies ["clients" "default"]identity_policies []policies ["clients" "default"]
Copy the generated
token
value. In this example, the token ishvs.ad3DG8zxyPcqq4cvrMzsIxr9
.Return to the Vault UI and enter the generated token to sign in.
Select mongodb/.
Under Get Credentials, enter
tester
in the Role to use field.Click Get Credentials to display the credentials.
Customize the generated username schema
In the request MongoDB credentials section, you
saw the Vault generated username and password. The generated username resembles v-token-tester-6iRIcGv8tLpu816oblPY-1556567086
. This may be less
obvious to differentiate 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 a tester
role, so 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}}@$MONGODB_URL/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/JPQtefXthLkh7hE8vPpBY5Zwlease_duration 24hlease_renewable truepassword GHVxvy6gDf7zD9Kxk-8fusername 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
Resources are available to help integrate your applications with a Vault database secrets engine. You can use these resources, and your existing applications will require little to no code changes to work with Vault.
Refer to the following tutorials: