Search code examples
hibernatehikaricpmicronaut

Encrypt Database password in application.yml for Micronaut + Hibernate


For a Micronaut + Hibernate applicaton, I have my database password stored in application.yml.

I am looking for ways : to provide an encrypted password in yml file & decrypt it when Database objects are constructed.

Micronaut provides no ways to achieve this.

But I think using Hikari Connection pool, should help me achieve it. Coz, Hikari CP allows me to intercept the process of construction of Database objects. Atleast there documentation claim so.

Have any one faced this issue & did solve it? Is there any other way to solve this with(or)without Hikari?

Kindly advise.


Solution

  • I have found a way to achieve it for Micronaut + Hibernate + Tomcat CP

    Note: should work for Hikari CP as well. Just change packageName of DatasourceConfiguration.class

    1. provide encrypted password in application.yml

      datasources: default: url: ${JDBC_URL:DB_URL} driverClassName: ${JDBC_DRIVER:DRIVER_CLASS} username: ${JDBC_USER:USER_NAME} password: ${JDBC_PASSWORD:ENCRYPTED_PASSWORD}

    2) Create a factory class & replace the method "getPassword" of class DatasourceConfiguration
    import io.micronaut.configuration.jdbc.tomcat.DatasourceConfiguration;
    import io.micronaut.configuration.jdbc.tomcat.DatasourceFactory;
    import io.micronaut.context.ApplicationContext;
    import io.micronaut.context.annotation.Bean;
    import io.micronaut.context.annotation.Context;
    import io.micronaut.context.annotation.EachBean;
    import io.micronaut.context.annotation.Factory;
    import io.micronaut.context.annotation.Replaces;
    import io.micronaut.context.annotation.Requires;
    import io.micronaut.inject.qualifiers.Qualifiers;
    import org.apache.tomcat.jdbc.pool.PoolProperties;
    import javax.inject.Inject;
    import javax.inject.Singleton;
    import javax.sql.DataSource;
    
    
    @Factory
    public class ApplicationConfiguration {
    
      @Context
      @Replaces(value = String.class, bean = io.micronaut.configuration.jdbc.tomcat.DatasourceConfiguration.class, named = "default")
      public String getPassword() {
        DatasourceConfiguration configuration = applicationContext.getBean(DatasourceConfiguration.class,
            Qualifiers.byName("default"));
        configuration.setPassword(decryptPassword(configuration.getPassword()));
        return configuration.getPassword();
      }
    
    //BELOW IS ONE OTHER APPROACH TO ACHIEVE THIS...BUT METHOD ABOVE IS BEST
      @Singleton
      @Replaces(value = DataSource.class, factory = DatasourceFactory.class)
      @Context
      @EachBean(DatasourceConfiguration.class)
      public DataSource dataSource(DatasourceConfiguration datasourceConfiguration) {
        org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(datasourceConfiguration);
        
        ds.getPoolProperties().setPassword(decryptPassword(configuration.getPassword()));
        return ds;
      }
    }