blob: 556d59b71e7c0e335e4f5a555743b71ba421a842 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* http://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.apache.camel.component.jasypt.springboot;
import org.apache.camel.component.properties.PropertiesParser;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.jasypt.exceptions.EncryptionInitializationException;
import org.jasypt.iv.IvGenerator;
import org.jasypt.iv.NoIvGenerator;
import org.jasypt.iv.RandomIvGenerator;
import org.jasypt.salt.RandomSaltGenerator;
import org.jasypt.salt.SaltGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertyResolver;
import java.lang.annotation.Annotation;
import static org.apache.camel.component.jasypt.springboot.JasyptEncryptedPropertiesConfiguration.PREFIX;
import static org.apache.camel.component.jasypt.springboot.JasyptEncryptedPropertiesUtils.isIVNeeded;
import static org.apache.camel.util.ObjectHelper.isNotEmpty;
import static org.apache.camel.util.StringHelper.after;
import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from;
import static org.springframework.core.ResolvableType.forClass;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "camel.component.jasypt.enabled", matchIfMissing = true)
@AutoConfigureBefore(CamelAutoConfiguration.class)
public class JasyptEncryptedPropertiesAutoconfiguration {
private static final Logger LOG = LoggerFactory.getLogger(JasyptEncryptedPropertiesAutoconfiguration.class);
private static final String SYSTEM_ENVIRONMENT_PREFIX = "sysenv:";
private static final String SYSTEM_PROPERTIES_PREFIX = "sys:";
@Bean
public JasyptEncryptedPropertiesConfiguration JasyptEncryptedPropertiesAutoconfiguration(final ConfigurableEnvironment environment) {
JasyptEncryptedPropertiesConfiguration config = new JasyptEncryptedPropertiesConfiguration();
final BindHandler handler = new IgnoreErrorsBindHandler(BindHandler.DEFAULT);
final MutablePropertySources propertySources = environment.getPropertySources();
PropertySourcesPlaceholdersResolver propertyResolver = new PropertySourcesPlaceholdersResolver(propertySources);
Iterable<ConfigurationPropertySource> configurationPropertySources = from(propertySources);
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
final Binder binder = new Binder(configurationPropertySources, propertyResolver, conversionService);
final ResolvableType type = forClass(JasyptEncryptedPropertiesConfiguration.class);
final Annotation annotation = findAnnotation(JasyptEncryptedPropertiesConfiguration.class, ConfigurationProperties.class);
final Annotation[] annotations = new Annotation[]{annotation};
final Bindable<?> target = Bindable.of(type).withExistingValue(config).withAnnotations(annotations);
binder.bind(PREFIX, target, handler);
return config;
}
@Bean
@ConditionalOnMissingBean(EnvironmentStringPBEConfig.class)
public EnvironmentStringPBEConfig environmentVariablesConfiguration(JasyptEncryptedPropertiesConfiguration configuration) {
EnvironmentStringPBEConfig environmentStringPBEConfig = new EnvironmentStringPBEConfig();
environmentStringPBEConfig.setAlgorithm(configuration.getAlgorithm());
environmentStringPBEConfig.setIvGenerator(getIVGenerator(configuration));
environmentStringPBEConfig.setSaltGenerator(getSaltGenerator(configuration));
environmentStringPBEConfig.setProviderClassName(configuration.getProviderClassName());
parsePassword(environmentStringPBEConfig, configuration);
return environmentStringPBEConfig;
}
@Bean
@ConditionalOnMissingBean(StringEncryptor.class)
public StringEncryptor stringEncryptor(EnvironmentStringPBEConfig environmentVariablesConfiguration) {
StandardPBEStringEncryptor standardPBEStringEncryptor = new StandardPBEStringEncryptor();
standardPBEStringEncryptor.setConfig(environmentVariablesConfiguration);
return standardPBEStringEncryptor;
}
@Bean
public EncryptablePropertySourcesPlaceholderConfigurer propertyConfigurer(StringEncryptor stringEncryptor) {
return new EncryptablePropertySourcesPlaceholderConfigurer(stringEncryptor);
}
/*
This bean override the default org.apache.camel.spring.boot.SpringPropertiesParser
and allow the use of encrypted properties inside the camel context.
*/
@Bean
public PropertiesParser encryptedPropertiesParser(PropertyResolver propertyResolver, StringEncryptor stringEncryptor) {
return new JasyptSpringEncryptedPropertiesParser(propertyResolver, stringEncryptor);
}
public SaltGenerator getSaltGenerator(JasyptEncryptedPropertiesConfiguration configuration) {
String saltGeneratorClassName = configuration.getSaltGeneratorClassName();
SaltGenerator saltGenerator = loadClass(saltGeneratorClassName);
if (saltGenerator != null) {
return saltGenerator;
}
return new RandomSaltGenerator();
}
private IvGenerator getIVGenerator(JasyptEncryptedPropertiesConfiguration configuration) {
String ivGeneratorClassName = configuration.getIvGeneratorClassName();
IvGenerator ivGenerator = loadClass(ivGeneratorClassName);
if (ivGenerator != null) {
return ivGenerator;
}
String algorithm = configuration.getAlgorithm();
return isIVNeeded(algorithm) ? new RandomIvGenerator() : new NoIvGenerator();
}
private <T> T loadClass(String className) {
try {
final Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
return (T) clazz.newInstance();
} catch (Exception e) {
throw new EncryptionInitializationException(e);
}
}
private void parsePassword(EnvironmentStringPBEConfig environmentStringPBEConfig, JasyptEncryptedPropertiesConfiguration configuration) {
String passwordReference = configuration.getPassword();
if (isNotEmpty(passwordReference) && passwordReference.startsWith(SYSTEM_ENVIRONMENT_PREFIX)) {
environmentStringPBEConfig.setPasswordEnvName(after(passwordReference, SYSTEM_ENVIRONMENT_PREFIX));
return;
}
if (isNotEmpty(passwordReference) && passwordReference.startsWith(SYSTEM_PROPERTIES_PREFIX)) {
environmentStringPBEConfig.setPasswordSysPropertyName(after(passwordReference, SYSTEM_PROPERTIES_PREFIX));
return;
}
environmentStringPBEConfig.setPassword(passwordReference);
}
}