使用Spring Cloud Config定制属性加载器

时间:2017-01-04 05:42:13

标签: spring-boot spring-cloud-config

我在我的spring-boot应用程序中使用Spring Cloud Config,我需要编写一些自定义代码来处理属性被标记为属性时从我的公司密码库中读取的属性。我知道spring cloud支持Hashicorp Vault,但这不是万一。

我不想对要从其他来源检索的特定属性进行硬编码,例如,我会为应用app1创建一个属性文件,其中包含值为dev的值spring.datasource.url=jdbc:mysql://localhost/test spring.datasource.username=dbuser spring.datasource.password=dbpass spring.datasource.driver-class-name=com.mysql.jdbc.Driver

prod

但对于其他一些资料,例如spring.datasource.url=jdbc:mysql://localhost/test spring.datasource.username=prod-user spring.datasource.password=[[vault]] spring.datasource.driver-class-name=com.mysql.jdbc.Driver ,我会:

[[vault]]

所以我需要自定义属性保险库来拦截加载的属性,只要它找到返回的值等于spring.datasource.password(或其他类型的标志),并从公司保险库查询。在这种情况下,我的自定义属性加载器将从公司密码库中找到属性Base64.encodeToString(("users name").getBytes(), 2); 的值。所有其他属性仍将按标准spring cloud配置客户端加载的值原样返回。

我想使用带注释的代码,没有XML配置。

2 个答案:

答案 0 :(得分:0)

您可以实施自己的PropertySourceLocator并添加条目 目录META-INF中的spring.factories。

#spring.factories

org.springframework.cloud.bootstrap.BootstrapConfiguration=/
foo.bar.MyPropertySourceLocator

然后,您可以在公司密码库中引用密钥,就像春天的常规属性一样。

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=prod-user
spring.datasource.password=${lodaded.password.from.corporate.vault}
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

HasiCorp的实施:VaultPropertySourceLocatorSupport

答案 1 :(得分:0)

在尝试解决相同的问题时,我相信我已经开始尝试可以接受的解决方法。

这是我下面的解决方案。

public class JBossVaultEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
    MutablePropertySources propertySources = environment.getPropertySources();
    Map<String, String> sensitiveProperties = propertySources.stream()
            .filter(propertySource -> propertySource instanceof EnumerablePropertySource)
            .map(propertySource -> (EnumerablePropertySource<?>) propertySource)
            .map(propertySource -> {
                Map<String, String> vaultProperties = new HashMap<>();
                String[] propertyNames = propertySource.getPropertyNames();
                for (String propertyName : propertyNames) {
                    String propertyValue = propertySource.getProperty(propertyName).toString();
                    if (propertyValue.startsWith("VAULT::")) {
                        vaultProperties.put(propertyName, propertyValue);
                    }
                }
                return vaultProperties;
            })
            .reduce(new HashMap<>(), (m1, m2) -> {
                m1.putAll(m2);
                return m1;
            });

    Map<String, Object> vaultProperties = new HashMap<>();
    sensitiveProperties.keySet().stream()
            .forEach(key -> {
                vaultProperties.put(key, VaultReader.readAttributeValue(sensitiveProperties.get(key)));
            });

    propertySources.addFirst(new MapPropertySource("vaultProperties", vaultProperties));
}