Add the ability for FailsafeTextEncryptor to have a delegate. (#1349)
Related to https://github.com/spring-cloud/spring-cloud-config/issues/2330 Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
This commit is contained in:
@@ -177,14 +177,40 @@ public abstract class TextEncryptorUtils {
|
||||
*/
|
||||
public static class FailsafeTextEncryptor implements TextEncryptor {
|
||||
|
||||
private TextEncryptor delegate;
|
||||
|
||||
/**
|
||||
* You can set a delegate that can be used to encrypt/decrypt values if later on
|
||||
* after the initial initialization of the app we have the necessary values to
|
||||
* create a proper {@link TextEncryptor}. Depending on where the encryption keys
|
||||
* are set we might not have the right values to create a {@link TextEncryptor}
|
||||
* (this can happen if the keys are in application.properties for example, but we
|
||||
* create the text encryptor during Bootstrap). The delegate functionality allows
|
||||
* us the option to set the delegate later on when we have the necessary values.
|
||||
* @param delegate The TextEncryptor to use for encryption/decryption
|
||||
*/
|
||||
public void setDelegate(TextEncryptor delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public TextEncryptor getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String text) {
|
||||
if (this.delegate != null) {
|
||||
return this.delegate.encrypt(text);
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"No encryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String encryptedText) {
|
||||
if (this.delegate != null) {
|
||||
return this.delegate.decrypt(encryptedText);
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?");
|
||||
}
|
||||
|
||||
@@ -142,6 +142,28 @@ public class EncryptionIntegrationTests {
|
||||
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 {
|
||||
|
||||
@@ -29,8 +29,15 @@ import org.springframework.boot.context.config.ConfigDataLocationResolver;
|
||||
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
|
||||
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
|
||||
import org.springframework.cloud.bootstrap.encrypt.RsaProperties;
|
||||
import org.springframework.cloud.bootstrap.encrypt.TextEncryptorUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
|
||||
public class TestConfigDataLocationResolver implements ConfigDataLocationResolver<TestConfigDataResource> {
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestConfigDataLocationResolver implements ConfigDataLocationResolver<TestConfigDataResource>, Ordered {
|
||||
|
||||
public static AtomicInteger count = new AtomicInteger(1);
|
||||
|
||||
@@ -52,6 +59,20 @@ public class TestConfigDataLocationResolver implements ConfigDataLocationResolve
|
||||
context.getBootstrapContext().registerIfAbsent(aClass, supplier);
|
||||
}
|
||||
String myplaceholder = context.getBinder().bind("myplaceholder", Bindable.of(String.class)).orElse("notfound");
|
||||
boolean createFailsafeDelegate = context.getBinder().bind("createfailsafedelegate", Bindable.of(Boolean.class))
|
||||
.orElse(Boolean.FALSE);
|
||||
if (createFailsafeDelegate) {
|
||||
assertThat(context.getBootstrapContext().isRegistered(TextEncryptor.class)).isTrue();
|
||||
TextEncryptor textEncryptor = context.getBootstrapContext().get(TextEncryptor.class);
|
||||
assertThat(textEncryptor).isInstanceOf(TextEncryptorUtils.FailsafeTextEncryptor.class);
|
||||
KeyProperties keyProperties = context.getBinder().bindOrCreate(KeyProperties.PREFIX,
|
||||
Bindable.of(KeyProperties.class));
|
||||
assertThat(TextEncryptorUtils.keysConfigured(keyProperties)).isTrue();
|
||||
RsaProperties rsaProperties = context.getBinder().bindOrCreate(RsaProperties.PREFIX,
|
||||
Bindable.of(RsaProperties.class));
|
||||
((TextEncryptorUtils.FailsafeTextEncryptor) textEncryptor)
|
||||
.setDelegate(TextEncryptorUtils.createTextEncryptor(keyProperties, rsaProperties));
|
||||
}
|
||||
HashMap<String, Object> props = new HashMap<>(config);
|
||||
props.put(TestEnvPostProcessor.EPP_VALUE, count.get());
|
||||
if (count.get() == 99 && myplaceholder.contains("${vcap")) {
|
||||
@@ -61,4 +82,9 @@ public class TestConfigDataLocationResolver implements ConfigDataLocationResolve
|
||||
return Collections.singletonList(new TestConfigDataResource(props));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
encrypt.key=pie
|
||||
Reference in New Issue
Block a user