Browse Source

Fix so local and remote bootstrap properties can be decrypted

The order of initializers is important (decrypt has to come after
property sources), as is the order of property sources (the
decrypted ones have to be high enough priority to override local
and remote bootstrap).

Fixes gh-325
pull/496/head
Dave Syer 9 years ago
parent
commit
7f897d59ee
  1. 26
      spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/config/PropertySourceBootstrapConfiguration.java
  2. 2
      spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EnvironmentDecryptApplicationInitializer.java
  3. 65
      spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/BootstrapOrderingCustomPropertySourceIntegrationTests.java
  4. 1
      spring-cloud-context/src/test/resources/custom.properties

26
spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/config/PropertySourceBootstrapConfiguration.java

@ -26,7 +26,6 @@ import org.apache.commons.logging.LogFactory; @@ -26,7 +26,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LoggingSystem;
@ -36,6 +35,7 @@ import org.springframework.cloud.logging.LoggingRebinder; @@ -36,6 +35,7 @@ import org.springframework.cloud.logging.LoggingRebinder;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@ -52,27 +52,28 @@ import org.springframework.util.StringUtils; @@ -52,27 +52,28 @@ import org.springframework.util.StringUtils;
@Configuration
@EnableConfigurationProperties(PropertySourceBootstrapProperties.class)
public class PropertySourceBootstrapConfiguration implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = BootstrapApplicationListener.BOOTSTRAP_PROPERTY_SOURCE_NAME;
private static Log logger = LogFactory
.getLog(PropertySourceBootstrapConfiguration.class);
private int order = Ordered.HIGHEST_PRECEDENCE + 10;
@Autowired(required = false)
private List<PropertySourceLocator> propertySourceLocators = new ArrayList<>();
@Autowired
private PropertySourceBootstrapProperties properties;
@Autowired
private ConfigurationPropertiesBindingPostProcessor binder;
public void setPropertySourceLocators(
Collection<PropertySourceLocator> propertySourceLocators) {
this.propertySourceLocators = new ArrayList<>(propertySourceLocators);
}
@Override
public int getOrder() {
return this.order;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
CompositePropertySource composite = new CompositePropertySource(
@ -126,8 +127,8 @@ public class PropertySourceBootstrapConfiguration implements @@ -126,8 +127,8 @@ public class PropertySourceBootstrapConfiguration implements
rebinder.setEnvironment(environment);
// We can't fire the event in the ApplicationContext here (too early), but we can
// create our own listener and poke it (it doesn't need the key changes)
rebinder.onApplicationEvent(new EnvironmentChangeEvent(Collections
.<String> emptySet()));
rebinder.onApplicationEvent(
new EnvironmentChangeEvent(Collections.<String> emptySet()));
}
private void insertPropertySources(MutablePropertySources propertySources,
@ -137,9 +138,8 @@ public class PropertySourceBootstrapConfiguration implements @@ -137,9 +138,8 @@ public class PropertySourceBootstrapConfiguration implements
PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties();
new RelaxedDataBinder(remoteProperties, "spring.cloud.config")
.bind(new PropertySourcesPropertyValues(incoming));
if (!remoteProperties.isAllowOverride()
|| (!remoteProperties.isOverrideNone() && remoteProperties
.isOverrideSystemProperties())) {
if (!remoteProperties.isAllowOverride() || (!remoteProperties.isOverrideNone()
&& remoteProperties.isOverrideSystemProperties())) {
propertySources.addFirst(composite);
return;
}

2
spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EnvironmentDecryptApplicationInitializer.java

@ -104,7 +104,7 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -104,7 +104,7 @@ public class EnvironmentDecryptApplicationInitializer implements
MapPropertySource propertySource) {
if (propertySources
.contains(BootstrapApplicationListener.BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
propertySources.addAfter(
propertySources.addBefore(
BootstrapApplicationListener.BOOTSTRAP_PROPERTY_SOURCE_NAME,
propertySource);
}

65
spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/BootstrapOrderingCustomPropertySourceIntegrationTests.java

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
package org.springframework.cloud.bootstrap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.bootstrap.BootstrapOrderingCustomPropertySourceIntegrationTests.Application;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@IntegrationTest({"encrypt.key:deadbeef", "spring.cloud.bootstrap.name:custom"})
@ActiveProfiles("encrypt")
public class BootstrapOrderingCustomPropertySourceIntegrationTests {
@Autowired
private ConfigurableEnvironment environment;
@Test
public void bootstrapPropertiesExist() {
assertTrue(this.environment.getPropertySources().contains("bootstrap"));
}
@Test
public void customPropertiesDecrypted() {
assertEquals("bar", this.environment.resolvePlaceholders("${custom.foo}"));
}
@EnableAutoConfiguration
@Configuration
protected static class Application {
}
@Configuration
// This is added to bootstrap context as a source in bootstrap.properties
protected static class PropertySourceConfiguration implements PropertySourceLocator {
public static Map<String, Object> MAP = new HashMap<String, Object>(
Collections.<String, Object> singletonMap("custom.foo", "{cipher}6154ca04d4bb6144d672c4e3d750b5147116dd381946d51fa44f8bc25dc256f4"));
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("testBootstrap", MAP);
}
}
}

1
spring-cloud-context/src/test/resources/custom.properties

@ -0,0 +1 @@ @@ -0,0 +1 @@
spring.main.sources: org.springframework.cloud.bootstrap.BootstrapOrderingCustomPropertySourceIntegrationTests.PropertySourceConfiguration
Loading…
Cancel
Save