From 5ee74f52b0c16dfb9c347d59c8ea2f64cc874ecf Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Fri, 14 Jun 2024 14:49:43 +0100 Subject: [PATCH] Use LazySecretKeysHandler for Jasypt Config --- .../jasypt/deployment/JasyptProcessor.java | 2 +- .../devui/JasyptUtilsDevUIProcessor.java | 2 +- .../jasypt/JasyptPasswordNotProvidedTest.java | 21 ++- .../JasyptPasswordSysEnvValueMissingTest.java | 21 ++- .../JasyptPasswordSysValueMissingTest.java | 21 ++- .../jasypt/CamelJasyptBuildTimeConfig.java | 16 +- .../component/jasypt/CamelJasyptConfig.java | 100 ++++++++--- .../jasypt/CamelJasyptDevUIService.java | 19 +-- .../CamelJasyptPropertiesParserHolder.java | 4 - .../CamelJasyptSecretKeysHandlerFactory.java | 160 +++--------------- 10 files changed, 187 insertions(+), 179 deletions(-) diff --git a/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/JasyptProcessor.java b/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/JasyptProcessor.java index bd87b43d0009..4e22772179cb 100644 --- a/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/JasyptProcessor.java +++ b/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/JasyptProcessor.java @@ -81,7 +81,7 @@ static final class CamelJasyptEnabled implements BooleanSupplier { @Override public boolean getAsBoolean() { - return config.enabled; + return config.enabled(); } } } diff --git a/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/devui/JasyptUtilsDevUIProcessor.java b/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/devui/JasyptUtilsDevUIProcessor.java index fd39facf2877..96abf86c05e8 100644 --- a/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/devui/JasyptUtilsDevUIProcessor.java +++ b/extensions/jasypt/deployment/src/main/java/org/apache/camel/quarkus/component/jasypt/deployment/devui/JasyptUtilsDevUIProcessor.java @@ -49,7 +49,7 @@ static final class CamelJasyptEnabled implements BooleanSupplier { @Override public boolean getAsBoolean() { - return config.enabled; + return config.enabled(); } } } diff --git a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordNotProvidedTest.java b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordNotProvidedTest.java index e7af5c50a64a..1cf46bb3b8ba 100644 --- a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordNotProvidedTest.java +++ b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordNotProvidedTest.java @@ -17,6 +17,9 @@ package org.apache.camel.quarkus.component.jasypt; import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jasypt.JasyptPropertiesParser; +import org.apache.camel.component.properties.PropertiesComponent; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.jupiter.api.Test; @@ -25,11 +28,27 @@ public class JasyptPasswordNotProvidedTest { @RegisterExtension static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .overrideConfigKey("greeting.secret", "ENC(GKJfy64eBDzxUuQCfArd6OjnAaW/oM9e)") .setExpectedException(IllegalStateException.class) - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)); + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClass(JasyptRoutes.class)); @Test void passwordNotProvidedThrowsException() { // Nothing to test as we just verify the application fails to start } + + public static final class JasyptRoutes extends RouteBuilder { + @Override + public void configure() { + JasyptPropertiesParser jasypt = new JasyptPropertiesParser(); + jasypt.setPassword("2s3cr3t"); + + PropertiesComponent component = (PropertiesComponent) getContext().getPropertiesComponent(); + jasypt.setPropertiesComponent(component); + component.setPropertiesParser(jasypt); + + from("direct:decryptManualConfiguration") + .setBody().simple("{{greeting.secret}}"); + } + } } diff --git a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysEnvValueMissingTest.java b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysEnvValueMissingTest.java index 10299440b185..9bf7fbe1de21 100644 --- a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysEnvValueMissingTest.java +++ b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysEnvValueMissingTest.java @@ -17,6 +17,9 @@ package org.apache.camel.quarkus.component.jasypt; import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jasypt.JasyptPropertiesParser; +import org.apache.camel.component.properties.PropertiesComponent; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.jupiter.api.Test; @@ -27,12 +30,28 @@ public class JasyptPasswordSysEnvValueMissingTest { @RegisterExtension static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .overrideConfigKey("greeting.secret", "ENC(GKJfy64eBDzxUuQCfArd6OjnAaW/oM9e)") .overrideConfigKey("quarkus.camel.jasypt.password", "sysenv:" + PASSWORD_VAR_NAME) .setExpectedException(IllegalStateException.class) - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)); + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClass(JasyptRoutes.class)); @Test void nonExistentPasswordEnvironmentVariableHandledGracefully() { // Nothing to test as we just verify the application fails to start } + + public static final class JasyptRoutes extends RouteBuilder { + @Override + public void configure() { + JasyptPropertiesParser jasypt = new JasyptPropertiesParser(); + jasypt.setPassword("2s3cr3t"); + + PropertiesComponent component = (PropertiesComponent) getContext().getPropertiesComponent(); + jasypt.setPropertiesComponent(component); + component.setPropertiesParser(jasypt); + + from("direct:decryptManualConfiguration") + .setBody().simple("{{greeting.secret}}"); + } + } } diff --git a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysValueMissingTest.java b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysValueMissingTest.java index b78a6486c5d2..d4f783eba9b7 100644 --- a/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysValueMissingTest.java +++ b/extensions/jasypt/deployment/src/test/java/org/apache/camel/quarkus/component/jasypt/JasyptPasswordSysValueMissingTest.java @@ -17,6 +17,9 @@ package org.apache.camel.quarkus.component.jasypt; import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jasypt.JasyptPropertiesParser; +import org.apache.camel.component.properties.PropertiesComponent; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.jupiter.api.Test; @@ -27,12 +30,28 @@ public class JasyptPasswordSysValueMissingTest { @RegisterExtension static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .overrideConfigKey("greeting.secret", "ENC(GKJfy64eBDzxUuQCfArd6OjnAaW/oM9e)") .overrideConfigKey("quarkus.camel.jasypt.password", "sys:" + PASSWORD_PROPERTY_NAME) .setExpectedException(IllegalStateException.class) - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)); + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClass(JasyptRoutes.class)); @Test void nonExistentPasswordSystemPropertyHandledGracefully() { // Nothing to test as we just verify the application fails to start } + + public static final class JasyptRoutes extends RouteBuilder { + @Override + public void configure() { + JasyptPropertiesParser jasypt = new JasyptPropertiesParser(); + jasypt.setPassword("2s3cr3t"); + + PropertiesComponent component = (PropertiesComponent) getContext().getPropertiesComponent(); + jasypt.setPropertiesComponent(component); + component.setPropertiesParser(jasypt); + + from("direct:decryptManualConfiguration") + .setBody().simple("{{greeting.secret}}"); + } + } } diff --git a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptBuildTimeConfig.java b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptBuildTimeConfig.java index 074d90955e9f..f0325ee5d4ad 100644 --- a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptBuildTimeConfig.java +++ b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptBuildTimeConfig.java @@ -16,21 +16,19 @@ */ package org.apache.camel.quarkus.component.jasypt; -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; -/** - * Note: This class exists mainly for documentation purposes. The actual configuration values - * are read via the SmallRye config internals within the SecretKeysHandler. - */ -@ConfigRoot(name = "camel.jasypt", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) -public class CamelJasyptBuildTimeConfig { +@ConfigMapping(prefix = "quarkus.camel.jasypt") +@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) +public interface CamelJasyptBuildTimeConfig { /** * Setting this option to false will disable Jasypt integration with Quarkus SmallRye configuration. * You can however, manually configure Jasypt with Camel in the 'classic' way of manually configuring * JasyptPropertiesParser and PropertiesComponent. Refer to the usage section for more details. */ - @ConfigItem(defaultValue = "true") - public boolean enabled; + @WithDefault("true") + boolean enabled(); } diff --git a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptConfig.java b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptConfig.java index 420689a1c230..20a9085ace83 100644 --- a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptConfig.java +++ b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptConfig.java @@ -16,29 +16,34 @@ */ package org.apache.camel.quarkus.component.jasypt; +import java.lang.reflect.InvocationTargetException; import java.util.Optional; +import java.util.Set; -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; +import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; +import org.jasypt.encryption.pbe.config.PBEConfig; +import org.jasypt.iv.NoIvGenerator; import org.jasypt.iv.RandomIvGenerator; import org.jasypt.salt.RandomSaltGenerator; -/** - * Note: This class exists mainly for documentation purposes. The actual configuration values - * are read via the SmallRye config internals within the SecretKeysHandler. - */ -@ConfigRoot(name = "camel.jasypt", phase = ConfigPhase.RUN_TIME) -public class CamelJasyptConfig { - static final String NAME = "camel-jasypt"; - static final String DEFAULT_ALGORITHM = StandardPBEByteEncryptor.DEFAULT_ALGORITHM; +@ConfigMapping(prefix = "quarkus.camel.jasypt") +@ConfigRoot(phase = ConfigPhase.RUN_TIME) +public interface CamelJasyptConfig { + String NAME = "camel-jasypt"; + String DEFAULT_ALGORITHM = StandardPBEByteEncryptor.DEFAULT_ALGORITHM; /** * The algorithm to be used for decryption. */ - @ConfigItem(defaultValue = DEFAULT_ALGORITHM) - public String algorithm; + @WithDefault(DEFAULT_ALGORITHM) + String algorithm(); /** * The master password used by Jasypt for decrypting configuration values. @@ -48,25 +53,82 @@ public class CamelJasyptConfig { * sysenv: will look up the value from the OS system environment with the given key. *

*/ - @ConfigItem - public Optional password; + Optional password(); /** * Configures the Jasypt StandardPBEStringEncryptor with a RandomIvGenerator using the given algorithm. */ - @ConfigItem(defaultValue = RandomIvGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM) - public String randomIvGeneratorAlgorithm; + @WithDefault(RandomIvGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM) + String randomIvGeneratorAlgorithm(); /** * Configures the Jasypt StandardPBEStringEncryptor with a RandomSaltGenerator using the given algorithm. */ - @ConfigItem(defaultValue = RandomSaltGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM) - public String randomSaltGeneratorAlgorithm; + @WithDefault(RandomSaltGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM) + String randomSaltGeneratorAlgorithm(); /** * The fully qualified class name of an org.apache.camel.quarkus.component.jasypt.JasyptConfigurationCustomizer * implementation. This provides the optional capability of having full control over the Jasypt configuration. */ - @ConfigItem - public Optional configurationCustomizerClassName; + Optional configurationCustomizerClassName(); + + String SYS_CONFIG_PREFIX = "sys:"; + String SYS_ENV_CONFIG_PREFIX = "sysenv:"; + Set ALGORITHMS_THAT_REQUIRE_IV = Set.of( + "PBEWITHHMACSHA1ANDAES_128", + "PBEWITHHMACSHA1ANDAES_256", + "PBEWITHHMACSHA224ANDAES_128", + "PBEWITHHMACSHA224ANDAES_256", + "PBEWITHHMACSHA256ANDAES_128", + "PBEWITHHMACSHA256ANDAES_256", + "PBEWITHHMACSHA384ANDAES_128", + "PBEWITHHMACSHA384ANDAES_256", + "PBEWITHHMACSHA512ANDAES_128", + "PBEWITHHMACSHA512ANDAES_256"); + + default PBEConfig pbeConfig() { + EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); + + String password = null; + if (password().isPresent()) { + password = password().get(); + if (ObjectHelper.isNotEmpty(password)) { + // Preserve backwards compat with the Camel way of configuring the master password + if (password.startsWith(SYS_ENV_CONFIG_PREFIX)) { + password = System.getenv(StringHelper.after(password, SYS_ENV_CONFIG_PREFIX)); + } else if (password.startsWith(SYS_CONFIG_PREFIX)) { + password = System.getProperty(StringHelper.after(password, SYS_CONFIG_PREFIX)); + } + } + } + + config.setPassword(password); + config.setAlgorithm(algorithm()); + config.setIvGenerator(ALGORITHMS_THAT_REQUIRE_IV.contains(algorithm().toUpperCase()) + ? new RandomIvGenerator(randomIvGeneratorAlgorithm()) : new NoIvGenerator()); + config.setSaltGenerator(new RandomSaltGenerator(randomSaltGeneratorAlgorithm())); + + if (configurationCustomizerClassName().isPresent()) { + try { + Class encryptorClass = Thread.currentThread().getContextClassLoader() + .loadClass(configurationCustomizerClassName().get()); + JasyptConfigurationCustomizer customizer = (JasyptConfigurationCustomizer) encryptorClass + .getDeclaredConstructor().newInstance(); + customizer.customize(config); + } catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException + | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + // Avoid potentially confusing runtime NPEs and fail fast if no password has been configured + try { + config.getPassword(); + } catch (NullPointerException e) { + throw new IllegalStateException("The jasypt password has not been configured."); + } + + return config; + } } diff --git a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptDevUIService.java b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptDevUIService.java index f8508423d38f..a41ec68e8ebe 100644 --- a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptDevUIService.java +++ b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptDevUIService.java @@ -21,19 +21,18 @@ @ApplicationScoped public class CamelJasyptDevUIService { + private final StandardPBEStringEncryptor encryptor; + + public CamelJasyptDevUIService(CamelJasyptConfig jasyptConfig) { + encryptor = new StandardPBEStringEncryptor(); + encryptor.setConfig(jasyptConfig.pbeConfig()); + } + public String encryptText(String text) { - StandardPBEStringEncryptor encryptor = CamelJasyptPropertiesParserHolder.getEncryptor(); - if (encryptor != null) { - return encryptor.encrypt(text); - } - return null; + return encryptor.encrypt(text); } public String decryptText(String text) { - StandardPBEStringEncryptor encryptor = CamelJasyptPropertiesParserHolder.getEncryptor(); - if (encryptor != null) { - return encryptor.decrypt(text); - } - return null; + return encryptor.decrypt(text); } } diff --git a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptPropertiesParserHolder.java b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptPropertiesParserHolder.java index c9fbaf8374ad..5f33e377335d 100644 --- a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptPropertiesParserHolder.java +++ b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptPropertiesParserHolder.java @@ -44,8 +44,4 @@ static void setEncryptor(StandardPBEStringEncryptor encryptor) { ENCRYPTOR = encryptor; } } - - static StandardPBEStringEncryptor getEncryptor() { - return ENCRYPTOR; - } } diff --git a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptSecretKeysHandlerFactory.java b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptSecretKeysHandlerFactory.java index 163baecfcebd..393014bbfd83 100644 --- a/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptSecretKeysHandlerFactory.java +++ b/extensions/jasypt/runtime/src/main/java/org/apache/camel/quarkus/component/jasypt/CamelJasyptSecretKeysHandlerFactory.java @@ -16,159 +16,55 @@ */ package org.apache.camel.quarkus.component.jasypt; -import java.lang.reflect.InvocationTargetException; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Set; - import io.smallrye.config.ConfigSourceContext; -import io.smallrye.config.ConfigValue; import io.smallrye.config.SecretKeysHandler; import io.smallrye.config.SecretKeysHandlerFactory; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; import org.apache.camel.component.jasypt.JasyptPropertiesParser; -import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.StringHelper; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; -import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; -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 static org.apache.camel.quarkus.component.jasypt.CamelJasyptConfig.DEFAULT_ALGORITHM; public class CamelJasyptSecretKeysHandlerFactory implements SecretKeysHandlerFactory { - private static final String CONFIG_PREFIX = "quarkus.camel.jasypt."; - private static final String SYS_CONFIG_PREFIX = "sys:"; - private static final String SYS_ENV_CONFIG_PREFIX = "sysenv:"; - private static final Set ALGORITHMS_THAT_REQUIRE_IV = Set.of( - "PBEWITHHMACSHA1ANDAES_128", - "PBEWITHHMACSHA1ANDAES_256", - "PBEWITHHMACSHA224ANDAES_128", - "PBEWITHHMACSHA224ANDAES_256", - "PBEWITHHMACSHA256ANDAES_128", - "PBEWITHHMACSHA256ANDAES_256", - "PBEWITHHMACSHA384ANDAES_128", - "PBEWITHHMACSHA384ANDAES_256", - "PBEWITHHMACSHA512ANDAES_128", - "PBEWITHHMACSHA512ANDAES_256"); private final JasyptPropertiesParser parser = CamelJasyptPropertiesParserHolder.getJasyptPropertiesParser(); - private boolean enabled = true; @Override public SecretKeysHandler getSecretKeysHandler(ConfigSourceContext context) { - configureJasypt(context); - - return new SecretKeysHandler() { + return new LazySecretKeysHandler(new SecretKeysHandlerFactory() { @Override - public String decode(String secret) { - return parser.parseProperty("", secret, null); + public SecretKeysHandler getSecretKeysHandler(final ConfigSourceContext context) { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withSources(new ConfigSourceContext.ConfigSourceContextConfigSource(context)) + .withMapping(CamelJasyptConfig.class) + .withMapping(CamelJasyptBuildTimeConfig.class) + .build(); + + CamelJasyptConfig jasyptConfig = config.getConfigMapping(CamelJasyptConfig.class); + StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); + encryptor.setConfig(jasyptConfig.pbeConfig()); + CamelJasyptPropertiesParserHolder.setEncryptor(encryptor); + + return new SecretKeysHandler() { + @Override + public String decode(String secret) { + return parser.parseProperty("", secret, null); + } + + @Override + public String getName() { + return CamelJasyptSecretKeysHandlerFactory.this.getName(); + } + }; } @Override public String getName() { - return CamelJasyptConfig.NAME; + return CamelJasyptSecretKeysHandlerFactory.this.getName(); } - }; + }); } @Override public String getName() { return CamelJasyptConfig.NAME; } - - private void configureJasypt(ConfigSourceContext context) { - EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); - - String algorithm = getAlgorithm(context); - config.setPassword(getPassword(context)); - config.setAlgorithm(algorithm); - config.setIvGenerator(getIvGenerator(algorithm, context)); - config.setSaltGenerator(getSaltGenerator(context)); - customizeConfiguration(config, context); - - StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); - encryptor.setConfig(config); - - // Avoid potentially confusing runtime NPEs and fail fast if no password has been configured - try { - config.getPassword(); - } catch (NullPointerException e) { - throw new IllegalStateException("The jasypt password has not been configured."); - } - - CamelJasyptPropertiesParserHolder.setEncryptor(encryptor); - } - - private String getPassword(ConfigSourceContext context) { - Optional passwordOptional = getOptionalConfigValue(context, "password"); - if (passwordOptional.isPresent()) { - String password = passwordOptional.get(); - if (ObjectHelper.isNotEmpty(password)) { - // Preserve backwards compat with the Camel way of configuring the master password - if (password.startsWith(SYS_ENV_CONFIG_PREFIX)) { - password = System.getenv(StringHelper.after(password, SYS_ENV_CONFIG_PREFIX)); - } else if (password.startsWith(SYS_CONFIG_PREFIX)) { - password = System.getProperty(StringHelper.after(password, SYS_CONFIG_PREFIX)); - } - } - return password; - } - return null; - } - - private String getAlgorithm(ConfigSourceContext context) { - return getConfigValue(context, "algorithm", DEFAULT_ALGORITHM); - } - - private IvGenerator getIvGenerator(String algorithm, ConfigSourceContext context) { - if (ObjectHelper.isNotEmpty(algorithm) && ALGORITHMS_THAT_REQUIRE_IV.contains(algorithm.toUpperCase())) { - String ivGeneratorAlgorithm = getConfigValue(context, "random-iv-generator-algorithm", - RandomSaltGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM); - return new RandomIvGenerator(ivGeneratorAlgorithm); - } - return new NoIvGenerator(); - } - - private SaltGenerator getSaltGenerator(ConfigSourceContext context) { - String algorithm = getConfigValue(context, "random-salt-generator-algorithm", - RandomSaltGenerator.DEFAULT_SECURE_RANDOM_ALGORITHM); - return new RandomSaltGenerator(algorithm); - } - - private void customizeConfiguration(EnvironmentStringPBEConfig config, ConfigSourceContext context) { - Optional customizerClassName = getOptionalConfigValue(context, "configuration-customizer-class-name"); - if (customizerClassName.isPresent()) { - try { - Class encryptorClass = Thread.currentThread().getContextClassLoader().loadClass(customizerClassName.get()); - JasyptConfigurationCustomizer customizer = (JasyptConfigurationCustomizer) encryptorClass - .getDeclaredConstructor().newInstance(); - customizer.customize(config); - } catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException - | NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - } - - private String getConfigValue(ConfigSourceContext context, String key, String defaultValue) { - String configKey = CONFIG_PREFIX + key; - ConfigValue value = context.getValue(configKey); - if (value != null) { - return value.getValue(); - } - if (defaultValue != null) { - return defaultValue; - } - throw new NoSuchElementException("Property value for %s was not found".formatted(configKey)); - } - - private Optional getOptionalConfigValue(ConfigSourceContext context, String key) { - ConfigValue value = context.getValue(CONFIG_PREFIX + key); - if (value != null) { - return Optional.of(value.getValue()); - } - return Optional.empty(); - } }