In this article, I will show you how to integrate Amazon RDS connection information into a Spring project using AWS Secrets Manager.
With traditional Spring projects, we tend to configure the data source directly inside the source code. In different environments (development, staging, production), it is common to use Spring profiles to change these parameters. This solution is convenient, but it lacks security (credentials explosion, inability to access manager), difficult to manage and change (password rotation policy).
AWS offers a solution using AWS Secrets Manager integration with RDS and Rotating Secrets, simplifying management and ensuring security. Refer to Security best practices for Amazon RDS
Here are 2 simple steps to integrate RDS data source and Spring Boot project using AWS Secrets Manager.
Step 1. Add this dependency in pom.xml file
<dependency> <groupId>com.amazonaws.secretsmanager</groupId> <artifactId>aws-secretsmanager-jdbc</artifactId> <version>1.0.5</version> </dependency>
Step 2. Change data source configuration
spring: datasource: url: jdbc-secretsmanager:mysql://database-host:3306/rdsdb username: rdsrotation driver-class-name: com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver
- url: it has a prefix jdbc-secretsmanager instead of just jdbc as usual
- username: Secret Name which you’ve got in AWS Secrets Manager
The magic here is that driver-class-name is AWSSecretsManagerMySQLDriver. It is the AWS Secrets Manager Driver driver which wraps the original driver (for instance com.mysql.cj.jdbc.Driver).
Some databases and corresponding drivers:
- MySQL: AWSSecretsManagerMySQLDriver
- MariaDB: AWSSecretsManagerMariaDBDriver
- Oracle DB: AWSSecretsManagerOracleDriver
- PostgreSQL: AWSSecretsManagerPostgreSQLDriver
- MSSQL: AWSSecretsManagerMSSQLServerDriver
Here is a GitHub link to this implementation.
So it’s done. Now you can use Spring data source normally. You can rotate your password automatically every day, every month in AWS Secrets Manager and your program will still work as you expected without restarting every time you change the password.
But How? If you need to understand in more detail how it works, continue to follow below.
How it work
When the program needs a JDBC connection, the java.sql.Driver#connect function is called. Instead of retrieving an existing username/password, the Driver wrapper (eg AWSSecretsManagerMySQLDriver) will call into the AWS Secrets Manager to retrieve the username/password.
The problem is that you have to calls the AWS Secrets Manager API every time you use the connection, it will take time and cost a lot(AWS Secrets Manager charges by the number of API calls). So, the better way is to cache and reuse username/password next time instead of calling AWS Secrets Manager.
If the cached has expired (default is 1 hour), the driver will continue to call into AWS Secrets Manager to retrieve the username/password (can be new or old).
So what if the cached has not expired but the username/password in AWS Secrets Manager(also in RDS of course) has been changed? Driver uses fallback mechanism. It doesn’t know credentials are changed, so it continuous connects to database using the existing username/password (in the cached), if the database returns an error indicating the wrong username/password, call AWS Secrets Manager to get the new username/password.
And that’s it. Above is the guide on how to integrate Amazon RDS and AWS Secrets Manager into Spring Boot project. This method is not limited to Spring but can be used with any Java project that uses JDBC.
Reference
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP\_BestPractices.Security.html
- https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html
- https://dzone.com/articles/spring-boot-handle-aws-rds-password-change-or-rota
- https://github.com/aws/aws-secretsmanager-jdbc
- https://aws.amazon.com/blogs/security/use-aws-secrets-manager-client-side-caching-libraries-to-improve-the-availability-and-latency-of-using-your-secrets/