diff --git a/docs/guides/server/configuration.adoc b/docs/guides/server/configuration.adoc index dbb09dcaacb0..33b6a7629d56 100644 --- a/docs/guides/server/configuration.adoc +++ b/docs/guides/server/configuration.adoc @@ -124,7 +124,7 @@ After executing the command, you will be prompted to *Enter the password to be s When the KeyStore is created, you can start the server using the following parameters: -<@kc.start parameters="--config-keystore=/path/to/keystore.p12 --config-keystore-password=storepass --config-keystore-type=PKCS12"/> +<@kc.start parameters="--config-keystore=/path/to/keystore.p12 --config-keystore-password=keystorepass --config-keystore-type=PKCS12"/> === Format for raw Quarkus properties In most cases, the available configuration options should suffice to configure the server. diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java index c8b87dafe569..4e639cf9d4e9 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java @@ -34,7 +34,7 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.getRawPersistedProperty; import static org.keycloak.quarkus.runtime.configuration.Configuration.getRuntimeProperty; import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX; -import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.formatValue; +import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.maskValue; import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.isBuildTimeProperty; import static org.keycloak.utils.StringUtil.isNotBlank; import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST; @@ -222,7 +222,7 @@ public void accept(String key, String value) { return; } - properties.add(key + "=" + formatValue(key, value)); + properties.add(key + "=" + maskValue(key, value)); } }, arg -> { properties.add(arg); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ShowConfig.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ShowConfig.java index 088e35530a6f..6257f5ed3d14 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ShowConfig.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ShowConfig.java @@ -22,7 +22,7 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfigValue; import static org.keycloak.quarkus.runtime.configuration.Configuration.getPropertyNames; import static org.keycloak.quarkus.runtime.configuration.Configuration.getRuntimeProperty; -import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.formatValue; +import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.maskValue; import java.util.HashSet; import java.util.List; @@ -148,7 +148,9 @@ private void printProperty(String property) { value = getRuntimeProperty(property).orElse(value); } - spec.commandLine().getOut().printf("\t%s = %s (%s)%n", configValue.getName(), formatValue(configValue.getName(), value), KeycloakConfigSourceProvider.getConfigSourceDisplayName(configValue.getConfigSourceName())); + value = maskValue(configValue.getName(), value, configValue.getConfigSourceName()); + + spec.commandLine().getOut().printf("\t%s = %s (%s)%n", configValue.getName(), value, KeycloakConfigSourceProvider.getConfigSourceDisplayName(configValue.getConfigSourceName())); } private static String groupProperties(String property) { diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/KeycloakConfigSourceProvider.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/KeycloakConfigSourceProvider.java index 3a5a1c1e08d7..ba702dad3ef2 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/KeycloakConfigSourceProvider.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/KeycloakConfigSourceProvider.java @@ -100,9 +100,13 @@ public static String getConfigSourceDisplayName(String configSource) { if (configSource == null) { return "Derived"; } - if (configSource.startsWith("KeyStoreConfigSource")) { + if (isKeyStoreConfigSource(configSource)) { return "config-keystore"; } return CONFIG_SOURCE_DISPLAY_NAMES.getOrDefault(configSource, configSource); } + + public static boolean isKeyStoreConfigSource(String configSourceName) { + return configSourceName.contains("KeyStoreConfigSource"); + } } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigKeystorePropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigKeystorePropertyMappers.java index c4505054579b..804bf3cbaf10 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigKeystorePropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigKeystorePropertyMappers.java @@ -29,6 +29,7 @@ public static PropertyMapper[] getConfigKeystorePropertyMappers() { .to(SMALLRYE_KEYSTORE_PASSWORD) .transformer(ConfigKeystorePropertyMappers::validatePassword) .paramLabel("config-keystore-password") + .isMasked(true) .build(), fromOption(ConfigKeystoreOptions.CONFIG_KEYSTORE_TYPE) .to("smallrye.config.source.keystore.kc-default.type") diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMappers.java index 195666da70ca..38401210ce24 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMappers.java @@ -34,6 +34,7 @@ import static org.keycloak.quarkus.runtime.Environment.isParsedCommand; import static org.keycloak.quarkus.runtime.Environment.isRebuild; import static org.keycloak.quarkus.runtime.Environment.isRebuildCheck; +import static org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider.isKeyStoreConfigSource; public final class PropertyMappers { @@ -125,11 +126,15 @@ public static void sanitizeDisabledMappers() { MAPPERS.sanitizeDisabledMappers(); } - public static String formatValue(String property, String value) { + public static String maskValue(String property, String value) { + return maskValue(property, value, null); + } + + public static String maskValue(String property, String value, String configSourceName) { property = removeProfilePrefixIfNeeded(property); PropertyMapper mapper = getMapper(property); - if (mapper != null && mapper.isMask()) { + if ((configSourceName != null && isKeyStoreConfigSource(configSourceName) || (mapper != null && mapper.isMask()))) { return VALUE_MASK; } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/ShowConfigCommandTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/ShowConfigCommandTest.java index 55581227698b..5d126e65e31f 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/ShowConfigCommandTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/ShowConfigCommandTest.java @@ -17,17 +17,19 @@ package org.keycloak.it.cli; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.main.Launch; +import io.quarkus.test.junit.main.LaunchResult; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.keycloak.it.junit5.extension.CLITest; import org.keycloak.it.junit5.extension.ConfigurationTestResource; - -import io.quarkus.test.common.QuarkusTestResource; -import io.quarkus.test.junit.main.Launch; -import io.quarkus.test.junit.main.LaunchResult; import org.keycloak.quarkus.runtime.cli.command.ShowConfig; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.keycloak.quarkus.runtime.cli.command.Main.CONFIG_FILE_LONG_NAME; @QuarkusTestResource(value = ConfigurationTestResource.class, restrictToAnnotatedClass = true) @@ -59,4 +61,16 @@ void testShowConfigCommandHidesCredentialsInProfiles(LaunchResult result) { Assertions.assertFalse(output.contains("testpw3")); Assertions.assertTrue(output.contains("kc.db-password = " + PropertyMappers.VALUE_MASK)); } + + @Test + @Launch({ CONFIG_FILE_LONG_NAME+"=src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf", ShowConfig.NAME, "all" }) + void testSmallRyeKeyStoreConfigSource(LaunchResult result) { + // keystore is shared with QuarkusPropertiesDistTest#testSmallRyeKeyStoreConfigSource + String output = result.getOutput(); + assertThat(output, containsString("kc.config-keystore-password = " + PropertyMappers.VALUE_MASK)); + assertThat(output, containsString("kc.log-level = " + PropertyMappers.VALUE_MASK)); + + assertThat(output, not(containsString("secret"))); + assertThat(output, not(containsString("debug"))); + } } diff --git a/quarkus/tests/integration/src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf b/quarkus/tests/integration/src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf new file mode 100644 index 000000000000..6a9edddf94b6 --- /dev/null +++ b/quarkus/tests/integration/src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf @@ -0,0 +1,2 @@ +config-keystore=src/test/resources/keystore +config-keystore-password=secret \ No newline at end of file