The following approach works for me. Create @Context
annotated Singleton
which is will be created before all other beans. At the time of creation Environment
is already initialised and all configuration properties are loaded. Next find all properties having started with special prefix defining encrypted value. Create new property source with decrypted values and put it into Environment
as new PropertySource
.
Code:
@Context
@Singleton
@Requires(property = "JASYPT_ENCRYPTOR_PASSWORD")
@Slf4j
public class JasyptConfigurationPropertiesDecryptor implements BeanInitializedEventListener<Environment> {
private static final String PREFIX = "ENC(";
public JasyptConfigurationPropertiesDecryptor(DefaultEnvironment env, @Value("${JASYPT_ENCRYPTOR_PASSWORD}") String encPassword) {
log.info("JasyptBootstrapDecryptor started");
processConfigurationProperties(env, encPassword);
}
public void processConfigurationProperties(DefaultEnvironment env, String encPassword) {
StandardPBEStringEncryptor encryptor = encryptor(encPassword);
Map<String, Object> all = env.getAllProperties(StringConvention.RAW, MapFormat.MapTransformation.FLAT);
Map<String, Object> decrypted = all.entrySet().stream()
.filter(entry -> entry.getValue().toString().startsWith(PREFIX))
.collect(collector(encryptor));
env.addPropertySource(MapPropertySource.of("decrypted", decrypted));
}
private StandardPBEStringEncryptor encryptor(String encPassword) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(encPassword);
encryptor.setStringOutputType("base64");
encryptor.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
encryptor.setIvGenerator(new RandomIvGenerator());
return encryptor;
}
@Nonnull
private Collector<Map.Entry<String, Object>, ?, Map<String, Object>> collector(StandardPBEStringEncryptor encryptor) {
return Collectors.toMap(Map.Entry::getKey, entry -> decrypt(entry, encryptor));
}
private String decrypt(Map.Entry<String, Object> entry, StandardPBEStringEncryptor encryptor) {
log.info("Decrypt \"{}\" configuration property", entry.getKey());
String encrypted = entry.getValue().toString().substring(PREFIX.length(), entry.getValue().toString().length() - 1);
return encryptor.decrypt(encrypted);
}
@Override
public Environment onInitialized(BeanInitializingEvent<Environment> event) {
return event.getBean();
}
}