How to Isolate Database Credentials in Spring Boot Using Vault

Data privacy and security became critical nowadays. Thus, we need to isolate database credentials and make it transparent to our applications/services.

Sharing is caring!

Overview

In my old post, I wrote about encrypting database credentials using Jasypt. But we still keep encrypted values on properties file. Which means, at some point, developers can decrypt the value and read those credentials.

But..

How about making it truly transparent from application perspective? What I mean by transparent is; the application does not know anything about the credentials. Therefore, in this blog post, I would like to share about securing your database credentials from application point of view.

I will use Hashicorp Vault as a secret management tools. All database credentials will be stored inside Vault, and I will retrieve those credentials while bootstrapping the application.

Use Case

In this use case, I will create a service and I name it as pg_service_1. The service itself will connect to postgres database, just like any ordinary service. However, the difference is, I will not put any database credentials configuration inside properties file. Instead, they will be kept inside Vault.

pg_service_1 will pass the initial token with certain validity period to Vault. Next, by using AppRole authentication mode, the service will retrieve the database credentials during the application start up, using pull secret ID mode. Then the Dummy Service will connect to the database and continue ready to serve requests.

For this purpose, I will have two personas, which are admin and app (pg_service_1).

isolate
vault-spring-boot

Admin

Step 1: Enable AppRole Authentication and Create Vault Policy

Step 2: Write AppRole for pg_service_1

Step 3: Store KV Data

Step 4: Generate Init Token and Pass It to App

App

For App, I will use Spring Boot as our pg_service_1.

Step 1: Add vault dependencies in pom.xml

Step 2: application.yml

Please note I exclude url, username and password under spring.datasouce key.

Step 3: Configure Spring Vault

AppRole authentication with PULL mechanism.

Step 4: Reconfigure Datasource Configuration

Note: set as @Primary bean, extends DataSourceProperties class and override afterPropertiesSet method.

Step 5: Start Application Using Init Token from Admin-Step 4

The service should be up and running; with connection to postgres database.

Conclusion

By using this kind of database credentials isolation, we can make sure only certain people who have access to the credentials. This approach will make your IT ecosystem more secure, audit-able and controllable related user access to production database.

That’s all for now, and source code is in my github repository.

Author: ru rocker

I have been a professional software developer since 2004. Java, Python, NodeJS, and Go-lang are my favorite programming languages. I also have an interest in DevOps. I hold professional certifications: SCJP, SCWCD, PSM 1, AWS Solution Architect Associate, and AWS Solution Architect Professional.

6 thoughts on “How to Isolate Database Credentials in Spring Boot Using Vault”

  1. could you please send me the full source code or Git Hub directory..it will be very helpful for me Thanks in Advanced!

  2. How would application’s hikari pool refresh vault token expiries, if you can provide examples of how to handle token expiries for long running services and vault tokens with limited validity that would be great.

    1. You need to restart your service. But maybe it is not an ideal condition. To mitigate this, you can use containers and do some blue-green deployment strategy to replace existing service and replace with the new token.

    2. @Shayam
      I’ve written two blog posts about how to ensure that expiring Spring Boot Vault database credentials are renewed, when reaching Vault’s max_ttl:
      * https://secrets-as-a-service.com/posts/hashicorp-vault/spring-boot-max_ttl/
      * https://secrets-as-a-service.com/posts/hashicorp-vault/rotate-dynamic-relational-database-connection-in-spring-at-runtime/

      The second one is exatly handeling the case with a relational database and hikari pool. I hope this helps.

      TL;DR:
      General Options:
      1. Use a long enough max_ttl and redeploy/restart the application often enough
      2. If needed, increase the Vault system max time-to-live
      3. Restart the Spring Boot application when the database secret expires
      4. Implement database connection rotation (The second post is explaining exactly that.)

      Relational Databases with hikari pool summery:
      Add a LeaseListenener via addLeaseListener() which
      * calls requestRotatingSecret() on the SecretLeaseContainer when the dynamic database lease expires
      * reacts on a SecretLeaseCreatedEvent with mode ROTATE) by:
      ** setting username and password on the HikariConfigMXBean of the HikariDataSource
      ** call softEvictConnections() on the HikariPoolMXBean to use the new credentials

Leave a Reply

Your email address will not be published. Required fields are marked *