Search code examples
javaspring-bootspring-cloudhashicorp-vaultspring-cloud-vault-config

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

  • Spring Cloud Vault gives you DEBUG info which helped me figure out the issue. I ended up defining the path with kv instead of a custom VaultConfigurer bean.

    kv:
      enabled: true
      backend: tcds/kv/app-name
      application-name: ccm
    

    This creates the path as follows: tcds/kv/app-name/ccm/${PROFILE}.
    I assumed that all secrets underneath this path will be picked up and I originally had multiple folders underneath my path of tcds/kv/app-name/ccm/dev.
    For example: ../ccm/dev/database, ../ccm/dev/other-creds.

    However, it seems that spring vault wasn't going to the nested paths for secrets and was looking for a file with all credentials there.

    So, I removed the dev folder and replaced it with a dev file with entries such as:

    {
      "database.username": "blah",
      "database.password": "moreblah",
      "other-creds.user": "dummy"
    }
    

    I am able to get credentials from vault by using the DatabaseConfig.java class alone and not having to use DatabaseCredentials.java with the @ConfigurationProperties annotation.