Reboot a Spring Boot application to rotate a new database credential from Vault when the lease expired
Notice: The application is created for the propose of technical demonstration. The solution should never be used in production environment.
The application exists because of a prestigious blog post named Hashicorp Vault max_ttl Killed My Spring App.
The blog post gives four solutions to resolve a spring vault issue that the database credentials will not be rotated after the lease expired its max_ttl. For detail about the issue, pls refer to here.
The application is a Java implementation of solution 3 using APPROLE authentication and tested with OpenJDK11-OpenJ9, vault v1.3.2 and MongoDB v3.6.
For the fourth solution in a more general case, please refer to the rotate
branch.
The application uses APPROLE authentication, and here is the configuration of vault as follows.
- Start
Vault
server in development modevault server -dev
- Export an environment variable for local connection
export VAULT_ADDR='http://127.0.0.1:8200'
- Create a new auth method named "approle"
vault auth enable approle
- Create a new policy path named "app-policy" and use hcl file to create policies of the path in order to get/renew database credentials (The fcl file locates under
vault
folder.)vault write sys/policy/app-policy policy=@app-policy.hcl
- Create a
readwrite
path in "approle" with unlimited tokens and secret idsvault write auth/approle/role/readwrite secret_id_ttl=100m token_num_uses=0 token_ttl=100m token_max_ttl=100m secret_id_num_uses=0 policies="default,app-policy"
- (Optional) Enable database secrets if it disabled
vault secrets enable database
- Create a MongoDB config named "app-mongodb" and add its connection info.
vault write database/config/app-mongodb plugin_name=mongodb-database-plugin allowed_roles="readwrite" connection_url="mongodb://{{username}}:{{password}}@[myip]/admin?ssl=false" username="[myusername]" password="[mypassword]"
- Configure a role that maps the MongoDB config to a MongoDB command that executes and creates the database credential (Here,
ttl
is 2 minutes andmax_ttl
is 5 minutes)vault write database/roles/readwrite db_name=app-mongodb creation_statements='{ "db": "vaultdemo", "roles": [{ "role": "dbOwner" }, {"role": "readWrite", "db": "vaultdemo"}] }' default_ttl="2m" max_ttl="5m"
- Get
role-id
which will be the value ofspring.cloud.vault.app-role.role-id
vault read auth/approle/role/readwrite/role-id
- Get
secret-id
which will be the value ofspring.cloud.vault.app-role.secret-id
vault write -f auth/approle/role/readwrite/secret-id
- Configure
spring.cloud.vault.app-role.role-id
andspring.cloud.vault.app-role.secret-id
inbootstrap.yml
. - Configure host and port of MongoDB in
application.yml
. - Start the application.
- Access POST http://localhost:8080 to init some data and GET http://localhost:8080 to retrieve them.
There are several logs shows the application do renew the database credential. After about 5 minutes, the lease is expired (because max_ttl
is 5m
) the application is rebooted.