Creates TextEncryptorBindHandler for Binder decryption.
It is registered in TextEncryptorConfigBootstrapper for later use in other ConfigData implementations.
This commit is contained in:
committed by
spencergibb
parent
1f0f750707
commit
7211cdd2e8
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.bootstrap.TextEncryptorConfigurationPropertiesBindHandlerAdvisor;
|
||||
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
|
||||
import org.springframework.cloud.bootstrap.encrypt.KeyProperties.KeyStore;
|
||||
import org.springframework.cloud.bootstrap.encrypt.RsaProperties;
|
||||
import org.springframework.cloud.context.encrypt.EncryptorFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
|
||||
import org.springframework.security.rsa.crypto.RsaSecretEncryptor;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ TextEncryptor.class })
|
||||
@ConditionalOnProperty(value = "spring.config.use-legacy-processing", havingValue = "false")
|
||||
public class EncryptionBootstrapAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private TextEncryptor encryptor;
|
||||
|
||||
@Autowired
|
||||
private KeyProperties key;
|
||||
|
||||
@Bean
|
||||
@ConfigurationPropertiesBinding
|
||||
TextEncryptorConfigurationPropertiesBindHandlerAdvisor textEncryptorConfigurationPropertiesBindHandlerAdvisor(ApplicationContext applicationContext) {
|
||||
return new TextEncryptorConfigurationPropertiesBindHandlerAdvisor(applicationContext);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(KeyCondition.class)
|
||||
@ConditionalOnClass(RsaSecretEncryptor.class)
|
||||
@EnableConfigurationProperties({ RsaProperties.class })
|
||||
protected static class RsaEncryptionConfiguration {
|
||||
|
||||
@Autowired
|
||||
private KeyProperties key;
|
||||
|
||||
@Autowired
|
||||
private RsaProperties rsaProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TextEncryptor.class)
|
||||
@ConfigurationPropertiesBinding
|
||||
public TextEncryptor textEncryptor() {
|
||||
KeyStore keyStore = this.key.getKeyStore();
|
||||
if (keyStore.getLocation() != null) {
|
||||
if (keyStore.getLocation().exists()) {
|
||||
return new RsaSecretEncryptor(
|
||||
new KeyStoreKeyFactory(keyStore.getLocation(), keyStore.getPassword().toCharArray())
|
||||
.getKeyPair(keyStore.getAlias(), keyStore.getSecret().toCharArray()),
|
||||
this.rsaProperties.getAlgorithm(), this.rsaProperties.getSalt(),
|
||||
this.rsaProperties.isStrong());
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Invalid keystore location");
|
||||
}
|
||||
|
||||
return new EncryptorFactory(this.key.getSalt()).create(this.key.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(KeyCondition.class)
|
||||
@ConditionalOnMissingClass("org.springframework.security.rsa.crypto.RsaSecretEncryptor")
|
||||
protected static class VanillaEncryptionConfiguration {
|
||||
|
||||
@Autowired
|
||||
private KeyProperties key;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TextEncryptor.class)
|
||||
@ConfigurationPropertiesBinding
|
||||
public TextEncryptor textEncryptor() {
|
||||
return new EncryptorFactory(this.key.getSalt()).create(this.key.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A Spring Boot condition for key encryption.
|
||||
*/
|
||||
public static class KeyCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
Environment environment = context.getEnvironment();
|
||||
if (hasProperty(environment, "encrypt.key-store.location")) {
|
||||
if (hasProperty(environment, "encrypt.key-store.password")) {
|
||||
return ConditionOutcome.match("Keystore found in Environment");
|
||||
}
|
||||
return ConditionOutcome.noMatch("Keystore found but no password in Environment");
|
||||
}
|
||||
else if (hasProperty(environment, "encrypt.key")) {
|
||||
return ConditionOutcome.match("Key found in Environment");
|
||||
}
|
||||
return ConditionOutcome.noMatch("Keystore nor key found in Environment");
|
||||
}
|
||||
|
||||
private boolean hasProperty(Environment environment, String key) {
|
||||
String value = environment.getProperty(key);
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.hasText(environment.resolvePlaceholders(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TextEncryptor that just fails, so that users don't get a false sense of security
|
||||
* adding ciphers to config files and not getting them decrypted.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
protected static class FailsafeTextEncryptor implements TextEncryptor {
|
||||
|
||||
@Override
|
||||
public String encrypt(String text) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No encryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String encryptedText) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.bootstrap;
|
||||
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.Bootstrapper;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
|
||||
import org.springframework.cloud.bootstrap.encrypt.RsaProperties;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Bootstrapper
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public class TextEncryptorConfigBootstrapper implements Bootstrapper {
|
||||
|
||||
@Override
|
||||
public void intitialize(BootstrapRegistry registry) {
|
||||
if (!ClassUtils.isPresent("org.springframework.security.crypto.encrypt.TextEncryptor", null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
registry.registerIfAbsent(KeyProperties.class,
|
||||
context -> context.get(Binder.class)
|
||||
.bind("encrypt", KeyProperties.class)
|
||||
.orElseGet(KeyProperties::new));
|
||||
registry.registerIfAbsent(RsaProperties.class,
|
||||
context -> context.get(Binder.class)
|
||||
.bind("encrypt.rsa", RsaProperties.class)
|
||||
.orElseGet(RsaProperties::new));
|
||||
|
||||
|
||||
/*registry.registerIfAbsent(TextEncryptorConfigurationPropertiesBindHandlerAdvisor.class, context -> {
|
||||
if (isLegacyProcessingEnabled(context.get(Binder.class))) {
|
||||
return null;
|
||||
}
|
||||
return new TextEncryptorConfigurationPropertiesBindHandlerAdvisor(context.get(TextEncryptor.class));
|
||||
});*/
|
||||
|
||||
// promote beans to context
|
||||
registry.addCloseListener(event -> {
|
||||
if (isLegacyProcessingEnabled(event.getApplicationContext().getEnvironment())) {
|
||||
return;
|
||||
}
|
||||
KeyProperties keyProperties = event.getBootstrapContext().get(KeyProperties.class);
|
||||
if (keyProperties != null) {
|
||||
event.getApplicationContext().getBeanFactory().registerSingleton("keyProperties",
|
||||
keyProperties);
|
||||
}
|
||||
RsaProperties rsaProperties = event.getBootstrapContext().get(RsaProperties.class);
|
||||
if (rsaProperties != null) {
|
||||
event.getApplicationContext().getBeanFactory().registerSingleton("rsaProperties",
|
||||
rsaProperties);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isLegacyProcessingEnabled(Binder binder) {
|
||||
return binder.bind("spring.config.use-legacy-processing", Boolean.class).orElse(false);
|
||||
}
|
||||
|
||||
private boolean isLegacyProcessingEnabled(Environment environment) {
|
||||
return environment.getProperty("spring.config.use-legacy-processing", Boolean.class, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* TextEncryptor that just fails, so that users don't get a false sense of security
|
||||
* adding ciphers to config files and not getting them decrypted.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
protected static class FailsafeTextEncryptor implements TextEncryptor {
|
||||
|
||||
@Override
|
||||
public String encrypt(String text) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No encryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String encryptedText) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.bootstrap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesBindHandlerAdvisor;
|
||||
import org.springframework.boot.context.properties.bind.AbstractBindHandler;
|
||||
import org.springframework.boot.context.properties.bind.BindContext;
|
||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
|
||||
public class TextEncryptorConfigurationPropertiesBindHandlerAdvisor implements ConfigurationPropertiesBindHandlerAdvisor {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public TextEncryptorConfigurationPropertiesBindHandlerAdvisor(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindHandler apply(BindHandler bindHandler) {
|
||||
return wrappedBindHandler(bindHandler);
|
||||
}
|
||||
|
||||
private BindHandler wrappedBindHandler(BindHandler handler) {
|
||||
KeyProperties keyProperties = this.applicationContext.getBean(KeyProperties.class);
|
||||
TextEncryptorBindHandler textEncryptorBindHandler = new TextEncryptorBindHandler(this.applicationContext.getBeanProvider(TextEncryptor.class).getIfAvailable(FailsafeTextEncryptor::new), keyProperties);
|
||||
return new BindHandler() {
|
||||
@Override
|
||||
public <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
|
||||
return handler.onStart(name, target, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onSuccess(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
|
||||
Object defaultHandlerResult = handler.onSuccess(name, target, context, result);
|
||||
return textEncryptorBindHandler.onSuccess(name, target, context, defaultHandlerResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onCreate(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
|
||||
return handler.onCreate(name, target, context, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Exception error) throws Exception {
|
||||
return handler.onFailure(name, target, context, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) throws Exception {
|
||||
handler.onFinish(name, target, context, result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* TextEncryptor that just fails, so that users don't get a false sense of security
|
||||
* adding ciphers to config files and not getting them decrypted.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
protected static class FailsafeTextEncryptor implements TextEncryptor {
|
||||
|
||||
@Override
|
||||
public String encrypt(String text) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No encryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String encryptedText) {
|
||||
throw new UnsupportedOperationException(
|
||||
"No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class TextEncryptorBindHandler extends AbstractBindHandler {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TextEncryptorBindHandler.class);
|
||||
|
||||
/**
|
||||
* Prefix indicating an encrypted value.
|
||||
*/
|
||||
protected static final String ENCRYPTED_PROPERTY_PREFIX = "{cipher}";
|
||||
|
||||
private final TextEncryptor textEncryptor;
|
||||
|
||||
private final KeyProperties keyProperties;
|
||||
|
||||
public TextEncryptorBindHandler(TextEncryptor textEncryptor, KeyProperties keyProperties) {
|
||||
this.textEncryptor = textEncryptor;
|
||||
this.keyProperties = keyProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onSuccess(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
|
||||
if (result instanceof String) {
|
||||
return decrypt(name.toString(), (String) result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String decrypt(String key, String original) {
|
||||
String value = original.substring(ENCRYPTED_PROPERTY_PREFIX.length());
|
||||
try {
|
||||
value = this.textEncryptor.decrypt(value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Decrypted: key=" + key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
catch (Exception e) {
|
||||
String message = "Cannot decrypt: key=" + key;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(message, e);
|
||||
}
|
||||
else {
|
||||
logger.warn(message);
|
||||
}
|
||||
if (this.keyProperties.isFailOnError()) {
|
||||
throw new IllegalStateException(message, e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,8 @@ org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfi
|
||||
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
|
||||
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
|
||||
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
|
||||
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
|
||||
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration,\
|
||||
org.springframework.cloud.autoconfigure.EncryptionBootstrapAutoConfiguration
|
||||
# Application Listeners
|
||||
org.springframework.context.ApplicationListener=\
|
||||
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
|
||||
@@ -17,3 +18,5 @@ org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
|
||||
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
|
||||
org.springframework.cloud.util.random.CachedRandomPropertySourceAutoConfiguration
|
||||
org.springframework.boot.Bootstrapper=\
|
||||
org.springframework.cloud.bootstrap.TextEncryptorConfigBootstrapper
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.bootstrap.encrypt;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -30,7 +31,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
public class EncryptionIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void symmetricPropertyValues() {
|
||||
public void legacySymmetricPropertyValues() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.config.use-legacy-processing=true", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
@@ -39,7 +40,7 @@ public class EncryptionIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void symmetricConfigurationProperties() {
|
||||
public void legacySymmetricConfigurationProperties() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.config.use-legacy-processing=true", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
@@ -47,12 +48,55 @@ public class EncryptionIntegrationTests {
|
||||
then(context.getBean(PasswordProperties.class).getPassword()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propSymmetricPropertyValues() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.cloud.bootstrap.enabled=true", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
.run();
|
||||
then(context.getEnvironment().getProperty("foo.password")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propSymmetricConfigurationProperties() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.cloud.bootstrap.enabled=true", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
.run();
|
||||
then(context.getBean(PasswordProperties.class).getPassword()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void symmetricPropertyValues() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.config.use-legacy-processing=false", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
.run();
|
||||
then(context.getEnvironment().getProperty("foo.password")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void symmetricConfigurationProperties() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties("spring.config.use-legacy-processing=false", "encrypt.key:pie",
|
||||
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
|
||||
.run();
|
||||
then(context.getBean(PasswordProperties.class).getPassword()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(PasswordProperties.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@EnableConfigurationProperties(PasswordProperties.class)
|
||||
protected static class TestAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties("foo")
|
||||
protected static class PasswordProperties {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user