javaspring-boothashicorp-vaultspring-vaultspring-cloud-vault-config

Vault UserPass authentication with Spring boot


I need to connect to Vault from my spring boot microservice. To get the vault token, the service needs to login to vault by providing username and password. Spring-vault integration doesn't support this behaviour by default.

I came across this SO question and tried the approach but it results in BeanDefinitionStoreException, as the bean named clientAuthentication is already defined.

Later I have referred this example and extend AbstractVaultConfiguration. Now my configuration hierarchy looks like the below:

@Configuration(proxyBeanMethods = false)
public abstract class AbstractVaultConfiguration implements ApplicationContextAware {
  public abstract VaultEndpoint vaultEndpoint();
  public abstract ClientAuthentication clientAuthentication();
  // other methods and bean definitions
}

@Configuration
public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration implements 
ApplicationContextAware {
  // other methods
}

public class VaultCustomConfig extends AbstractVaultConfiguration {
@Override
public VaultEndpoint vaultEndpoint() {
    return VaultEndpoint.create("https://vault-dev.net", 443);
}

@Override
public ClientAuthentication clientAuthentication() {
    //logic to fetch token
}
}

First two classes are provided by spring-vault. I have added the last one and also put entry in spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.test.configuration.VaultCustomConfig

The application is starting but getting 403 error. When I exclude EnvironmentVaultConfiguration from auto configuration, getting exceptions that many beans are not created(ex-vaultTemplate). I am able to contact vault API and fetch the token using RestTemplate. The challenge is setting that token before the app tries to contact vault(through spring-vault support).

Instead of overriding vault configuration, I tried setting an environment variable named vault.token which will be read by spring during start-up, but that is also not working(probably I missed something).

How can I override the built-in configuration and provide the token?


Solution

  • Spring reads vault token from this property spring.cloud.vault.token. I have created a custom PropertySourceLocator and added the token:

    public class VaultCustomPropertySourceLocator implements PropertySourceLocator {
    
    @Override
    public PropertySource<?> locate(Environment environment) {
        Properties props = new Properties();
        props.setProperty("spring.cloud.vault.token", getVaultAuthToken());
        PropertiesPropertySource ps = new PropertiesPropertySource("customPropsSource",props);
        return ps;
    }
    
    private String getVaultAuthToken() {
        // logic to fetch vault token
    }
    }