Browse Source

Reverse order of property sources before decrypting

Fixes gh-70
pull/496/head
Dave Syer 9 years ago
parent
commit
99cd797464
  1. 25
      spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EnvironmentDecryptApplicationInitializer.java
  2. 37
      spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EnvironmentDecryptApplicationListenerTests.java

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

@ -15,7 +15,9 @@ @@ -15,7 +15,9 @@
*/
package org.springframework.cloud.bootstrap.encrypt;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@ -38,7 +40,7 @@ import org.springframework.security.crypto.encrypt.TextEncryptor; @@ -38,7 +40,7 @@ import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
* Decrypt properties from the environment and insert them with high priority so they
* override the encrypted values.
*
*
* @author Dave Syer
*
*/
@ -58,7 +60,7 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -58,7 +60,7 @@ public class EnvironmentDecryptApplicationInitializer implements
/**
* Strategy to determine how to handle exceptions during decryption.
*
*
* @param failOnError the flag value (default true)
*/
public void setFailOnError(boolean failOnError) {
@ -71,14 +73,15 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -71,14 +73,15 @@ public class EnvironmentDecryptApplicationInitializer implements
@Override
public int getOrder() {
return order;
return this.order;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
MapPropertySource decrypted = new MapPropertySource(
DECRYPTED_PROPERTY_SOURCE_NAME, decrypt(environment.getPropertySources()));
DECRYPTED_PROPERTY_SOURCE_NAME,
decrypt(environment.getPropertySources()));
if (!decrypted.getSource().isEmpty()) {
// We have some decrypted properties
insert(environment.getPropertySources(), decrypted);
@ -91,8 +94,8 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -91,8 +94,8 @@ public class EnvironmentDecryptApplicationInitializer implements
// initialized, so we can fire an EnvironmentChangeEvent there to rebind
// @ConfigurationProperties, in case they were encrypted.
insert(mutable.getPropertySources(), decrypted);
parent.publishEvent(new EnvironmentChangeEvent(decrypted.getSource()
.keySet()));
parent.publishEvent(
new EnvironmentChangeEvent(decrypted.getSource().keySet()));
}
}
}
@ -112,7 +115,11 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -112,7 +115,11 @@ public class EnvironmentDecryptApplicationInitializer implements
public Map<String, Object> decrypt(PropertySources propertySources) {
Map<String, Object> overrides = new LinkedHashMap<String, Object>();
List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
for (PropertySource<?> source : propertySources) {
sources.add(0, source);
}
for (PropertySource<?> source : sources) {
decrypt(source, overrides);
}
return overrides;
@ -128,14 +135,14 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -128,14 +135,14 @@ public class EnvironmentDecryptApplicationInitializer implements
if (value.startsWith("{cipher}")) {
value = value.substring("{cipher}".length());
try {
value = encryptor.decrypt(value);
value = this.encryptor.decrypt(value);
if (logger.isDebugEnabled()) {
logger.debug("Decrypted: key=" + key);
}
}
catch (Exception e) {
String message = "Cannot decrypt: key=" + key;
if (failOnError) {
if (this.failOnError) {
throw new IllegalStateException(message, e);
}
if (logger.isDebugEnabled()) {
@ -163,5 +170,5 @@ public class EnvironmentDecryptApplicationInitializer implements @@ -163,5 +170,5 @@ public class EnvironmentDecryptApplicationInitializer implements
}
}
}

37
spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EnvironmentDecryptApplicationListenerTests.java

@ -15,46 +15,63 @@ @@ -15,46 +15,63 @@
*/
package org.springframework.cloud.bootstrap.encrypt;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import org.junit.Test;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.MapPropertySource;
import org.springframework.security.crypto.encrypt.Encryptors;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
public class EnvironmentDecryptApplicationListenerTests {
private EnvironmentDecryptApplicationInitializer listener = new EnvironmentDecryptApplicationInitializer(Encryptors.noOpText());
private EnvironmentDecryptApplicationInitializer listener = new EnvironmentDecryptApplicationInitializer(
Encryptors.noOpText());
@Test
public void decryptCipherKey() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, "foo: {cipher}bar");
listener.initialize(context);
this.listener.initialize(context);
assertEquals("bar", context.getEnvironment().getProperty("foo"));
}
@Test(expected=IllegalStateException.class)
@Test
public void propertySourcesOrderedCorrectly() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, "foo: {cipher}bar");
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
"test_override",
Collections.<String, Object> singletonMap("foo", "{cipher}spam")));
this.listener.initialize(context);
assertEquals("spam", context.getEnvironment().getProperty("foo"));
}
@Test(expected = IllegalStateException.class)
public void errorOnDecrypt() {
listener = new EnvironmentDecryptApplicationInitializer(Encryptors.text("deadbeef", "AFFE37"));
this.listener = new EnvironmentDecryptApplicationInitializer(
Encryptors.text("deadbeef", "AFFE37"));
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, "foo: {cipher}bar");
listener.initialize(context);
this.listener.initialize(context);
assertEquals("bar", context.getEnvironment().getProperty("foo"));
}
@Test
public void errorOnDecryptWithEmpty() {
listener = new EnvironmentDecryptApplicationInitializer(Encryptors.text("deadbeef", "AFFE37"));
listener.setFailOnError(false);
this.listener = new EnvironmentDecryptApplicationInitializer(
Encryptors.text("deadbeef", "AFFE37"));
this.listener.setFailOnError(false);
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, "foo: {cipher}bar");
listener.initialize(context);
this.listener.initialize(context);
// Empty is safest fallback for undecryptable cipher
assertEquals("", context.getEnvironment().getProperty("foo"));
}

Loading…
Cancel
Save