Avoid initing the profile multiple times during re-augmentation

Closes keycloak#19324
This commit is contained in:
Pedro Igor 2023-03-27 08:12:52 -03:00
parent f0057157da
commit cda0c9dce0
5 changed files with 35 additions and 21 deletions

View file

@ -62,7 +62,6 @@ import org.keycloak.authorization.policy.provider.PolicySpi;
import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory; import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory;
import org.keycloak.common.Profile; import org.keycloak.common.Profile;
import org.keycloak.common.crypto.FipsMode; import org.keycloak.common.crypto.FipsMode;
import org.keycloak.common.profile.PropertiesFileProfileConfigResolver;
import org.keycloak.common.util.StreamUtil; import org.keycloak.common.util.StreamUtil;
import org.keycloak.config.SecurityOptions; import org.keycloak.config.SecurityOptions;
import org.keycloak.config.StorageOptions; import org.keycloak.config.StorageOptions;
@ -84,7 +83,6 @@ import org.keycloak.provider.ProviderManager;
import org.keycloak.provider.Spi; import org.keycloak.provider.Spi;
import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.KeycloakRecorder; 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.Configuration;
import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider; import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider; import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
@ -139,6 +137,7 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import static org.keycloak.connections.jpa.util.JpaUtils.loadSpecificNamedQueries; 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.Environment.getProviderFiles;
import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_HEALTH_ENDPOINT; import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_HEALTH_ENDPOINT;
import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_METRICS_ENDPOINT; import static org.keycloak.quarkus.runtime.KeycloakRecorder.DEFAULT_METRICS_ENDPOINT;
@ -222,9 +221,9 @@ class KeycloakProcessor {
@BuildStep @BuildStep
@Consume(ConfigBuildItem.class) @Consume(ConfigBuildItem.class)
ProfileBuildItem configureProfile(KeycloakRecorder recorder) { ProfileBuildItem configureProfile(KeycloakRecorder recorder) {
Profile profile = Profile.configure( Profile profile = getCurrentOrCreateFeatureProfile();
new QuarkusProfileConfigResolver(),
new PropertiesFileProfileConfigResolver()); // Need profile.properties for now as testsuite relies on it // record the features so that they are not calculated again at runtime
recorder.configureProfile(profile.getName(), profile.getFeatures()); recorder.configureProfile(profile.getName(), profile.getFeatures());
return new ProfileBuildItem(); return new ProfileBuildItem();

View file

@ -35,6 +35,8 @@ import io.quarkus.runtime.configuration.ProfileManager;
import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfig;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.keycloak.common.Profile;
import org.keycloak.common.profile.PropertiesFileProfileConfigResolver;
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource; import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
public final class Environment { public final class Environment {
@ -235,4 +237,21 @@ public final class Environment {
public static void setHomeDir(Path path) { public static void setHomeDir(Path path) {
System.setProperty("kc.home.dir", path.toFile().getAbsolutePath()); System.setProperty("kc.home.dir", path.toFile().getAbsolutePath());
} }
/**
* Do not call this method at runtime.</p>
*
* 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;
}
} }

View file

@ -1,14 +1,15 @@
package org.keycloak.quarkus.runtime.configuration.mappers; 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 static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
import io.smallrye.config.ConfigSourceInterceptorContext; import io.smallrye.config.ConfigSourceInterceptorContext;
import java.util.Optional; import java.util.Optional;
import org.keycloak.common.Profile; 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.config.ClassLoaderOptions;
import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.QuarkusProfileConfigResolver;
final class ClassLoaderPropertyMappers { final class ClassLoaderPropertyMappers {
@ -25,9 +26,9 @@ final class ClassLoaderPropertyMappers {
private static Optional<String> resolveIgnoredArtifacts(Optional<String> value, ConfigSourceInterceptorContext context) { private static Optional<String> resolveIgnoredArtifacts(Optional<String> value, ConfigSourceInterceptorContext context) {
if (Environment.isRebuildCheck() || Environment.isRebuild()) { 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( return Optional.of(
"org.bouncycastle:bcprov-jdk15on,org.bouncycastle:bcpkix-jdk15on,org.bouncycastle:bcutil-jdk15on,org.keycloak:keycloak-crypto-default"); "org.bouncycastle:bcprov-jdk15on,org.bouncycastle:bcpkix-jdk15on,org.bouncycastle:bcutil-jdk15on,org.keycloak:keycloak-crypto-default");
} }

View file

@ -5,6 +5,8 @@ import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.
import java.util.Optional; import java.util.Optional;
import org.keycloak.common.Profile;
import org.keycloak.common.Profile.Feature;
import org.keycloak.common.crypto.FipsMode; import org.keycloak.common.crypto.FipsMode;
import org.keycloak.config.SecurityOptions; import org.keycloak.config.SecurityOptions;
@ -25,21 +27,13 @@ final class SecurityPropertyMappers {
private static Optional<String> resolveFipsMode(Optional<String> value, ConfigSourceInterceptorContext context) { private static Optional<String> resolveFipsMode(Optional<String> value, ConfigSourceInterceptorContext context) {
if (value.isEmpty()) { if (value.isEmpty()) {
if (Profile.isFeatureEnabled(Feature.FIPS)) {
return of(FipsMode.NON_STRICT.toString());
}
return of(FipsMode.DISABLED.toString()); return of(FipsMode.DISABLED.toString());
} }
return of(FipsMode.valueOfOption(value.get()).toString()); return of(FipsMode.valueOfOption(value.get()).toString());
} }
private static Optional<String> resolveSecurityProvider(Optional<String> value,
ConfigSourceInterceptorContext configSourceInterceptorContext) {
FipsMode fipsMode = value.map(FipsMode::valueOfOption)
.orElse(FipsMode.DISABLED);
if (fipsMode.isFipsEnabled()) {
return of("BCFIPS");
}
return value;
}
} }

View file

@ -38,6 +38,7 @@ public class FipsDistTest {
runOnFipsEnabledDistribution(dist, () -> { runOnFipsEnabledDistribution(dist, () -> {
CLIResult cliResult = dist.run("start"); CLIResult cliResult = dist.run("start");
cliResult.assertStarted(); cliResult.assertStarted();
cliResult.assertMessageWasShownExactlyNumberOfTimes("Preview features enabled: fips", 2);
cliResult.assertMessage("Java security providers: [ \n" cliResult.assertMessage("Java security providers: [ \n"
+ " KC(BCFIPS version 1.000203, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider"); + " KC(BCFIPS version 1.000203, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
}); });