'How can I use SpringBoot to pick up DB credentials from Vault?

I have a springboot app that uses these versions:

SpringBoot: 2.3.1
SpringCloud: Hoxton.SR5 
SpringData: Neumann-SR1

I've used the custom class as described here (answer from @Arun): Configuring Spring Cloud Vault Config to pull from a location other than /secret

It doesn't even seem to be picking up the vault configs. I have a bootstrap.yml with the following:

spring:
  cloud:
    # Vault configurations
    vault:
      generic:
        enabled: false
      uri: https://${URI}
      authentication: TOKEN
      token: ${VAULT_TOKEN}

    config:
      discovery:
        enabled: true

I'm trying to bring it up locally, so I have my application.yml as follows:

spring:
  datasource:
    url: jdbc:postgresql://localhost:8157/postgres

This is where I'm trying to inject the values from vault into my DataSource:

@Profile(value = {"local", "dev", "stg", "prd"})
@Configuration
public class DatabaseConfig {

  @Autowired
  DatabaseCredentials config;

  @Bean
  @Primary
  public DataSource dataSource() {

    return DataSourceBuilder
        .create()
        .username(config.getUsername())
        .url(config.getUrl())
        .password(config.getPassword())
        .driverClassName("org.postgresql.Driver")
        .build();
  }
}

When the app starts up, it DatabaseCredentials is empty.

The other way I've done it is like this:

public class DatabaseConfig {
  
  @Value("${ccm.database.username}")
  String username;

  @Value("${ccm.database.password}")
  String password;

  @Value("${spring.datasource.url}")
  String url;

  @Bean
  @Primary
  public DataSource dataSource() {
    
    return DataSourceBuilder
        .create()
        .username(username)
        .url(url)
        .password(password)
        .driverClassName("org.postgresql.Driver")
        .build();
  }
}

This has also come up empty saying it can't find a value for ccm.database.username.

What am I doing wrong?



Solution 1:[1]

You are missing the annotations on DatabaseConfig.java

Which will be something like this.

@Component
@ConfigurationProperties("ccm.database")

So it becomes

@ConfigurationProperties("ccm.database")
@Component
public class DatabaseCredentials {
  
  @Value("${ccm.database.username}")
  String username;

  @Value("${ccm.database.password}")
  String password;

  @Value("${spring.datasource.url}")
  String url;

  // Getters and setters for all properties go here
}

To access the config

@Configuration
public class DatabaseConfig {

  @Autowired
  DatabaseCredentials config;

  @Bean
  @Primary
  public DataSource dataSource() {

    return DataSourceBuilder
        .create()
        .username(config.getUsername())
        .url(config.getUrl())
        .password(config.getPassword())
        .driverClassName("org.postgresql.Driver")
        .build();
  }
}

Solution 2:[2]

Spring cloud supports import standart spring boot configuration from vault.

use two dependendences for automatic configuration:

  • org.springframework.cloud:spring-cloud-starter-vault-config

  • org.springframework.cloud:spring-cloud-vault-config-databases

See: https://medium.com/digitalfrontiers/manage-your-database-accounts-with-spring-cloud-vault-config-48cecb837a36

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Nicolay