User configurable password generation for secret engines
Challenge
Vault's secret engines generate passwords that adhere to a default pattern that may not meet the standards required by your applications or within your organization. You may require passwords with:
- Lengths that are smaller or exceed the default length
- Differing character sets
- Frequency of characters
- Positional requirements for characters
- Disallowed repetition
- Disallowed words from a dictionary
Solution
Vault 1.5 introduced support for configurable password generation defined by a password policy. A policy defines the rules and requirements that the password must adhere and can provide that password directly through a new endpoint or within secrets engines.
Secrets engines with support for password policies:
Prerequisites
This lab was tested on macOS using an x86_64 based processor. If you are running macOS on an Apple silicon-based processor, click the Start interactive lab button or perform the steps using a x86_64 based Linux virtual machine in your preferred cloud provider.
Vault version 1.5 or later; refer to the Vault install guide to install Vault.
RabbitMQ environment or Docker.
ngrok installed and configured with auth token (HCP Vault Dedicated only)
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Lab setup
Start RabbitMQ
RabbitMQ is a message-broker that has a secrets engine that enables Vault to generate user credentials.
In a new terminal, start a RabbitMQ server running on port 15672
that
has a user named learn_vault
with the password hashicorp
.
$ docker run --rm --name some-rabbit -p 15672:15672 \ -e RABBITMQ_DEFAULT_USER=learn_vault \ -e RABBITMQ_DEFAULT_PASS=hashicorp \ rabbitmq:3-management
Docker downloads the necessary images and launches a RabbitMQ database container. RabbitMQ is ready for Vault to generate credentials.
Start Vault
A Vault server is able to generate passwords that meet the requirements of a configurable password policy. These password policies may also be applied to supported secrets engines.
In another terminal, start a Vault dev server with
root
as the root token.$ vault server -dev -dev-root-token-id root
Insecure operation
Do not run a Vault dev server in production. This approach is only used here to simplify the unsealing process for this demonstration.
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"]
The Vault server is ready to explore password policies.
Set an environment variable for the RabbitMQ address.
$ export RABBITMQ_URL=http://127.0.0.1:15672
You are ready to proceed with the lab.
Setup RabbitMQ secrets engine with the default password policy
The RabbitMQ secrets engine generates passwords that adhere to a default password policy.
Enable the RabbitMQ secrets engine at the
rabbitmq-default-policy
path.$ vault secrets enable -path rabbitmq-default-policy rabbitmqSuccess! Enabled the rabbitmq secrets engine at: rabbitmq-default-policy/
The secrets engine requires configuration so it can communicate with the RabbitMQ server.
Configure the secrets engine to connect to the RabbitMQ server.
$ vault write rabbitmq-default-policy/config/connection \ connection_uri=$RABBITMQ_URL \ username="learn_vault" \ password="hashicorp"
Output:
Success! Data written to: rabbitmq-default-policy/config/connection
The secrets engine is configured to talk to the RabbitMQ server running locally over the HTTP management interface. The user,
learn_vault
, with its passwordhashicorp
, is an administrator that was generated when RabbitMQ started.Create a role named
example
.$ vault write rabbitmq-default-policy/roles/example \ vhosts='{"/":{"read": ".*", "write": ".*"}}'
Output:
Success! Data written to: rabbitmq-default-policy/roles/example
The
example
role defines an endpoint for dynamic credential generation. The credentials generated are granted read and write every entity.Generate credentials from the
example
role.$ vault read rabbitmq-default-policy/creds/example
Example output:
Key Value--- -----lease_id rabbitmq-default-policy/creds/example/4yCYMMCZ4I4mKBlPsbNNsKdjlease_duration 768hlease_renewable truepassword v0E6LjTeabrtEAz72cbYINNodWSApPS61vGPusername root-2b3482f7-b522-9997-ab0c-1f3057a396d3
The credentials display the
username
andpassword
generated. The password generated,v0E6LjTeabrtEAz72cbYINNodWSApPS61vGP
, adheres to the default password policy for the secrets engine.
Define a password policy
Create a policy file named
example_policy.hcl
.$ tee example_policy.hcl <<EOFlength=20rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1}rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1}rule "charset" { charset = "0123456789" min-chars = 1}rule "charset" { charset = "!@#$%^&*" min-chars = 1}EOF
The policy is written in HashiCorp Configuration Language (HCL). The
length
field sets the length of the password returned to20
characters. Each rule stanza defines a character set and the minimum number of occurrences those characters need to appear in the generated password. These rules are cumulative so each one adds more requirements on the password generated.Create a Vault password policy named
example
with the password policy rules defined inexample_policy.hcl
.$ vault write sys/policies/password/example policy=@example_policy.hclSuccess! Data written to sys/polices/password/example_policy
This policy can now be accessed directly to generate a password or referenced by its name
example
when configuring supported secrets engines.Generate a password from the
example
password policy.$ vault read sys/policies/password/example/generateKey Value--- -----password #v!RQDHxHunJ1TUmCyys
The password generated adheres to the requirements:
- length of 20 characters
- at least 1 uppercase character
- at least 1 lowercase character
- at least 1 number
- at least 1 symbol
Setup RabbitMQ secrets engine with a password policy
The RabbitMQ secrets engine may be configured to adopt a password policy.
Enable the RabbitMQ secrets engine at the
rabbitmq-with-policy
path.$ vault secrets enable -path rabbitmq-with-policy rabbitmqSuccess! Enabled the rabbitmq secrets engine at: rabbitmq-with-policy/
The secrets engine requires configuration so it can communicate with the RabbitMQ server.
Configure the secrets engine to connect to the RabbitMQ server and use the
example
password policy.$ vault write rabbitmq-with-policy/config/connection \ connection_uri=$RABBITMQ_URL \ username="learn_vault" \ password="hashicorp" \ password_policy="example"
Output:
Success! Data written to: rabbitmq-with-policy/config/connection
The same connection information is used to establish the connection with the RabbitMQ server. The difference is that the
password_policy
has been set to theexample
policy defined in Define a password policy section.Create a role named
example
.$ vault write rabbitmq-with-policy/roles/example \ vhosts='{"/":{"read": ".*", "write": ".*"}}'
Output:
Success! Data written to: rabbitmq-with-policy/roles/example
The
example
role defines an endpoint for dynamic credential generation. The credentials generated are granted read and write on every entity.Generate a login from the
example
role.$ vault read rabbitmq-with-policy/creds/example
Example output:
Key Value--- -----lease_id rabbitmq-with-policy/creds/example/vfoht23KclCzOuKzlRYeMZZSlease_duration 768hlease_renewable truepassword HtjHFtdy21*iBpNZjLNbusername root-4efd295b-1a4e-285c-14c8-06b135c5464a
The credentials display the
username
andpassword
generated. Thepassword
generated,HtjHFtdy21*iBpNZjLNb
, adheres to the example password policy defined in the secrets engine's configuration.
Next steps
You configured a RabbitMQ secrets engine that generated credentials with the default password policy. Learn more about the RabbitMQ secrets engine by reading the documentation and the API documentation.
Then you defined a password policy and generated a password. Learn more about by reading the documentation and the API documentation.
Finally, you configured another RabbitMQ secrets engine that generated credentials that used a custom password policy.