micronaut-sql
micronaut-sql copied to clipboard
Expose Hikari DataSources in Beans to support password rotation
Feature description
Problem
Currently the DataSource's are encapsulated inside the DatasourceFactory
class (see https://github.com/micronaut-projects/micronaut-sql/blob/5.7.x/jdbc-hikari/src/main/java/io/micronaut/configuration/jdbc/hikari/DatasourceFactory.java). This makes it impossible to access the datasource without reflection.
I would like to access the DataSource instances to rotate passwords without affecting the service availability.
Feature idea
Ideally I would like to simply get the "DataSource" and change things directly in there:
// I would use either DataSource.class or HikariDataSource.class
HikariDataSource dataSource = applicationContext.getBean(DataSource.class, Qualifiers.ofName("datasourceName"));
dataSource.setPassword(newPassword);
dataSource.getHikariPoolMXBean().softEvictConnections(); // Refresh connections
Workaround (using reflection)
As an alternative I am working with the following workaround (using reflection):
private void updateDataSourcePassword() throws NoSuchFieldException, IllegalAccessException {
DatasourceFactory datasourceFactory = applicationContext.getBean(DatasourceFactory.class);
Field dataSourcesField = DatasourceFactory.class.getDeclaredField("dataSources");
dataSourcesField.setAccessible(true);
List<HikariDataSource> dataSources = (List<HikariDataSource>) dataSourcesField.get(datasourceFactory);
for (HikariDataSource dataSource : dataSources) {
dataSource.setPassword(newPassword);
dataSource.getHikariPoolMXBean().softEvictConnections(); // Refresh connections
}
}
Please let me know if there is a better workaround.
How does Spring work (probably the best solution)
This is something kindof supported by Spring:
- https://blog.jdriven.com/2021/06/configure-hikari-connection-pool-when-using-rds-iam/
- https://stackoverflow.com/questions/73793784/how-to-ensure-hikari-connections-are-spawn-with-latest-credentials
Basically you can override the HikariUrlDataSource
class with any custom classname using the application.properties
. This is something that is not supported either by Micronaut. It is quite a clean solution with the disadvantage that getPassword
is called for each connection. It could be worked around using a memory cache or lazy variables.