Simplify encryption autoconfig (#2065)

This commit is contained in:
Olga Maciaszek-Sharma
2022-03-17 17:30:39 +01:00
parent 97421f0bf8
commit 7acfb68078
6 changed files with 169 additions and 77 deletions

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2022 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.config.server.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.cloud.config.server.encryption.LocatorTextEncryptor;
import org.springframework.cloud.config.server.encryption.TextEncryptorLocator;
import org.springframework.cloud.context.encrypt.EncryptorFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.util.StringUtils;
/**
* Default text encryption auto-configuration.
*
* @author Olga Maciaszek-Sharma
* @since 3.1.2
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(RsaEncryptionAutoConfiguration.class)
@EnableConfigurationProperties
public class DefaultTextEncryptionAutoConfiguration {
private static final Log LOG = LogFactory.getLog(DefaultTextEncryptionAutoConfiguration.class);
@Autowired
ApplicationContext context;
@Bean
@ConditionalOnMissingBean
public KeyProperties keyProperties() {
return new KeyProperties();
}
@Bean
@ConditionalOnMissingBean(TextEncryptor.class)
@ConditionalOnBean(TextEncryptorLocator.class)
public TextEncryptor defaultLocatorBasedTextEncryptor(TextEncryptorLocator locator) {
return new LocatorTextEncryptor(locator);
}
@Bean
@ConditionalOnMissingBean(TextEncryptor.class)
public TextEncryptor defaultTextEncryptor(KeyProperties key) {
if (StringUtils.hasText(key.getKey())) {
return new EncryptorFactory(key.getSalt()).create(key.getKey());
}
return Encryptors.noOpText();
}
}

View File

@@ -17,33 +17,20 @@
package org.springframework.cloud.config.server.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.config.server.encryption.CipherEnvironmentEncryptor;
import org.springframework.cloud.config.server.encryption.EnvironmentEncryptor;
import org.springframework.cloud.config.server.encryption.KeyStoreTextEncryptorLocator;
import org.springframework.cloud.config.server.encryption.LocatorTextEncryptor;
import org.springframework.cloud.config.server.encryption.SingleTextEncryptorLocator;
import org.springframework.cloud.config.server.encryption.TextEncryptorLocator;
import org.springframework.cloud.context.encrypt.EncryptorFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
import org.springframework.security.rsa.crypto.RsaAlgorithm;
import org.springframework.security.rsa.crypto.RsaSecretEncryptor;
import org.springframework.util.StringUtils;
/**
* Auto configuration for text encryptors and environment encryptors (non-web stuff).
* Auto-configuration for text encryptors and environment encryptors (non-web stuff).
* Users can provide beans of the same type as any or all of the beans defined here in
* application code to override the default behaviour.
*
@@ -54,14 +41,14 @@ import org.springframework.util.StringUtils;
*
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@Import(SingleTextEncryptorConfiguration.class)
@AutoConfigureAfter(DefaultTextEncryptionAutoConfiguration.class)
public class EncryptionAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public KeyProperties keyProperties() {
return new KeyProperties();
@ConditionalOnBean(TextEncryptor.class)
@ConditionalOnMissingBean(TextEncryptorLocator.class)
public SingleTextEncryptorLocator singleTextEncryptorLocator(TextEncryptor encryptor) {
return new SingleTextEncryptorLocator(encryptor);
}
@Bean
@@ -76,57 +63,4 @@ public class EncryptionAutoConfiguration {
return new CipherEnvironmentEncryptor(locator);
}
@Bean
@ConditionalOnMissingBean(TextEncryptor.class)
public TextEncryptor defaultTextEncryptor(@Autowired(required = false) TextEncryptorLocator locator,
KeyProperties key) {
if (locator != null) {
return new LocatorTextEncryptor(locator);
}
if (StringUtils.hasText(key.getKey())) {
return new EncryptorFactory(key.getSalt()).create(key.getKey());
}
return Encryptors.noOpText();
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RsaSecretEncryptor.class)
@ConditionalOnProperty(prefix = "encrypt.key-store", value = "location", matchIfMissing = false)
protected static class KeyStoreConfiguration {
@Autowired
private KeyProperties key;
@Autowired
private RsaProperties rsaProperties;
@Bean
@ConditionalOnMissingBean
public TextEncryptorLocator textEncryptorLocator() {
KeyStore keyStore = key.getKeyStore();
KeyStoreTextEncryptorLocator locator = new KeyStoreTextEncryptorLocator(
new KeyStoreKeyFactory(keyStore.getLocation(), keyStore.getPassword().toCharArray(),
key.getKeyStore().getType()),
keyStore.getSecret(), keyStore.getAlias());
RsaAlgorithm algorithm = this.rsaProperties.getAlgorithm();
locator.setRsaAlgorithm(algorithm);
locator.setSalt(this.rsaProperties.getSalt());
locator.setStrong(this.rsaProperties.isStrong());
return locator;
}
}
}
@ConditionalOnBean(TextEncryptor.class)
@ConditionalOnMissingBean(TextEncryptorLocator.class)
@Configuration(proxyBeanMethods = false)
class SingleTextEncryptorConfiguration {
@Bean
public SingleTextEncryptorLocator textEncryptorLocator(TextEncryptor encryptor) {
return new SingleTextEncryptorLocator(encryptor);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2002-2022 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.config.server.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.cloud.bootstrap.encrypt.RsaProperties;
import org.springframework.cloud.config.server.encryption.KeyStoreTextEncryptorLocator;
import org.springframework.cloud.config.server.encryption.TextEncryptorLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
import org.springframework.security.rsa.crypto.RsaAlgorithm;
import org.springframework.security.rsa.crypto.RsaSecretEncryptor;
/**
* Auto-configuration for RSA encryption.
*
* @author Olga Maciaszek-Sharma
* @since 3.1.2
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "encrypt.key-store", value = "location")
@ConditionalOnClass(RsaSecretEncryptor.class)
@EnableConfigurationProperties
public class RsaEncryptionAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public KeyProperties keyProperties() {
return new KeyProperties();
}
@Bean
@ConditionalOnMissingBean
public TextEncryptorLocator textEncryptorLocator(KeyProperties key, RsaProperties rsaProperties) {
KeyProperties.KeyStore keyStore = key.getKeyStore();
KeyStoreTextEncryptorLocator locator = new KeyStoreTextEncryptorLocator(
new KeyStoreKeyFactory(keyStore.getLocation(), keyStore.getPassword().toCharArray(),
key.getKeyStore().getType()),
keyStore.getSecret(), keyStore.getAlias());
RsaAlgorithm algorithm = rsaProperties.getAlgorithm();
locator.setRsaAlgorithm(algorithm);
locator.setSalt(rsaProperties.getSalt());
locator.setStrong(rsaProperties.isStrong());
return locator;
}
}

View File

@@ -109,7 +109,9 @@ public class EncryptionController {
Map<String, String> keys = helper.getEncryptorKeys(name, profiles, input);
String textToEncrypt = helper.stripPrefix(input);
String encrypted = helper.addPrefix(keys, encryptorLocator.locate(keys).encrypt(textToEncrypt));
logger.info("Encrypted data");
if (logger.isInfoEnabled()) {
logger.info("Encrypted data");
}
return encrypted;
}
@@ -128,21 +130,31 @@ public class EncryptionController {
encryptor = getEncryptor(name, profiles, data);
String input = stripFormData(helper.stripPrefix(data), type, true);
String decrypted = encryptor.decrypt(input);
logger.info("Decrypted cipher data");
if (logger.isInfoEnabled()) {
logger.info("Decrypted cipher data");
}
return decrypted;
}
catch (IllegalArgumentException | IllegalStateException e) {
logger.error("Cannot decrypt key:" + name + ", value:" + data, e);
if (logger.isErrorEnabled()) {
logger.error("Cannot decrypt key:" + name + ", value:" + data, e);
}
throw new InvalidCipherException();
}
}
private TextEncryptor getEncryptor(String name, String profiles, String data) {
if (encryptorLocator == null) {
if (logger.isDebugEnabled()) {
logger.debug("Text encryptorLocator is null.");
}
throw new KeyNotInstalledException();
}
TextEncryptor encryptor = encryptorLocator.locate(helper.getEncryptorKeys(name, profiles, data));
if (encryptor == null) {
if (logger.isDebugEnabled()) {
logger.debug("TextEncryptor is null.");
}
throw new KeyNotInstalledException();
}
return encryptor;

View File

@@ -1,6 +1,8 @@
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapConfiguration,\
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
# Environment PostProcessor
@@ -11,6 +13,8 @@ org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapApplicati
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.config.server.diagnostics.GitUriFailureAnalyzer

View File

@@ -76,7 +76,7 @@ public class BootstrapConfigServerIntegrationTests {
@Test
@Ignore // FIXME: configdata
public void environmentBootstraps() throws Exception {
public void environmentBootstraps() {
assertThat(this.env.getProperty("info.foo", "")).isEqualTo("bar");
assertThat(this.env.getProperty("config.foo", "")).isEqualTo("foo");
}