Configure password generation polices for secret engines
Vault supports 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.
In the dynamic secrets tutorial, you configured Vault to generate dynamic credentials for a PostgreSQL database. In this tutorial, you will learn how to configure Vault to generate passwords that meet your organization's standards.
If you are not familar with how to configure Vault for dynamic credentials, follow the database secrets engine tutorial before you begin.
Scenario
HashiCups has a password policy that must be used for all application. Vault's database secrets engine generates passwords that adhere to a default pattern.
Secrets engines with support for password policies:
You can edit the default pattern to fit usecases such as:
- 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
Oliver will create a custom password policy that fullfils HashiCups security standars. The password requirements are:
- Length of 20 characters
- Multiple character sets
- Minumum number of characters from each set
Prerequisites
This lab was tested on macOS using an x86_64 based and Apple silicon-based processors. You may also run this tutorial by clicking the Start interactive lab button.
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
To perform the tasks described in this tutorial, you need to have:
- Docker to run a Vault and PostgreSQL container.
- Vault binary installed.
- Git installed.
Set up the lab
Clone the
learn-vault-dynamic-credentials
repository.$ git clone git@github.com:hashicorp-education/learn-vault-dynamic-credentials.git
Change into the
learn-vault-dynamic-credentials
directory.$ cd learn-vault-dynamic-credentials
Deploy the Vault and PostgreSQL containers.
$ terraform -chdir=vault-dynamic-creds-docker/ init && \ terraform -chdir=vault-dynamic-creds-docker/ apply -auto-approve
Example output:
Initializing the backend... Initializing provider plugins... - Finding kreuzwerker/docker versions matching "3.0.2"... - Installing kreuzwerker/docker v3.0.2... ...snip... Apply complete! Resources: 4 added, 0 changed, 0 destroyed. Outputs: POSTGRES_URL = "export TF_VAR_POSTGRES_URL=172.17.0.2:5432" POSTGRES_URL_HOST = "export 127.0.0.1:5432" VAULT_ADDR = "export VAULT_ADDR=http://127.0.0.1:8200" VAULT_TOKEN = "export VAULT_TOKEN=root"
Copy the export command from the Terraform output and export the environment variables.
Example:
$ export VAULT_ADDR=http://127.0.0.1:8200 \ VAULT_TOKEN=root \ TF_VAR_POSTGRES_URL=172.17.0.2:5432
Verify the PostgreSQL and Vault containers have started.
$ docker ps -f name=learn --format "table {{.Names}}\t{{.Status}}" NAMES STATUS learn-postgres Up 4 minutes learn-vault Up 4 minutes
Vault and PostgreSQL are running. Vault connects to PostgreSQL over the Docker bridge network.
Apply the PostgreSQL configuration used in the dynamic secrets tutorial.
$ terraform -chdir=vault-dynamic-creds-postgres/ init && \ terraform -chdir=vault-dynamic-creds-postgres/ apply -auto-approve
Example output:
Initializing the backend... Initializing provider plugins... - Finding cyrilgdn/postgresql versions matching "1.25.0"... - Installing cyrilgdn/postgresql v1.25.0... - Installed cyrilgdn/postgresql v1.25.0 (self-signed, key ID 418F268A88A6D481) ...snip... Plan: 2 to add, 0 to change, 0 to destroy. postgresql_role.ro: Creating... postgresql_grant.readonly_tables: Creating... postgresql_role.ro: Creation complete after 0s [id=ro] postgresql_grant.readonly_tables: Creation complete after 0s [id=ro_postgres_public_table] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Apply the Vault configuration used in the dynamic secrets tutorial.
$ terraform -chdir=vault-dynamic-creds-vault/ init && \ terraform -chdir=vault-dynamic-creds-vault/ apply -auto-approve
Example output:
Initializing the backend... Initializing provider plugins... - Finding hashicorp/vault versions matching "4.5.0"... ...snip... vault_database_secrets_mount.database: Creating... vault_database_secrets_mount.database: Creation complete after 0s [id=database] vault_database_secret_backend_role.readonly: Creating... vault_database_secret_backend_role.readonly: Creation complete after 0s [id=database/roles/readonly] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Vault and PostgreSQL are running and configured. You are ready to proceed with the tutorial.
Request credentials with default password policy
Each supported secrets engine has a default password policy that generates passwords.
Generate credentials from the
readonly
role.$ vault read database/creds/readonly
Example output:
Key Value --- ----- lease_id database/creds/readonly/5ZJXSIyWN5k4A8u6AMZs5I0s lease_duration 1h lease_renewable true password -LL23iRQqsAD0YmS1eq3 username v-token-readonly-xboXz3doC1jBe9ntlKaA-1737490496
The credentials display the
username
andpassword
generated. The password generated 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 <<EOF length=20 rule "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
Policies use the 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.hcl Success! Data written to sys/polices/password/example_policy
This policy is accessible 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/generate Key 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
Configure a custom password policy
Review the current database secrets engine configuration.
$ vault read database/config/postgres Key Value --- ----- allowed_roles [readonly] connection_details map[connection_url:postgresql://{{username}}:{{password}}@172.17.0.2:5432/postgres?sslmode=disable disable_escaping:false max_open_connections:2 username:root] password_policy n/a plugin_name postgresql-database-plugin plugin_version n/a root_credentials_rotate_statements [] verify_connection true
The secrets engine initially configured does not contain a password policy.
Configure the secrets engine to use the
example
password policy.$ vault write database/config/postgres password_policy="example" Success! Data written to: database/config/postgres
Review the updated database secrets engine configuration.
$ vault read database/config/postgres
Example output:
Key Value --- ----- allowed_roles [readonly] connection_details map[connection_url:postgresql://{{username}}:{{password}}@172.17.0.2:5432/postgres?sslmode=disable disable_escaping:false max_open_connections:2 username:root] password_policy example ...snip...
The secrets engine now generates passwords that adhere to the
example
password policy.Generate credentials from the
readonly
role with theexample
password policy.$ vault read database/creds/readonly Key Value --- ----- lease_id database/creds/readonly/AppmaMdS5mtMPwaZOnNnX2O9 lease_duration 1h lease_renewable true password ba8oWN@106l6uffb*GbY username v-token-readonly-W1guRN3Sr2SEw4Oj0uJU-1737491327
The credentials display the
username
andpassword
generated. Thepassword
generated adheres to the example password policy defined in the secrets engine's configuration.
Clean up
Destroy the Terraform resources.
$ terraform -chdir=vault-dynamic-creds-vault/ destroy -auto-approve && \ terraform -chdir=vault-dynamic-creds-postgres/ destroy -auto-approve && \ terraform -chdir=vault-dynamic-creds-docker/ destroy -auto-approve
Unset the environment variables.
$ unset VAULT_ADDR VAULT_TOKEN TF_VAR_POSTGRES_URL
Delete the
example_policy.hcl
password policy file.$ rm example_policy.hcl
Summary
You requested credentials from the database secrets engine that generated credentials with the default password policy. Then you defined a password policy and generated a password. Finally, you updated the secrets engine configuration to use the custom password policy.