From a673656d38a09426be02f126e0762f3f16ea8733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Barto=C5=A1?= Date: Mon, 30 Jun 2025 12:40:11 +0200 Subject: [PATCH 1/2] Unable to configure TLS reloading in Keycloak version 26.2.0 or later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #40713 Signed-off-by: Martin Bartoš Co-authored-by: Steve Hawkins --- .../mappers/HttpPropertyMappers.java | 8 ++++++-- .../mappers/ManagementPropertyMappers.java | 3 +-- .../configuration/mappers/PropertyMapper.java | 3 ++- .../quarkus/runtime/cli/PicocliTest.java | 3 +++ .../test/AbstractConfigurationTest.java | 14 ++++++++++++++ .../configuration/test/ConfigurationTest.java | 18 +++++++++++++++--- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java index dc27987e4a2b..eeb6854e4a2f 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java @@ -93,8 +93,7 @@ public static PropertyMapper[] getHttpPropertyMappers() { .build(), fromOption(HttpOptions.HTTPS_CERTIFICATES_RELOAD_PERIOD) .to("quarkus.http.ssl.certificate.reload-period") - // -1 means no reload - .transformer((value, context) -> "-1".equals(value) ? null : value) + .transformer(HttpPropertyMappers::transformNegativeReloadPeriod) .paramLabel("reload period") .build(), fromOption(HttpOptions.HTTPS_CERTIFICATE_FILE) @@ -174,6 +173,11 @@ private static String getHttpEnabledTransformer(String value, ConfigSourceInterc return isHttpEnabled(value) ? "enabled" : "disabled"; } + static String transformNegativeReloadPeriod(String value, ConfigSourceInterceptorContext context) { + // -1 means no reload + return "-1".equals(value) ? null : value; + } + private static boolean isHttpEnabled(String value) { if (Environment.isDevMode() || Environment.isNonServerMode()) { return true; diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ManagementPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ManagementPropertyMappers.java index 7c170c665ae5..044e5b10781a 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ManagementPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ManagementPropertyMappers.java @@ -74,8 +74,7 @@ public static PropertyMapper[] getManagementPropertyMappers() { fromOption(ManagementOptions.HTTPS_MANAGEMENT_CERTIFICATES_RELOAD_PERIOD) .mapFrom(HttpOptions.HTTPS_CERTIFICATES_RELOAD_PERIOD) .to("quarkus.management.ssl.certificate.reload-period") - // -1 means no reload - .transformer((value, context) -> "-1".equals(value) ? null : value) + .transformer(HttpPropertyMappers::transformNegativeReloadPeriod) .paramLabel("reload period") .build(), fromOption(ManagementOptions.HTTPS_MANAGEMENT_CERTIFICATE_FILE) diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java index 86fd10a8bc74..74ffbb63738e 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java @@ -244,7 +244,8 @@ private ConfigValue transformValue(String name, ConfigValue configValue, ConfigS String mappedValue = value; boolean mapped = false; - var theMapper = parentValue ? this.parentMapper : this.mapper; + // use parent mapper/transformer when no mapper is explicitly specified in .mapFrom() + var theMapper = parentValue && parentMapper != null ? this.parentMapper : this.mapper; if (theMapper != null && (!name.equals(getFrom()) || parentValue)) { mappedValue = theMapper.apply(value, context); mapped = true; diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java index 161256442482..5e5f9798b356 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java @@ -124,10 +124,13 @@ public void testNegativeArgument() { assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode); assertEquals("1h", nonRunningPicocli.config.getConfigValue("quarkus.http.ssl.certificate.reload-period").getValue()); + assertEquals("1h", + nonRunningPicocli.config.getConfigValue("quarkus.management.ssl.certificate.reload-period").getValue()); nonRunningPicocli = pseudoLaunch("start-dev", "--https-certificates-reload-period=-1"); assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode); assertNull(nonRunningPicocli.config.getConfigValue("quarkus.http.ssl.certificate.reload-period").getValue()); + assertNull(nonRunningPicocli.config.getConfigValue("quarkus.management.ssl.certificate.reload-period").getValue()); } @Test diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/AbstractConfigurationTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/AbstractConfigurationTest.java index 076b58400c37..06b83532f742 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/AbstractConfigurationTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/AbstractConfigurationTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import java.lang.reflect.Field; @@ -172,6 +173,19 @@ protected void assertExternalConfig(Map expectedValues) { expectedValues.forEach(this::assertExternalConfig); } + protected void assertConfigNull(String key, boolean isExternal) { + Function getConfig = isExternal ? Configuration::getConfigValue : Configuration::getKcConfigValue; + assertThat(String.format("We expect that the value is null for key '%s'", key), getConfig.apply(key).getValue(), nullValue()); + } + + protected void assertConfigNull(String key) { + assertConfigNull(key, false); + } + + protected void assertExternalConfigNull(String key) { + assertConfigNull(key, true); + } + protected static void addPersistedConfigValues(Map values) { var configValueProps = PersistedConfigSource.getInstance().getConfigValueProperties(); values.forEach((k, v) -> configValueProps.put(k, diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java index a28b01d49238..d9e0bf61e250 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java @@ -497,11 +497,23 @@ public void testKeystoreConfigSourcePropertyMapping() { @Test public void testReloadPeriod() { ConfigArgsConfigSource.setCliArgs(""); - assertEquals("1h", createConfig().getConfigValue("quarkus.http.ssl.certificate.reload-period").getValue()); + initConfig(); + assertExternalConfig(Map.of( + "quarkus.http.ssl.certificate.reload-period", "1h", + "quarkus.management.ssl.certificate.reload-period", "1h" + )); + ConfigArgsConfigSource.setCliArgs("--https-certificates-reload-period=-1"); - assertNull(createConfig().getConfigValue("quarkus.http.ssl.certificate.reload-period").getValue()); + initConfig(); + assertExternalConfigNull("quarkus.http.ssl.certificate.reload-period"); + assertExternalConfigNull("quarkus.management.ssl.certificate.reload-period"); + ConfigArgsConfigSource.setCliArgs("--https-certificates-reload-period=2h"); - assertEquals("2h", createConfig().getConfigValue("quarkus.http.ssl.certificate.reload-period").getValue()); + initConfig(); + assertExternalConfig(Map.of( + "quarkus.http.ssl.certificate.reload-period", "2h", + "quarkus.management.ssl.certificate.reload-period", "2h" + )); } @Test From 8343c9130affca8d4ec93cfe84f35710e43e8a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Barto=C5=A1?= Date: Tue, 1 Jul 2025 13:43:40 +0200 Subject: [PATCH 2/2] Update quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Steven Hawkins Signed-off-by: Martin Bartoš --- .../quarkus/runtime/configuration/mappers/PropertyMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java index 74ffbb63738e..86d16b74fe01 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java @@ -244,7 +244,7 @@ private ConfigValue transformValue(String name, ConfigValue configValue, ConfigS String mappedValue = value; boolean mapped = false; - // use parent mapper/transformer when no mapper is explicitly specified in .mapFrom() + // fall back to the transformer when no mapper is explicitly specified in .mapFrom() var theMapper = parentValue && parentMapper != null ? this.parentMapper : this.mapper; if (theMapper != null && (!name.equals(getFrom()) || parentValue)) { mappedValue = theMapper.apply(value, context);