diff --git a/docs/guides/server/configuration.adoc b/docs/guides/server/configuration.adoc index e5c782a642c..f106e4a4da4 100644 --- a/docs/guides/server/configuration.adoc +++ b/docs/guides/server/configuration.adoc @@ -155,6 +155,8 @@ Note that some Quarkus properties are already mapped in the {project_name} confi To disable expression evaluation, the `\` character functions as an escape character. In particular, it must be used to escape the usage of `$` characters when they appear to define an expression or are repeated. For example, if you want the configuration value `my$$password`, use `my\$\$password` instead. Note that the `\` character requires additional escaping or quoting when using most unix shells, or when it appears in properties files. For example, bash single quotes preserve the single backslash `--db-password='my\$\$password'`. Also, with bash double quotes, you need an additional backslash `--db-password="my\\$\\$password"`. Similarly in a properties file, backslash characters must also be escaped: `kc.db-password=my\\$\\$password` +When specifying Windows file paths in configuration values, backslashes must also be escaped. For example, if you want to specify the path `C:\path\to\file`, you should write it as `C:\\path\\to\\file`. Alternatively, you can use forward slashes which don't need escaping: `C:/path/to/file`. + == Starting {project_name} You can start {project_name} in `development mode` or `production mode`. Each mode offers different defaults for the intended environment. diff --git a/quarkus/dist/src/main/content/bin/kc.bat b/quarkus/dist/src/main/content/bin/kc.bat index 6f6168f55d5..437f34e8ceb 100644 --- a/quarkus/dist/src/main/content/bin/kc.bat +++ b/quarkus/dist/src/main/content/bin/kc.bat @@ -177,8 +177,12 @@ if "x%JAVA%" == "x" ( set CLASSPATH_OPTS="%DIRNAME%..\lib\quarkus-run.jar" +rem set the homedir with \ replaced by / +set KC_HOME_DIR=%DIRNAME%.. +set KC_HOME_DIR=%KC_HOME_DIR:\=/% + rem The property 'java.util.concurrent.ForkJoinPool.common.threadFactory' is set here, as a Java Agent or enabling JMX might initialize the factory before Quarkus can set the property in JDK21+. -set JAVA_RUN_OPTS=-Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory %JAVA_OPTS% -Dkc.home.dir="%DIRNAME%.." -Djboss.server.config.dir="%DIRNAME%..\conf" -Dkeycloak.theme.dir="%DIRNAME%..\themes" %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS% +set JAVA_RUN_OPTS=-Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory %JAVA_OPTS% -Dkc.home.dir="%KC_HOME_DIR%" -Djboss.server.config.dir="%DIRNAME%..\conf" -Dkeycloak.theme.dir="%DIRNAME%..\themes" %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS% set OPTIMIZED_OPTION=--optimized set HELP_LONG_OPTION=--help 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 63a65634bde..b058a69d711 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 @@ -139,31 +139,31 @@ public final class HttpPropertyMappers { public static void validateConfig() { boolean enabled = isHttpEnabled(Configuration.getOptionalKcValue(HttpOptions.HTTP_ENABLED.getKey()).orElse(null)); - Optional certFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_CERTIFICATE_FILE.getKey()); - Optional keystoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_FILE.getKey()); + Optional certFile = Configuration.getOptionalValue(QUARKUS_HTTPS_CERT_FILES); + Optional keystoreFile = Configuration.getOptionalValue(QUARKUS_HTTPS_KEY_STORE_FILE); if (!enabled && certFile.isEmpty() && keystoreFile.isEmpty()) { throw new PropertyException(Messages.httpsConfigurationNotSet()); } CertificateConfig config = new CertificateConfig(); - config.trustStoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_FILE.getKey()).map(Paths::get); + config.trustStoreFile = Configuration.getOptionalValue(QUARKUS_HTTPS_TRUST_STORE_FILE).map(Paths::get); config.trustStorePassword = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_PASSWORD.getKey()); - config.trustStoreFileType = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_TYPE.getKey()); + config.trustStoreFileType = Configuration.getOptionalValue(QUARKUS_HTTPS_TRUST_STORE_FILE_TYPE); config.trustStoreProvider = Configuration.getOptionalValue("quarkus.http.ssl.certificate.trust-store-provider"); config.trustStoreCertAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.trust-store-cert-alias"); config.trustStoreFiles = Optional.empty(); config.keyStoreFile = keystoreFile.map(Paths::get); config.keyStorePassword = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_PASSWORD.getKey()); - config.keyStoreFileType = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_TYPE.getKey()); + config.keyStoreFileType = Configuration.getOptionalValue(QUARKUS_HTTPS_KEY_STORE_FILE_TYPE); config.keyStoreProvider = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-provider"); config.keyStoreAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias"); config.keyStoreAliasPassword = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias-password"); config.keyStoreAliasPasswordKey = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias-password-key"); config.keyStoreKeyAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-key-alias"); - config.keyFiles = Configuration.getOptionalKcValue(HttpOptions.HTTPS_CERTIFICATE_KEY_FILE.getKey()).map(Paths::get).map(List::of); + config.keyFiles = Configuration.getOptionalValue(QUARKUS_HTTPS_CERT_KEY_FILES).map(Paths::get).map(List::of); config.files = certFile.map(Paths::get).map(List::of); try { diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/JavaOptsScriptTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/JavaOptsScriptTest.java index 07afe821464..9fc28421a93 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/JavaOptsScriptTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/JavaOptsScriptTest.java @@ -22,8 +22,10 @@ import io.quarkus.test.junit.main.LaunchResult; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; import org.keycloak.it.junit5.extension.DistributionTest; +import org.keycloak.it.junit5.extension.DryRun; import org.keycloak.it.junit5.extension.RawDistOnly; import org.keycloak.it.junit5.extension.WithEnvVars; @@ -32,6 +34,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.matchesPattern; +@DryRun @DistributionTest @RawDistOnly(reason = "No need to test script again on container") @WithEnvVars({"PRINT_ENV", "true"}) @@ -120,4 +123,13 @@ public class JavaOptsScriptTest { assertThat(output, containsString("DefaultFactory: groovy Closures in annotations are disabled and will not be loaded")); } + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different path behaviour on Windows.") + @Test + @Launch({"start-dev", "--optimized"}) + void testKcHomeDirPathFormat(LaunchResult result) { + String output = result.getOutput(); + assertThat(output, containsString("kc.home.dir=")); + assertThat(output, matchesPattern("(?s).*kc\\.home\\.dir=\"[A-Z]:/.*?/keycloak/quarkus/tests/integration/target/kc-tests/keycloak-\\d+\\.\\d+\\.\\d+.*?/bin/\\.\\.\".*")); + } + } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/QuarkusPropertiesDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/QuarkusPropertiesDistTest.java index b7cf28847e3..6db22c54691 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/QuarkusPropertiesDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/QuarkusPropertiesDistTest.java @@ -179,7 +179,7 @@ public class QuarkusPropertiesDistTest { "--https-certificate-key-file=C:\\tmp\\kc\\bin\\..\\conf/server.key.pem" }) @Order(14) void testHttpCertsPathTransformerOnWindows(CLIResult cliResult) { - cliResult.assertError("Failed to load 'https-key-' material: NoSuchFileException C:/tmp/kc/bin/../conf/server.crt.pem"); + cliResult.assertError("Failed to load 'https-key-' material: NoSuchFileException C:\\tmp\\kc\\bin\\..\\conf\\server.crt.pem"); } public static class AddConsoleHandlerFromQuarkusProps implements Consumer { diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java index fa1ccdf9049..aa3e2b8e179 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java @@ -102,7 +102,8 @@ public class CLITestExtension extends QuarkusMainTestExtension { configureEnvVars(context.getRequiredTestClass().getAnnotation(WithEnvVars.class)); configureEnvVars(context.getRequiredTestMethod().getAnnotation(WithEnvVars.class)); - boolean dryRun = context.getRequiredTestMethod().getAnnotation(DryRun.class) != null; + boolean dryRun = context.getRequiredTestClass().getAnnotation(DryRun.class) != null + || context.getRequiredTestMethod().getAnnotation(DryRun.class) != null; if (dryRun && isRaw()) { dist.setEnvVar(DryRunMixin.KC_DRY_RUN_ENV, "true"); dist.setEnvVar(DryRunMixin.KC_DRY_RUN_BUILD_ENV, "true"); diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DryRun.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DryRun.java index a0ef9d360e3..2983f754d12 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DryRun.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DryRun.java @@ -25,7 +25,7 @@ import java.lang.annotation.Target; /** * {@link DryRun} is used to configure a non-running, non-augmenting distribution */ -@Target({ ElementType.METHOD }) +@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface DryRun {