Merge remote-tracking branch 'origin/2.0.x'
This commit is contained in:
@@ -163,31 +163,34 @@ public class EnvironmentDecryptApplicationInitializer implements
|
|||||||
sources.add(0, source);
|
sources.add(0, source);
|
||||||
}
|
}
|
||||||
for (PropertySource<?> source : sources) {
|
for (PropertySource<?> source : sources) {
|
||||||
decrypt(source, overrides);
|
collectEncryptedProperties(source, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doDecrypt(overrides);
|
||||||
return overrides;
|
return overrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> decrypt(PropertySource<?> source) {
|
private Map<String, Object> decrypt(PropertySource<?> source) {
|
||||||
Map<String, Object> overrides = new LinkedHashMap<>();
|
Map<String, Object> overrides = new LinkedHashMap<>();
|
||||||
decrypt(source, overrides);
|
collectEncryptedProperties(source, overrides);
|
||||||
|
doDecrypt(overrides);
|
||||||
return overrides;
|
return overrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern COLLECTION_PROPERTY = Pattern
|
private static final Pattern COLLECTION_PROPERTY = Pattern
|
||||||
.compile("(\\S+)?\\[(\\d+)\\](\\.\\S+)?");
|
.compile("(\\S+)?\\[(\\d+)\\](\\.\\S+)?");
|
||||||
|
|
||||||
private void decrypt(PropertySource<?> source, Map<String, Object> overrides) {
|
private void collectEncryptedProperties(PropertySource<?> source,
|
||||||
|
Map<String, Object> overrides) {
|
||||||
|
|
||||||
if (source instanceof CompositePropertySource) {
|
if (source instanceof CompositePropertySource) {
|
||||||
|
|
||||||
for (PropertySource<?> nested : ((CompositePropertySource) source)
|
for (PropertySource<?> nested : ((CompositePropertySource) source)
|
||||||
.getPropertySources()) {
|
.getPropertySources()) {
|
||||||
decrypt(nested, overrides);
|
collectEncryptedProperties(nested, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else if (source instanceof EnumerablePropertySource) {
|
||||||
else if (source instanceof EnumerablePropertySource) {
|
|
||||||
Map<String, Object> otherCollectionProperties = new LinkedHashMap<>();
|
Map<String, Object> otherCollectionProperties = new LinkedHashMap<>();
|
||||||
boolean sourceHasDecryptedCollection = false;
|
boolean sourceHasDecryptedCollection = false;
|
||||||
|
|
||||||
@@ -197,37 +200,16 @@ public class EnvironmentDecryptApplicationInitializer implements
|
|||||||
if (property != null) {
|
if (property != null) {
|
||||||
String value = property.toString();
|
String value = property.toString();
|
||||||
if (value.startsWith("{cipher}")) {
|
if (value.startsWith("{cipher}")) {
|
||||||
value = value.substring("{cipher}".length());
|
|
||||||
try {
|
|
||||||
value = this.encryptor.decrypt(value);
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Decrypted: key=" + key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
String message = "Cannot decrypt: key=" + key;
|
|
||||||
if (this.failOnError) {
|
|
||||||
throw new IllegalStateException(message, e);
|
|
||||||
}
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.warn(message, e);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.warn(message);
|
|
||||||
}
|
|
||||||
// Set value to empty to avoid making a password out of the
|
|
||||||
// cipher text
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
overrides.put(key, value);
|
overrides.put(key, value);
|
||||||
if (COLLECTION_PROPERTY.matcher(key).matches()) {
|
if (COLLECTION_PROPERTY.matcher(key).matches()) {
|
||||||
sourceHasDecryptedCollection = true;
|
sourceHasDecryptedCollection = true;
|
||||||
}
|
}
|
||||||
}
|
} else if (COLLECTION_PROPERTY.matcher(key).matches()) {
|
||||||
else if (COLLECTION_PROPERTY.matcher(key).matches()) {
|
// put non-encrypted properties so merging of index properties
|
||||||
// put non-ecrypted properties so merging of index properties
|
|
||||||
// happens correctly
|
// happens correctly
|
||||||
otherCollectionProperties.put(key, value);
|
otherCollectionProperties.put(key, value);
|
||||||
|
} else {
|
||||||
|
overrides.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,4 +221,35 @@ public class EnvironmentDecryptApplicationInitializer implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doDecrypt(Map<String, Object> overrides) {
|
||||||
|
for (String key : overrides.keySet()) {
|
||||||
|
String value = overrides.get(key).toString();
|
||||||
|
if (value.startsWith("{cipher}")) {
|
||||||
|
value = value.substring("{cipher}".length());
|
||||||
|
try {
|
||||||
|
value = this.encryptor.decrypt(value);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Decrypted: key=" + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
String message = "Cannot decrypt: key=" + key;
|
||||||
|
if (this.failOnError) {
|
||||||
|
throw new IllegalStateException(message, e);
|
||||||
|
}
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.warn(message, e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.warn(message);
|
||||||
|
}
|
||||||
|
// Set value to empty to avoid making a password out of the
|
||||||
|
// cipher text
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
overrides.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.springframework.cloud.bootstrap.encrypt.EnvironmentDecryptApplicationInitializer.DECRYPTED_PROPERTY_SOURCE_NAME;
|
import static org.springframework.cloud.bootstrap.encrypt.EnvironmentDecryptApplicationInitializer.DECRYPTED_PROPERTY_SOURCE_NAME;
|
||||||
|
|
||||||
@@ -78,6 +80,17 @@ public class EnvironmentDecryptApplicationInitializerTests {
|
|||||||
assertEquals("spam", context.getEnvironment().getProperty("foo"));
|
assertEquals("spam", context.getEnvironment().getProperty("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void propertySourcesOrderedCorrectlyWithUnencryptedOverrides() {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
TestPropertyValues.of("foo: {cipher}bar").applyTo(context);
|
||||||
|
context.getEnvironment().getPropertySources()
|
||||||
|
.addFirst(new MapPropertySource("test_override",
|
||||||
|
Collections.<String, Object>singletonMap("foo", "spam")));
|
||||||
|
this.listener.initialize(context);
|
||||||
|
assertEquals("spam", context.getEnvironment().getProperty("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void errorOnDecrypt() {
|
public void errorOnDecrypt() {
|
||||||
this.listener = new EnvironmentDecryptApplicationInitializer(
|
this.listener = new EnvironmentDecryptApplicationInitializer(
|
||||||
@@ -173,4 +186,22 @@ public class EnvironmentDecryptApplicationInitializerTests {
|
|||||||
initializer.initialize(ctx);
|
initializer.initialize(ctx);
|
||||||
assertEquals(expected, ctx.getEnvironment().getProperty("key"));
|
assertEquals(expected, ctx.getEnvironment().getProperty("key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnlyDecryptIfNotOverridden() {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
TextEncryptor encryptor = mock(TextEncryptor.class);
|
||||||
|
when(encryptor.decrypt("bar2")).thenReturn("bar2");
|
||||||
|
EnvironmentDecryptApplicationInitializer initializer = new EnvironmentDecryptApplicationInitializer(
|
||||||
|
encryptor);
|
||||||
|
TestPropertyValues.of("foo: {cipher}bar", "foo2: {cipher}bar2").applyTo(context);
|
||||||
|
context.getEnvironment().getPropertySources()
|
||||||
|
.addFirst(new MapPropertySource("test_override",
|
||||||
|
Collections.<String, Object>singletonMap("foo", "spam")));
|
||||||
|
initializer.initialize(context);
|
||||||
|
assertEquals("spam", context.getEnvironment().getProperty("foo"));
|
||||||
|
assertEquals("bar2", context.getEnvironment().getProperty("foo2"));
|
||||||
|
verify(encryptor).decrypt("bar2");
|
||||||
|
verifyNoMoreInteractions(encryptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user