Reputation: 27
I am currently trying to replace hardcoded secrets on my Spring (non SpringBoot) application using the Spring Cloud Azure library as documented in here.
Currently I have managed to retrieve the secrets after the application startup:
@Configuration
public class KeyVaultConfig {
@Value("${spring.cloud.azure.keyvault.secret.endpoint}")
private String keyVaultUri;
private SecretClient secretClient;
public KeyVaultConfig() {}
@PostConstruct
private void setKeyVaultProvider() {
this.secretClient = new SecretClientBuilder()
.vaultUrl(keyVaultUri)
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
public SecretClient getSecretClient() {
return secretClient;
}
}
And then I succesfully retrieve the secret in another class as:
@PostConstruct
public void getTest() {
System.out.println("lul");
SecretClient secretClient = keyVaultConfig.getSecretClient();
secretClient.getSecret("secret");
}
Now, the problem is that I need to use the secret as soon as the context is created because my app-context.xml is defined as this:
<bean id="dataSourceMysql" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.driverClassName}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
<property name="minPoolSize" value="${c3p0.minPoolSize}" />
<property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
<property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
<property name="preferredTestQuery" value="SELECT 1234567890" />
<property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}" />
<property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
</bean>
Any advice or suggestion? Thanks!
Upvotes: 0
Views: 603
Reputation: 3473
To use the secret retrieved from Azure Key Vault as the password for your MySQL DataSource in the Spring application.
Firstly, Add Spring Cloud Azure Dependencies.
pom.xml:
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
<version>5.9.1</version>
</dependency>
If you use any certificates the add Azure-identity
dependency also.
KeyVaultConfig:
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class KeyVaultConfig {
@Value("${spring.cloud.azure.keyvault.uri}")
private String keyVaultUri;
@Bean
public SecretClient secretClient() {
return new SecretClientBuilder()
.vaultUrl(keyVaultUri)
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
}
SecretInitializer:
import com.azure.security.keyvault.secrets.SecretClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class SecretInitializer {
@Autowired
private SecretClient secretClient;
@Autowired
private ConfigurableApplicationContext context;
@PostConstruct
public void init() {
String secretValue = secretClient.getSecret("your-secret-name").getValue();
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource("secrets", Collections.singletonMap("db.password", secretValue)));
}
}
Its better to configure in application.properties
, configure your MySQL DataSource, including the password placeholder.
properties:
db.driverClassName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/your_database
db.username=username
db.password=${db.password}
c3p0.acquireIncrement=3
c3p0.minPoolSize=5
c3p0.maxPoolSize=20
c3p0.maxIdleTime=1800
c3p0.testConnectionOnCheckout=true
c3p0.idleConnectionTestPeriod=1800
DataSourceConfig:
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Value("${db.driverClassName}")
private String driverClassName;
@Value("${db.url}")
private String jdbcUrl;
@Value("${db.username}")
private String username;
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driverClassName);
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUser(username);
dataSource.setPassword("${db.password}");
// Set other properties such as maxPoolSize, minPoolSize, etc.
return dataSource;
}
}
Secret retrieved:
Upvotes: 0