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 5bd87c5b6f..9b6f5d82fd 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 @@ -62,7 +62,6 @@ import org.keycloak.authorization.policy.provider.PolicySpi; import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory; import org.keycloak.common.Profile; import org.keycloak.common.crypto.FipsMode; -import org.keycloak.common.profile.PropertiesFileProfileConfigResolver; import org.keycloak.common.util.StreamUtil; import org.keycloak.config.SecurityOptions; import org.keycloak.config.StorageOptions; @@ -84,7 +83,6 @@ import org.keycloak.provider.ProviderManager; import org.keycloak.provider.Spi; import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.KeycloakRecorder; -import org.keycloak.quarkus.runtime.QuarkusProfileConfigResolver; import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider; import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider; @@ -139,6 +137,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import static org.keycloak.connections.jpa.util.JpaUtils.loadSpecificNamedQueries; +import static org.keycloak.quarkus.runtime.Environment.getCurrentOrCreateFeatureProfile; import static org.keycloak.quarkus.runtime.Environment.getProviderFiles; import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_HEALTH_ENDPOINT; import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_METRICS_ENDPOINT; @@ -222,9 +221,9 @@ class KeycloakProcessor { @BuildStep @Consume(ConfigBuildItem.class) ProfileBuildItem configureProfile(KeycloakRecorder recorder) { - Profile profile = Profile.configure( - new QuarkusProfileConfigResolver(), - new PropertiesFileProfileConfigResolver()); // Need profile.properties for now as testsuite relies on it + Profile profile = getCurrentOrCreateFeatureProfile(); + + // record the features so that they are not calculated again at runtime recorder.configureProfile(profile.getName(), profile.getFeatures()); return new ProfileBuildItem(); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java index fd691b0602..1af0c002e8 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java @@ -35,6 +35,8 @@ import io.quarkus.runtime.configuration.ProfileManager; import io.smallrye.config.SmallRyeConfig; import org.apache.commons.lang3.SystemUtils; +import org.keycloak.common.Profile; +import org.keycloak.common.profile.PropertiesFileProfileConfigResolver; import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource; public final class Environment { @@ -235,4 +237,21 @@ public final class Environment { public static void setHomeDir(Path path) { System.setProperty("kc.home.dir", path.toFile().getAbsolutePath()); } + + /** + * Do not call this method at runtime.

+ * + * The method is marked as {@code synchronized} because build steps are executed in parallel. + * + * @return the current feature profile instance + */ + public synchronized static Profile getCurrentOrCreateFeatureProfile() { + Profile profile = Profile.getInstance(); + + if (profile == null) { + profile = Profile.configure(new QuarkusProfileConfigResolver(), new PropertiesFileProfileConfigResolver()); + } + + return profile; + } } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java index f1793c564a..2901910f41 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java @@ -1,14 +1,15 @@ package org.keycloak.quarkus.runtime.configuration.mappers; +import static org.keycloak.quarkus.runtime.Environment.getCurrentOrCreateFeatureProfile; import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption; import io.smallrye.config.ConfigSourceInterceptorContext; import java.util.Optional; + import org.keycloak.common.Profile; -import org.keycloak.common.profile.PropertiesFileProfileConfigResolver; +import org.keycloak.common.Profile.Feature; import org.keycloak.config.ClassLoaderOptions; import org.keycloak.quarkus.runtime.Environment; -import org.keycloak.quarkus.runtime.QuarkusProfileConfigResolver; final class ClassLoaderPropertyMappers { @@ -25,9 +26,9 @@ final class ClassLoaderPropertyMappers { private static Optional resolveIgnoredArtifacts(Optional value, ConfigSourceInterceptorContext context) { if (Environment.isRebuildCheck() || Environment.isRebuild()) { - Profile profile = Profile.configure(new QuarkusProfileConfigResolver(), new PropertiesFileProfileConfigResolver()); + Profile profile = getCurrentOrCreateFeatureProfile(); - if (profile.getFeatures().get(Profile.Feature.FIPS)) { + if (profile.getFeatures().get(Feature.FIPS)) { return Optional.of( "org.bouncycastle:bcprov-jdk15on,org.bouncycastle:bcpkix-jdk15on,org.bouncycastle:bcutil-jdk15on,org.keycloak:keycloak-crypto-default"); } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/SecurityPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/SecurityPropertyMappers.java index c6f7a2a8ab..cefc543c1b 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/SecurityPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/SecurityPropertyMappers.java @@ -5,6 +5,8 @@ import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper. import java.util.Optional; +import org.keycloak.common.Profile; +import org.keycloak.common.Profile.Feature; import org.keycloak.common.crypto.FipsMode; import org.keycloak.config.SecurityOptions; @@ -25,21 +27,13 @@ final class SecurityPropertyMappers { private static Optional resolveFipsMode(Optional value, ConfigSourceInterceptorContext context) { if (value.isEmpty()) { + if (Profile.isFeatureEnabled(Feature.FIPS)) { + return of(FipsMode.NON_STRICT.toString()); + } + return of(FipsMode.DISABLED.toString()); } return of(FipsMode.valueOfOption(value.get()).toString()); } - - private static Optional resolveSecurityProvider(Optional value, - ConfigSourceInterceptorContext configSourceInterceptorContext) { - FipsMode fipsMode = value.map(FipsMode::valueOfOption) - .orElse(FipsMode.DISABLED); - - if (fipsMode.isFipsEnabled()) { - return of("BCFIPS"); - } - - return value; - } } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FipsDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FipsDistTest.java index c1d1fac69b..755529f3ef 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FipsDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FipsDistTest.java @@ -38,6 +38,7 @@ public class FipsDistTest { runOnFipsEnabledDistribution(dist, () -> { CLIResult cliResult = dist.run("start"); cliResult.assertStarted(); + cliResult.assertMessageWasShownExactlyNumberOfTimes("Preview features enabled: fips", 2); cliResult.assertMessage("Java security providers: [ \n" + " KC(BCFIPS version 1.000203, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider"); });