diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 2a6d6a336fef8..1d6be884915ea 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -55,7 +55,7 @@ 2.0 3.1 2.1.0 - 3.1.3 + 3.2.0 4.0.1 4.0.0 3.3.0 @@ -3809,6 +3809,11 @@ smallrye-config-common ${smallrye-config.version} + + io.smallrye.config + smallrye-config-core + ${smallrye-config.version} + io.smallrye.config smallrye-config-validator @@ -3826,7 +3831,12 @@ io.smallrye.config - smallrye-config-core + smallrye-config-source-keystore + ${smallrye-config.version} + + + io.smallrye.config + smallrye-config-crypto ${smallrye-config.version} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java index dba8f2b5eeb88..c5380c77d5664 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java @@ -13,7 +13,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.jboss.logging.Logger; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; @@ -38,6 +37,7 @@ import io.quarkus.paths.PathCollection; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.util.JavaVersionUtil; +import io.smallrye.config.SmallRyeConfigProviderResolver; public class QuarkusAugmentor { @@ -177,8 +177,8 @@ public BuildResult run() throws Exception { return buildResult; } finally { try { - ConfigProviderResolver.instance() - .releaseConfig(ConfigProviderResolver.instance().getConfig(deploymentClassLoader)); + ((SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver.instance()) + .releaseConfig(deploymentClassLoader); } catch (Exception ignore) { } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigBuildSteps.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigBuildSteps.java index 51eab2942912f..a3bdf3071a2c9 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigBuildSteps.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigBuildSteps.java @@ -34,6 +34,8 @@ import io.smallrye.config.ConfigSourceInterceptor; import io.smallrye.config.ConfigSourceInterceptorFactory; import io.smallrye.config.ConfigValidator; +import io.smallrye.config.SecretKeysHandler; +import io.smallrye.config.SecretKeysHandlerFactory; import io.smallrye.config.SmallRyeConfigProviderResolver; class ConfigBuildSteps { @@ -90,6 +92,8 @@ void nativeServiceProviders( Converter.class, ConfigSourceInterceptor.class, ConfigSourceInterceptorFactory.class, + SecretKeysHandler.class, + SecretKeysHandlerFactory.class, ConfigValidator.class)) { final String serviceName = serviceClass.getName(); final Set names = ServiceUtil.classNamesNamedIn(classLoader, SERVICES_PREFIX + serviceName); diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java index 5c04a6a4f4199..e9fe18f97ed53 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java @@ -90,14 +90,8 @@ public static SmallRyeConfigBuilder configBuilder(final boolean runTime, final b final boolean addDiscovered, final LaunchMode launchMode) { SmallRyeConfigBuilder builder = emptyConfigBuilder(); - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - builder.forClassLoader(classLoader); - builder.addDefaultSources(); - builder.withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem()); - builder.withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath()); - builder.withSources(new DotEnvConfigSourceProvider()); if (launchMode.isDevOrTest() && (runTime || bootstrap)) { - builder.withSources(new RuntimeOverrideConfigSource(classLoader)); + builder.withSources(new RuntimeOverrideConfigSource(Thread.currentThread().getContextClassLoader())); } if (runTime || bootstrap) { // Validator only for runtime. We cannot use the current validator for build time (chicken / egg problem) @@ -184,9 +178,16 @@ public OptionalInt getPriority() { // Ignore unmapped quarkus properties, because properties in the same root may be split between build / runtime builder.withMappingIgnore("quarkus.**"); - builder.addDefaultInterceptors(); - builder.addDiscoveredInterceptors(); - builder.addDiscoveredConverters(); + builder.forClassLoader(Thread.currentThread().getContextClassLoader()) + .addDiscoveredConverters() + .addDefaultInterceptors() + .addDiscoveredInterceptors() + .addDiscoveredSecretKeysHandlers() + .addDefaultSources() + .withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem()) + .withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath()) + .withSources(new DotEnvConfigSourceProvider()); + return builder; } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java index eafd80022e91b..9f168ae907e6f 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java @@ -26,7 +26,7 @@ public SmallRyeConfig getConfigFor(final SmallRyeConfigProviderResolver configPr //TODO: this code path is only hit when start fails in dev mode very early in the process //the recovery code will fail without this as it cannot read any properties such as //the HTTP port or logging info - return ConfigUtils.emptyConfigBuilder().addDefaultSources().addDiscoveredSources().build(); + return ConfigUtils.emptyConfigBuilder().addDiscoveredSources().build(); } return config; } diff --git a/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigExpanderTestCase.java b/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigExpanderTestCase.java index 3c62be1e69f18..897d54d1c4cf3 100644 --- a/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigExpanderTestCase.java +++ b/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigExpanderTestCase.java @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import io.smallrye.config.ExpressionConfigSourceInterceptor; import io.smallrye.config.PropertiesConfigSource; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; @@ -20,11 +19,10 @@ public class ConfigExpanderTestCase { private SmallRyeConfig buildConfig(Map configMap) { - final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); - builder.withInterceptors(new ExpressionConfigSourceInterceptor()); - builder.withSources(new PropertiesConfigSource(configMap, "test input", 500)); - final SmallRyeConfig config = (SmallRyeConfig) builder.build(); - return config; + return new SmallRyeConfigBuilder() + .addDefaultInterceptors() + .withSources(new PropertiesConfigSource(configMap, "test input", 500)) + .build(); } private Map maps(Map... maps) { diff --git a/docs/src/main/asciidoc/config-reference.adoc b/docs/src/main/asciidoc/config-reference.adoc index 5d5d84deeabc7..c96912d08e7c5 100644 --- a/docs/src/main/asciidoc/config-reference.adoc +++ b/docs/src/main/asciidoc/config-reference.adoc @@ -394,10 +394,58 @@ Then [WARNING] ==== -The configuration `quarkus.config.profile.parent` must be placed in the main `application.properties` file, passed as a system property, or passed as an environment variable. -It does not work when the configuration is placed in the profile aware files. +Do not use Profile aware files to set `quarkus.config.profile.parent`. This will not work because the profile is +required in advance to load the profile aware files. ==== +=== Multiple Profiles + +Multiple Profiles may be active at the same time. The configuration `quarkus.profile` accepts a comma-separated list +of profile names: `quarkus.profile=common,dev`. Both `common` and `dev` are separate profiles. + +When multiple profiles are active, the rules for profile configuration are the same. If two profiles define the same +configuration, then the last listed profile has priority. Consider: + +.application.properties +[source,properties] +---- +quarkus.profile=common,dev + +my.prop=1234 +%common.my.prop=1234 +%dev.my.prop=5678 + +%common.commom.prop=common +%dev.dev.prop=dev +%test.test.prop=test +---- + +Then + +* `common.prop` value is `common` +* `dev.prop` value is `dev` +* `my.prop` value is `5678` +* `test.prop` does not have a `value` + +It is also possible to define multiple profile properties, with a comma-separated list of profile names. If the same +property name exists in multiple profile properties then, the property name with the most specific profile wins: + +.application.properties +[source,properties] +---- +quarkus.profile=dev + +%prod,dev.my.prop=1234 +%dev.my.prop=5678 + +%prod,dev.another.prop=1234 +---- + +Then + +* `my.prop` value is 5678. +* `another.prop` value is 1234. + === Default Runtime Profile The default Quarkus runtime profile is set to the profile used to build the application: @@ -475,6 +523,23 @@ application.host=${HOST:${remote.host}} This will expand the `HOST` environment variable and use the value of the property `remote.host` as the default value if `HOST` is not set. +== Secret Keys Expressions + +A secret configuration may be expressed as `${handler::value}`, where the `handler` is the name of a +`io.smallrye.config.SecretKeysHandler` to decode or decrypt the `value`. Consider: + +.application.properties +[source,properties] +---- +my.secret=${aes-gcm-nopadding::DJNrZ6LfpupFv6QbXyXhvzD8eVDnDa_kTliQBpuzTobDZxlg} +---- + +A lookup to `my.secret` will use the `SecretKeysHandler` name `aes-gcm-nopadding` to decode the value +`DJNrZ6LfpupFv6QbXyXhvzD8eVDnDa_kTliQBpuzTobDZxlg`. + +For more information, please check SmallRye Config +link:https://smallrye.io/smallrye-config/Main/config/secret-keys/[Secret Keys] documentation. + == Accessing a generating UUID The default config source from Quarkus provides a random UUID value. @@ -568,7 +633,9 @@ If you are in the rare situation that you need to change the build time configur == Additional Information * xref:config-yaml.adoc[YAML ConfigSource Extension] +// Moved to Quarkiverse. There is a redirect to resolve the link * xref:vault.adoc[HashiCorp Vault ConfigSource Extension] +// Moved to Quarkiverse. There is a redirect to resolve the link * xref:consul-config.adoc[Consul ConfigSource Extension] * xref:spring-cloud-config-client.adoc[Spring Cloud ConfigSource Extension] * xref:config-mappings.adoc[Mapping configuration to objects] @@ -576,15 +643,13 @@ If you are in the rare situation that you need to change the build time configur Quarkus relies on link:https://github.com/smallrye/smallrye-config/[SmallRye Config] and inherits its features: -* Additional ``ConfigSource``s -* Additional ``Converter``s -* Indexed properties -* Parent profile -* Interceptors for configuration value resolution -* Relocate configuration properties -* Fallback configuration properties -* Logging -* Hide secrets +* link:https://smallrye.io/smallrye-config/Main/config-sources/custom/[Additional Config Sources] +* link:https://smallrye.io/smallrye-config/Main/config-sources/factories/[Config Source Factories] +* link:https://smallrye.io/smallrye-config/Main/converters/custom/[Additional Converters] +* link:https://smallrye.io/smallrye-config/Main/extensions/interceptors/[Interceptors] +* link:https://smallrye.io/smallrye-config/Main/extensions/relocate/[Relocate Configuration] +* link:https://smallrye.io/smallrye-config/Main/extensions/fallback/[Fallback Configuration] +* link:https://smallrye.io/smallrye-config/Main/config/secret-keys/[Secret Keys] For more information, please check the link:https://smallrye.io/smallrye-config/Main[SmallRye Config documentation]. diff --git a/independent-projects/tools/pom.xml b/independent-projects/tools/pom.xml index 654f479575d61..3e2b4e38bdc4c 100644 --- a/independent-projects/tools/pom.xml +++ b/independent-projects/tools/pom.xml @@ -66,7 +66,7 @@ 999-SNAPSHOT 21 2.11.0 - 1.13.2 + 2.1.0 3.0.5 diff --git a/integration-tests/smallrye-config/.env b/integration-tests/smallrye-config/.env index 5d20f3e113b6f..decac569ed32d 100644 --- a/integration-tests/smallrye-config/.env +++ b/integration-tests/smallrye-config/.env @@ -1,6 +1,6 @@ DOTENV_SERVER_NAME=localhost DOTENV_SERVER_PORT=8080 -_TEST_QUARKUS_DATASOURCE_DB_KIND=h2 -_TEST_QUARKUS_DATASOURCE_JDBC_URL=jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1 -_TEST_QUARKUS_HIBERNATE_ORM_DATABASE_GENERATION=drop-and-create +QUARKUS_DATASOURCE_DB_KIND=h2 +QUARKUS_DATASOURCE_JDBC_URL=jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1 +QUARKUS_HIBERNATE_ORM_DATABASE_GENERATION=drop-and-create diff --git a/integration-tests/smallrye-config/keystore b/integration-tests/smallrye-config/keystore new file mode 100644 index 0000000000000..74db4bb9a9dc9 Binary files /dev/null and b/integration-tests/smallrye-config/keystore differ diff --git a/integration-tests/smallrye-config/pom.xml b/integration-tests/smallrye-config/pom.xml index ece98c2440a4c..190438f577f7f 100644 --- a/integration-tests/smallrye-config/pom.xml +++ b/integration-tests/smallrye-config/pom.xml @@ -19,9 +19,14 @@ io.quarkus quarkus-hibernate-validator + io.quarkus - quarkus-config-yaml + quarkus-hibernate-orm + + + io.quarkus + quarkus-jdbc-h2 io.quarkus @@ -37,10 +42,23 @@ io.quarkus quarkus-smallrye-opentracing + + + io.quarkus + quarkus-config-yaml + io.smallrye.config smallrye-config-source-file-system + + io.smallrye.config + smallrye-config-source-keystore + + + io.smallrye.config + smallrye-config-crypto + io.quarkus @@ -62,23 +80,6 @@ rest-assured test - - - io.quarkus - quarkus-hibernate-orm - test - - - net.bytebuddy - byte-buddy - - - - - io.quarkus - quarkus-jdbc-h2 - test - @@ -96,7 +97,7 @@ io.quarkus - quarkus-config-yaml-deployment + quarkus-hibernate-orm-deployment ${project.version} pom test @@ -109,7 +110,7 @@ io.quarkus - quarkus-resteasy-reactive-deployment + quarkus-jdbc-h2-deployment ${project.version} pom test @@ -122,7 +123,7 @@ io.quarkus - quarkus-resteasy-reactive-jackson-deployment + quarkus-resteasy-reactive-deployment ${project.version} pom test @@ -135,7 +136,7 @@ io.quarkus - quarkus-smallrye-opentracing-deployment + quarkus-resteasy-reactive-jackson-deployment ${project.version} pom test @@ -148,7 +149,7 @@ io.quarkus - quarkus-hibernate-orm-deployment + quarkus-smallrye-opentracing-deployment ${project.version} pom test @@ -161,7 +162,7 @@ io.quarkus - quarkus-jdbc-h2-deployment + quarkus-config-yaml-deployment ${project.version} pom test @@ -172,7 +173,6 @@ - diff --git a/integration-tests/smallrye-config/src/main/resources/application.properties b/integration-tests/smallrye-config/src/main/resources/application.properties index d44dc7bbd9af3..960766adbc554 100644 --- a/integration-tests/smallrye-config/src/main/resources/application.properties +++ b/integration-tests/smallrye-config/src/main/resources/application.properties @@ -22,3 +22,9 @@ smallrye.config.source.file.locations=src/main/smallrye-config-source-file-syste no.profile=any profile.main.properties=main + +#secrets +smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key=somearbitrarycrazystringthatdoesnotmatter +smallrye.config.source.keystore.test.path=keystore +smallrye.config.source.keystore.test.password=secret +smallrye.config.source.keystore.test.handler=aes-gcm-nopadding diff --git a/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsIT.java b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsIT.java new file mode 100644 index 0000000000000..4ee4c0fc3b5f3 --- /dev/null +++ b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsIT.java @@ -0,0 +1,7 @@ +package io.quarkus.it.smallrye.config; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +public class SecretsIT extends SecretsTest { +} diff --git a/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsTest.java b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsTest.java new file mode 100644 index 0000000000000..3128db8329916 --- /dev/null +++ b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/SecretsTest.java @@ -0,0 +1,21 @@ +package io.quarkus.it.smallrye.config; + +import static io.restassured.RestAssured.given; +import static jakarta.ws.rs.core.Response.Status.OK; +import static org.hamcrest.Matchers.equalTo; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class SecretsTest { + @Test + void secrets() { + given() + .get("/config/{name}", "my.secret") + .then() + .statusCode(OK.getStatusCode()) + .body("value", equalTo("decoded")); + } +} diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/UnknownBuildConfigTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/UnknownBuildConfigTest.java index 2bb9c6a755c60..4b9ad31019f5f 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/UnknownBuildConfigTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/UnknownBuildConfigTest.java @@ -39,7 +39,7 @@ void unknownBuildConfig() { .orElse(new Object[0])) .collect(toSet()); - assertEquals(7, logRecords.size()); + assertEquals(7, unrecognized.size()); assertTrue(unrecognized.contains("quarkus.unknown.prop")); assertTrue(unrecognized.contains("quarkus.build.unknown.prop")); assertTrue(unrecognized.contains("quarkus.rename-old.prop"));