EncryptionIntegrationTests.java
/*
* Copyright 2012-present 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.encrypt;
import org.junit.jupiter.api.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;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.test.TestConfigDataLocationResolver;
import org.springframework.cloud.context.test.TestEnvPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.BDDAssertions.then;
public class EncryptionIntegrationTests {
@Test
public void legacySymmetricPropertyValues() {
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 legacySymmetricConfigurationProperties() {
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 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 symmetricPropertyValuesFailOnError() {
assertThatThrownBy(() -> {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
.web(WebApplicationType.NONE)
.properties("spring.config.use-legacy-processing=false", "encrypt.key:pie",
"foo.password:{cipher}ZZZbf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
.run();
}).isInstanceOf(IllegalStateException.class).hasMessageContaining("Cannot decrypt");
}
@Test
public void symmetricPropertyValuesFailOnErrorFalse() {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
.web(WebApplicationType.NONE)
.properties("encrypt.fail-on-error=false", "spring.config.use-legacy-processing=false", "encrypt.key:pie",
"foo.password:{cipher}ZZZbf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
.run();
then(context.getEnvironment().getProperty("foo.password")).isEmpty();
}
@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 decryptEnvironmentPostProcessorDisabled() {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
.web(WebApplicationType.NONE)
.properties("spring.config.use-legacy-processing=false", "encrypt.key:pie",
"spring.cloud.decrypt-environment-post-processor.enabled=false",
"foo.password:{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95")
.run();
then(context.getEnvironment().getProperty("foo.password")).startsWith("{cipher}bf2945");
}
@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");
}
@Test
public void decryptAfterRefresh() {
TestConfigDataLocationResolver.config.put("foo.password",
"{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95");
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
.web(WebApplicationType.NONE)
.properties("encrypt.key:pie", TestEnvPostProcessor.EPP_ENABLED + "=true",
"spring.cloud.refresh.enabled:true")
.run();
TextEncryptor encryptor = context.getBean(TextEncryptor.class);
ContextRefresher refresher = context.getBean(ContextRefresher.class);
ConfigurableEnvironment env = context.getBean(ConfigurableEnvironment.class);
then(env.getProperty("foo.password")).isEqualTo("test");
TestConfigDataLocationResolver.config.put("foo.password", "{cipher}" + encryptor.encrypt("newValue"));
refresher.refresh();
then(env.getProperty("foo.password")).isEqualTo("newValue");
context.close();
TestConfigDataLocationResolver.config.clear();
}
@Test
public void failsafeTextEncryptor() {
ConfigurableApplicationContext context = new SpringApplicationBuilder(
EncryptionIntegrationTests.TestConfiguration.class)
.web(WebApplicationType.NONE)
.properties()
.run();
then(context.getBean(TextEncryptor.class)).isInstanceOf(TextEncryptorUtils.FailsafeTextEncryptor.class);
}
@Test
public void failsafeShouldHaveDelegate() {
TestConfigDataLocationResolver.config.put("foo.password",
"{cipher}bf29452295df354e6153c5b31b03ef23c70e55fba24299aa85c63438f1c43c95");
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestAutoConfiguration.class)
.web(WebApplicationType.NONE)
.properties("spring.config.import=testdatasource:,classpath:application-failsafe.properties",
"createfailsafedelegate=true")
.run();
ConfigurableEnvironment env = context.getBean(ConfigurableEnvironment.class);
then(env.getProperty("foo.password")).isEqualTo("test");
context.close();
TestConfigDataLocationResolver.config.clear();
}
@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 {
private String password;
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
}