From 2740e7162f8a25b881c492e43250b02161440d8d Mon Sep 17 00:00:00 2001 From: Steve Hawkins Date: Mon, 3 Aug 2026 11:21:30 -0400 Subject: [PATCH 1/2] fix: ensuring truststore initialization happens before factory init closes: #51396 Signed-off-by: Steve Hawkins --- .../quarkus/deployment/KeycloakProcessor.java | 14 ++++---------- .../keycloak/it/cli/dist/TruststoreDistTest.java | 6 +++++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java index e602b28d3289..fd65e563e2a4 100644 --- a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java +++ b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java @@ -337,14 +337,6 @@ void configureManagementInterface(BuildProducer routes, .build()); } - @Record(ExecutionTime.STATIC_INIT) - @BuildStep - @Consume(ConfigBuildItem.class) - @Consume(CryptoProviderInitBuildItem.class) // ensures the Providers are loaded prior to handle the keystore #49359 - void configureTruststore(KeycloakRecorder recorder) { - recorder.configureTruststore(getFipsMode()); - } - /** * Check whether JDBC driver is present for the specified DB * @@ -907,8 +899,10 @@ public List scan(MethodInfo method, ClassInfo actualEndp @Produce(CryptoProviderInitBuildItem.class) @BuildStep @Record(ExecutionTime.STATIC_INIT) - void setCryptoProvider(KeycloakRecorder recorder) { - recorder.setCryptoProvider(getFipsMode()); + void initCrypto(KeycloakRecorder recorder) { + FipsMode fipsMode = getFipsMode(); + recorder.setCryptoProvider(fipsMode); + recorder.configureTruststore(fipsMode); } private FipsMode getFipsMode() { diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java index d44ffef0d67c..c10220215ebb 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java @@ -22,6 +22,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.KeycloakRunner; import org.keycloak.it.junit5.extension.RawDistOnly; @@ -62,12 +63,15 @@ void testMutualAuthWithTruststorePaths(KeycloakRunner runner) { rawDist.copyOrReplaceFileFromClasspath("/self-signed.p12", Path.of("conf", "self-signed.p12")); Path keyStore = rawDist.getDistPath().resolve("conf").resolve("self-signed.p12").toAbsolutePath(); - runner.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org", + CLIResult result = runner.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org", "--log-level=org.keycloak.truststore:debug", "--truststore-paths=" + paths, "--https-client-auth=required", "--https-key-store-file=" + keyStore); given().trustStore(TruststoreDistTest.class.getResource("/self-signed-truststore.p12").getPath(), TruststoreBuilder.DUMMY_PASSWORD) .keyStore(TruststoreDistTest.class.getResource("/self-signed.p12").getPath(), "password") .get("https://mykeycloak.org:8443").then().body(Matchers.containsString("https://mykeycloak.org")); + + // ensure that the provider factories init with the correct truststore + result.getOutput().matches("File truststore provider initialized: [^\\n]*keycloak-truststore.p12"); } @Test From 1b057126853e3a533e846f8b3b54de1efc0042cf Mon Sep 17 00:00:00 2001 From: Steve Hawkins Date: Tue, 4 Aug 2026 09:07:36 -0400 Subject: [PATCH 2/2] correcting the assertion, and removing a redundant cliresult assertion Signed-off-by: Steve Hawkins --- .../it/cli/dist/CustomJpaEntityProviderDistTest.java | 10 +++++----- .../org/keycloak/it/cli/dist/TruststoreDistTest.java | 3 ++- .../org/keycloak/it/junit5/extension/CLIResult.java | 5 ----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/CustomJpaEntityProviderDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/CustomJpaEntityProviderDistTest.java index 49e53cd7859f..76d01b46f398 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/CustomJpaEntityProviderDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/CustomJpaEntityProviderDistTest.java @@ -72,15 +72,15 @@ void testUserManagedEntityNotAddedToDefaultPU(CLIResult cliResult) { cliResult.assertNoMessage("(JPA Startup Thread: client-store) Error while creating file"); cliResult.assertNoMessage("(JPA Startup Thread: keycloak-default) Error while creating file"); - cliResult.assertStringCount("name: new-user-store", 1); - cliResult.assertStringCount("name: client-store", 1); - cliResult.assertStringCount("name: pu-without-dialect-store", 1); - cliResult.assertStringCount("com.acme.provider.legacy.jpa.entity.Realm", 1); + cliResult.assertMessageWasShownExactlyNumberOfTimes("name: new-user-store", 1); + cliResult.assertMessageWasShownExactlyNumberOfTimes("name: client-store", 1); + cliResult.assertMessageWasShownExactlyNumberOfTimes("name: pu-without-dialect-store", 1); + cliResult.assertMessageWasShownExactlyNumberOfTimes("com.acme.provider.legacy.jpa.entity.Realm", 1); cliResult.assertMessage("jakarta.persistence.jtaDataSource: client-store"); cliResult.assertMessage("jakarta.persistence.jtaDataSource: new-user-store"); cliResult.assertMessage("jakarta.persistence.jtaDataSource: pu-without-dialect-store"); - cliResult.assertStringCount("hibernate.dialect: org.hibernate.dialect.H2Dialect", 4); + cliResult.assertMessageWasShownExactlyNumberOfTimes("hibernate.dialect: org.hibernate.dialect.H2Dialect", 4); cliResult.assertStartedDevMode(); } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java index c10220215ebb..624a2c110543 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/TruststoreDistTest.java @@ -71,7 +71,8 @@ void testMutualAuthWithTruststorePaths(KeycloakRunner runner) { .get("https://mykeycloak.org:8443").then().body(Matchers.containsString("https://mykeycloak.org")); // ensure that the provider factories init with the correct truststore - result.getOutput().matches("File truststore provider initialized: [^\\n]*keycloak-truststore.p12"); + // this is from the startup, so no additional waiting is necessary + assertTrue(result.getOutputStream().stream().anyMatch(s -> s.matches(".*File truststore provider initialized: .*keycloak-truststore.p12.*"))); } @Test diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java index 02a175562d6e..c36ac3f7b680 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java @@ -20,7 +20,6 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -200,8 +199,4 @@ default void assertJsonLogDefaultsApplied() throws JsonProcessingException { } } - default void assertStringCount(String msg, int count) { - Pattern pattern = Pattern.compile(msg); - assertThat((int) pattern.matcher(getOutput()).results().count(), is(count)); - } }