Polish fips-mode switch for preview (#17228)

* Polish fips-mode switch for preview
Closes #17208 #17210 


Co-authored-by: mposolda <mposolda@gmail.com>
This commit is contained in:
rmartinc 2023-02-22 12:12:52 +01:00 committed by GitHub
parent 9df7ef4331
commit f91ac2970d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 150 additions and 106 deletions

View file

@ -32,6 +32,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -86,7 +87,9 @@ public class Profile {
UPDATE_EMAIL("Update Email Action", Type.PREVIEW), UPDATE_EMAIL("Update Email Action", Type.PREVIEW),
JS_ADAPTER("Host keycloak.js and keycloak-authz.js through the Keycloak sever", Type.DEFAULT); JS_ADAPTER("Host keycloak.js and keycloak-authz.js through the Keycloak sever", Type.DEFAULT),
FIPS("FIPS 140-2 mode", Type.PREVIEW_DISABLED_BY_DEFAULT);
private final Type type; private final Type type;
private String label; private String label;
@ -123,6 +126,7 @@ public class Profile {
DEFAULT("Default"), DEFAULT("Default"),
DISABLED_BY_DEFAULT("Disabled by default"), DISABLED_BY_DEFAULT("Disabled by default"),
PREVIEW("Preview"), PREVIEW("Preview"),
PREVIEW_DISABLED_BY_DEFAULT("Preview disabled by default"), // Preview features, which are not automatically enabled even with enabled preview profile (Needs to be enabled explicitly)
EXPERIMENTAL("Experimental"), EXPERIMENTAL("Experimental"),
DEPRECATED("Deprecated"); DEPRECATED("Deprecated");
@ -197,8 +201,12 @@ public class Profile {
return features.entrySet().stream().filter(e -> !e.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet()); return features.entrySet().stream().filter(e -> !e.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
} }
/**
* @return all features of type "preview" or "preview_disabled_by_default"
*/
public Set<Feature> getPreviewFeatures() { public Set<Feature> getPreviewFeatures() {
return getFeatures(Feature.Type.PREVIEW); return Stream.concat(getFeatures(Feature.Type.PREVIEW).stream(), getFeatures(Feature.Type.PREVIEW_DISABLED_BY_DEFAULT).stream())
.collect(Collectors.toSet());
} }
public Set<Feature> getExperimentalFeatures() { public Set<Feature> getExperimentalFeatures() {
@ -257,14 +265,18 @@ public class Profile {
} }
private void logUnsupportedFeatures() { private void logUnsupportedFeatures() {
logUnsuportedFeatures(Feature.Type.PREVIEW, Logger.Level.INFO); logUnsuportedFeatures(Feature.Type.PREVIEW, getPreviewFeatures(), Logger.Level.INFO);
logUnsuportedFeatures(Feature.Type.EXPERIMENTAL, Logger.Level.WARN); logUnsuportedFeatures(Feature.Type.EXPERIMENTAL, getExperimentalFeatures(), Logger.Level.WARN);
logUnsuportedFeatures(Feature.Type.DEPRECATED, Logger.Level.WARN); logUnsuportedFeatures(Feature.Type.DEPRECATED, getDeprecatedFeatures(), Logger.Level.WARN);
} }
private void logUnsuportedFeatures(Feature.Type type, Logger.Level level) { private void logUnsuportedFeatures(Feature.Type type, Set<Feature> checkedFeatures, Logger.Level level) {
Set<Feature.Type> checkedFeatureTypes = checkedFeatures.stream()
.map(Feature::getType)
.collect(Collectors.toSet());
String enabledFeaturesOfType = features.entrySet().stream() String enabledFeaturesOfType = features.entrySet().stream()
.filter(e -> e.getValue() && e.getKey().getType().equals(type)) .filter(e -> e.getValue() && checkedFeatureTypes.contains(e.getKey().getType()))
.map(e -> e.getKey().getKey()).sorted().collect(Collectors.joining(", ")); .map(e -> e.getKey().getKey()).sorted().collect(Collectors.joining(", "));
if (!enabledFeaturesOfType.isEmpty()) { if (!enabledFeaturesOfType.isEmpty()) {

View file

@ -1,21 +1,32 @@
package org.keycloak.common.crypto; package org.keycloak.common.crypto;
public enum FipsMode { public enum FipsMode {
enabled("org.keycloak.crypto.fips.FIPS1402Provider"), NON_STRICT("org.keycloak.crypto.fips.FIPS1402Provider"),
strict("org.keycloak.crypto.fips.Fips1402StrictCryptoProvider"), STRICT("org.keycloak.crypto.fips.Fips1402StrictCryptoProvider"),
disabled("org.keycloak.crypto.def.DefaultCryptoProvider"); DISABLED("org.keycloak.crypto.def.DefaultCryptoProvider");
private String providerClassName; private final String providerClassName;
private final String optionName;
FipsMode(String providerClassName) { FipsMode(String providerClassName) {
this.providerClassName = providerClassName; this.providerClassName = providerClassName;
this.optionName = name().toLowerCase().replace('_', '-');
} }
public boolean isFipsEnabled() { public boolean isFipsEnabled() {
return this.equals(enabled) || this.equals(strict); return this.equals(NON_STRICT) || this.equals(STRICT);
} }
public String getProviderClassName() { public String getProviderClassName() {
return providerClassName; return providerClassName;
} }
public static FipsMode valueOfOption(String name) {
return valueOf(name.toUpperCase().replace('-', '_'));
}
@Override
public String toString() {
return optionName;
}
} }

View file

@ -70,13 +70,13 @@ public class ProfileTest {
} }
Assert.assertEquals(Profile.ProfileName.DEFAULT, profile.getName()); Assert.assertEquals(Profile.ProfileName.DEFAULT, profile.getName());
Set<Profile.Feature> disabledFeatutes = new HashSet<>(Arrays.asList(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.DYNAMIC_SCOPES, Profile.Feature.DOCKER, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.MAP_STORAGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL)); Set<Profile.Feature> disabledFeatutes = new HashSet<>(Arrays.asList(Profile.Feature.FIPS, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.DYNAMIC_SCOPES, Profile.Feature.DOCKER, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.MAP_STORAGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL));
// KERBEROS can be disabled (i.e. FIPS mode disables SunJGSS provider) // KERBEROS can be disabled (i.e. FIPS mode disables SunJGSS provider)
if (Profile.Feature.KERBEROS.getType() == Profile.Feature.Type.DISABLED_BY_DEFAULT) { if (Profile.Feature.KERBEROS.getType() == Profile.Feature.Type.DISABLED_BY_DEFAULT) {
disabledFeatutes.add(Profile.Feature.KERBEROS); disabledFeatutes.add(Profile.Feature.KERBEROS);
} }
assertEquals(profile.getDisabledFeatures(), disabledFeatutes); assertEquals(profile.getDisabledFeatures(), disabledFeatutes);
assertEquals(profile.getPreviewFeatures(), Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL); assertEquals(profile.getPreviewFeatures(), Profile.Feature.FIPS, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL);
} }
@Test @Test

View file

@ -84,7 +84,7 @@ public class HttpOptions {
.category(OptionCategory.HTTP) .category(OptionCategory.HTTP)
.description("The type of the key store file. " + .description("The type of the key store file. " +
"If not given, the type is automatically detected based on the file name. " + "If not given, the type is automatically detected based on the file name. " +
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.strict.name() + "' and no value is set, it defaults to 'BCFKS'.") "If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
.build(); .build();
public static final Option HTTPS_TRUST_STORE_FILE = new OptionBuilder<>("https-trust-store-file", File.class) public static final Option HTTPS_TRUST_STORE_FILE = new OptionBuilder<>("https-trust-store-file", File.class)
@ -101,7 +101,7 @@ public class HttpOptions {
.category(OptionCategory.HTTP) .category(OptionCategory.HTTP)
.description("The type of the trust store file. " + .description("The type of the trust store file. " +
"If not given, the type is automatically detected based on the file name. " + "If not given, the type is automatically detected based on the file name. " +
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.strict.name() + "' and no value is set, it defaults to 'BCFKS'.") "If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
.build(); .build();
public static final Option<Boolean> HTTP_SERVER_ENABLED = new OptionBuilder<>("http-server-enabled", Boolean.class) public static final Option<Boolean> HTTP_SERVER_ENABLED = new OptionBuilder<>("http-server-enabled", Boolean.class)

View file

@ -14,7 +14,7 @@ public enum OptionCategory {
PROXY("Proxy", 90, ConfigSupportLevel.SUPPORTED), PROXY("Proxy", 90, ConfigSupportLevel.SUPPORTED),
VAULT("Vault", 100, ConfigSupportLevel.SUPPORTED), VAULT("Vault", 100, ConfigSupportLevel.SUPPORTED),
LOGGING("Logging", 110, ConfigSupportLevel.SUPPORTED), LOGGING("Logging", 110, ConfigSupportLevel.SUPPORTED),
SECURITY("Security", 120, ConfigSupportLevel.EXPERIMENTAL), SECURITY("Security", 120, ConfigSupportLevel.PREVIEW),
GENERAL("General", 999, ConfigSupportLevel.SUPPORTED); GENERAL("General", 999, ConfigSupportLevel.SUPPORTED);
private String heading; private String heading;

View file

@ -1,13 +1,21 @@
package org.keycloak.config; package org.keycloak.config;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.keycloak.common.crypto.FipsMode; import org.keycloak.common.crypto.FipsMode;
public class SecurityOptions { public class SecurityOptions {
public static final Option<FipsMode> FIPS_MODE = new OptionBuilder<>("fips-mode", FipsMode.class) public static final Option<FipsMode> FIPS_MODE = new OptionBuilder<>("fips-mode", FipsMode.class)
.category(OptionCategory.SECURITY) .category(OptionCategory.SECURITY)
.expectedValues(SecurityOptions::getFipsModeValues)
.buildTime(true) .buildTime(true)
.description("Sets the FIPS mode. If 'enabled' is set, FIPS is enabled but on non-approved mode. For full FIPS compliance, set 'strict' to run on approved mode.") .description("Sets the FIPS mode. If '" + FipsMode.NON_STRICT + "' is set, FIPS is enabled but on non-approved mode. For full FIPS compliance, set '" + FipsMode.STRICT + "' to run on approved mode.")
.defaultValue(FipsMode.disabled) .defaultValue(FipsMode.DISABLED)
.build(); .build();
private static List<String> getFipsModeValues() {
return Arrays.asList(FipsMode.NON_STRICT.toString(), FipsMode.STRICT.toString());
}
} }

View file

@ -84,7 +84,6 @@ import io.smallrye.config.ConfigValue;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
import org.hibernate.jpa.boot.internal.PersistenceXmlParser; import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo; import org.jboss.jandex.ClassInfo;
@ -217,9 +216,7 @@ class KeycloakProcessor {
return new ConfigBuildItem(); return new ConfigBuildItem();
} }
@Record(ExecutionTime.STATIC_INIT) // called from setCryptoProvider now
@BuildStep
@Consume(ConfigBuildItem.class)
ProfileBuildItem configureProfile(KeycloakRecorder recorder) { ProfileBuildItem configureProfile(KeycloakRecorder recorder) {
Profile profile = Profile.configure( Profile profile = Profile.configure(
new QuarkusProfileConfigResolver(), new QuarkusProfileConfigResolver(),
@ -625,9 +622,16 @@ class KeycloakProcessor {
@BuildStep @BuildStep
@Record(ExecutionTime.STATIC_INIT) @Record(ExecutionTime.STATIC_INIT)
void setCryptoProvider(KeycloakRecorder recorder) { void setCryptoProvider(KeycloakRecorder recorder) {
FipsMode fipsMode = Configuration.getOptionalValue( configureProfile(recorder);
NS_KEYCLOAK_PREFIX + SecurityOptions.FIPS_MODE.getKey()).map( FipsMode fipsMode = Configuration.getOptionalValue(NS_KEYCLOAK_PREFIX + SecurityOptions.FIPS_MODE.getKey())
FipsMode::valueOf).orElse(FipsMode.disabled); .map(FipsMode::valueOfOption)
.orElse(FipsMode.DISABLED);
if (Profile.isFeatureEnabled(Profile.Feature.FIPS) && !fipsMode.isFipsEnabled()) {
// default to non strict when fips feature enabled
fipsMode = FipsMode.NON_STRICT;
} else if (fipsMode.isFipsEnabled() && !Profile.isFeatureEnabled(Profile.Feature.FIPS)) {
throw new RuntimeException("FIPS mode cannot be enabled without enabling the FIPS feature --features=fips");
}
recorder.setCryptoProvider(fipsMode); recorder.setCryptoProvider(fipsMode);
} }

View file

@ -2,17 +2,13 @@ package org.keycloak.quarkus.runtime.configuration.mappers;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption; import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
import java.util.Optional;
import org.keycloak.common.crypto.FipsMode;
import org.keycloak.config.ClassLoaderOptions;
import org.keycloak.config.SecurityOptions;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
import io.smallrye.config.ConfigSourceInterceptorContext; import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue; import java.util.Optional;
import org.keycloak.common.Profile;
import org.keycloak.common.profile.PropertiesFileProfileConfigResolver;
import org.keycloak.config.ClassLoaderOptions;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.QuarkusProfileConfigResolver;
final class ClassLoaderPropertyMappers { final class ClassLoaderPropertyMappers {
@ -29,10 +25,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()) {
ConfigValue fipsEnabled = Configuration.getConfigValue( Profile profile = Profile.configure(new QuarkusProfileConfigResolver(), new PropertiesFileProfileConfigResolver());
MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX + SecurityOptions.FIPS_MODE.getKey());
if (fipsEnabled != null && FipsMode.valueOf(fipsEnabled.getValue()).isFipsEnabled()) { if (profile.getFeatures().get(Profile.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

@ -147,7 +147,7 @@ final class HttpPropertyMappers {
ConfigSourceInterceptorContext configSourceInterceptorContext) { ConfigSourceInterceptorContext configSourceInterceptorContext) {
if (value.isPresent()) { if (value.isPresent()) {
try { try {
if (FipsMode.valueOf(value.get()).equals(FipsMode.strict)) { if (FipsMode.valueOfOption(value.get()).equals(FipsMode.STRICT)) {
return of("BCFKS"); return of("BCFKS");
} }
return empty(); return empty();

View file

@ -25,16 +25,16 @@ 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()) {
return of(FipsMode.disabled.toString()); return of(FipsMode.DISABLED.toString());
} }
return of(FipsMode.valueOf(value.get()).toString()); return of(FipsMode.valueOfOption(value.get()).toString());
} }
private static Optional<String> resolveSecurityProvider(Optional<String> value, private static Optional<String> resolveSecurityProvider(Optional<String> value,
ConfigSourceInterceptorContext configSourceInterceptorContext) { ConfigSourceInterceptorContext configSourceInterceptorContext) {
FipsMode fipsMode = value.map(FipsMode::valueOf) FipsMode fipsMode = value.map(FipsMode::valueOfOption)
.orElse(FipsMode.disabled); .orElse(FipsMode.DISABLED);
if (fipsMode.isFipsEnabled()) { if (fipsMode.isFipsEnabled()) {
return of("BCFIPS"); return of("BCFIPS");

View file

@ -118,7 +118,7 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError</argLine> <argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError --add-opens=java.base/java.security=ALL-UNNAMED</argLine>
<systemPropertyVariables> <systemPropertyVariables>
<kc.quarkus.tests.dist>${kc.quarkus.tests.dist}</kc.quarkus.tests.dist> <kc.quarkus.tests.dist>${kc.quarkus.tests.dist}</kc.quarkus.tests.dist>
</systemPropertyVariables> </systemPropertyVariables>

View file

@ -123,7 +123,7 @@ public class Keycloak {
addOptionIfNotSet(args, StorageOptions.STORAGE, StorageOptions.StorageType.chm); addOptionIfNotSet(args, StorageOptions.STORAGE, StorageOptions.StorageType.chm);
} }
boolean isFipsEnabled = ofNullable(getOptionValue(args, SecurityOptions.FIPS_MODE)).orElse(FipsMode.disabled).isFipsEnabled(); boolean isFipsEnabled = ofNullable(getOptionValue(args, SecurityOptions.FIPS_MODE)).orElse(FipsMode.DISABLED).isFipsEnabled();
if (isFipsEnabled) { if (isFipsEnabled) {
String logLevel = getOptionValue(args, LoggingOptions.LOG_LEVEL); String logLevel = getOptionValue(args, LoggingOptions.LOG_LEVEL);

View file

@ -60,7 +60,6 @@ final class ServerOptions extends ArrayList<String> {
private Map<String, Predicate<String>> getDefaultOptions(LegacyStore legacyStoreConfig, WithDatabase withDatabase) { private Map<String, Predicate<String>> getDefaultOptions(LegacyStore legacyStoreConfig, WithDatabase withDatabase) {
Map<String, Predicate<String>> defaultOptions = new HashMap<>(); Map<String, Predicate<String>> defaultOptions = new HashMap<>();
defaultOptions.put("--storage=chm", ignoreStorageChm(legacyStoreConfig, withDatabase));
defaultOptions.put("--cache=local", ignoreCacheLocal(legacyStoreConfig)); defaultOptions.put("--cache=local", ignoreCacheLocal(legacyStoreConfig));
return defaultOptions; return defaultOptions;

View file

@ -28,6 +28,8 @@ import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.OPTI
@LegacyStore @LegacyStore
public class FeaturesDistTest { public class FeaturesDistTest {
private static final String PREVIEW_FEATURES_EXPECTED_LOG = "Preview features enabled: admin-fine-grained-authz, client-secret-rotation, declarative-user-profile, openshift-integration, recovery-codes, scripts, token-exchange, update-email";
@Test @Test
public void testEnableOnBuild(KeycloakDistribution dist) { public void testEnableOnBuild(KeycloakDistribution dist) {
CLIResult cliResult = dist.run(Build.NAME, "--features=preview"); CLIResult cliResult = dist.run(Build.NAME, "--features=preview");
@ -47,6 +49,18 @@ public class FeaturesDistTest {
assertPreviewFeaturesEnabled((CLIResult) result); assertPreviewFeaturesEnabled((CLIResult) result);
} }
// Should enable "fips" together with all other "preview" features
@Test
@Launch({StartDev.NAME, "--features=preview,fips"})
public void testEnablePreviewFeaturesAndFips(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
String previewFeaturesWithFipsIncluded = PREVIEW_FEATURES_EXPECTED_LOG.replace("declarative-user-profile", "declarative-user-profile, fips");
assertThat(result.getOutput(), CoreMatchers.allOf(
containsString(previewFeaturesWithFipsIncluded)));
cliResult.assertError("Failed to configure FIPS.");
}
@Test @Test
@Launch({StartDev.NAME, "--features=preview", "--features-disabled=token-exchange"}) @Launch({StartDev.NAME, "--features=preview", "--features-disabled=token-exchange"})
public void testPreviewFeatureDisabledInPreviewMode(LaunchResult result) { public void testPreviewFeatureDisabledInPreviewMode(LaunchResult result) {
@ -87,6 +101,6 @@ public class FeaturesDistTest {
private void assertPreviewFeaturesEnabled(CLIResult result) { private void assertPreviewFeaturesEnabled(CLIResult result) {
assertThat(result.getOutput(), CoreMatchers.allOf( assertThat(result.getOutput(), CoreMatchers.allOf(
containsString("Preview features enabled: admin-fine-grained-authz, client-secret-rotation, declarative-user-profile, openshift-integration, recovery-codes, scripts, token-exchange, update-email"))); containsString(PREVIEW_FEATURES_EXPECTED_LOG)));
} }
} }

View file

@ -29,14 +29,14 @@ import org.keycloak.it.utils.RawKeycloakDistribution;
import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult; import io.quarkus.test.junit.main.LaunchResult;
@DistributionTest(keepAlive = true, defaultOptions = { "--http-enabled=true", "--hostname-strict=false", "--log-level=org.keycloak.common.crypto.CryptoIntegration:trace" }) @DistributionTest(keepAlive = true, defaultOptions = { "--features=fips", "--http-enabled=true", "--hostname-strict=false", "--log-level=org.keycloak.common.crypto.CryptoIntegration:trace" })
@RawDistOnly(reason = "Containers are immutable") @RawDistOnly(reason = "Containers are immutable")
public class FipsDistTest { public class FipsDistTest {
@Test @Test
void testFipsNonApprovedMode(KeycloakDistribution dist) { void testFipsNonApprovedMode(KeycloakDistribution dist) {
runOnFipsEnabledDistribution(dist, () -> { runOnFipsEnabledDistribution(dist, () -> {
CLIResult cliResult = dist.run("start", "--fips-mode=enabled"); CLIResult cliResult = dist.run("start");
cliResult.assertStarted(); cliResult.assertStarted();
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");
@ -64,7 +64,7 @@ public class FipsDistTest {
} }
@Test @Test
@Launch({ "start", "--fips-mode=enabled" }) @Launch({ "start", "--fips-mode=non-strict" })
void failStartDueToMissingFipsDependencies(LaunchResult result) { void failStartDueToMissingFipsDependencies(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
cliResult.assertError("Failed to configure FIPS. Make sure you have added the Bouncy Castle FIPS dependencies to the 'providers' directory."); cliResult.assertError("Failed to configure FIPS. Make sure you have added the Bouncy Castle FIPS dependencies to the 'providers' directory.");
@ -116,7 +116,7 @@ public class FipsDistTest {
void testHttpsPkcs12KeyStoreInNonApprovedMode(KeycloakDistribution dist) { void testHttpsPkcs12KeyStoreInNonApprovedMode(KeycloakDistribution dist) {
runOnFipsEnabledDistribution(dist, () -> { runOnFipsEnabledDistribution(dist, () -> {
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore")); dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
CLIResult cliResult = dist.run("start", "--fips-mode=enabled", "--https-key-store-password=passwordpassword"); CLIResult cliResult = dist.run("start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword");
cliResult.assertStarted(); cliResult.assertStarted();
}); });
} }
@ -129,8 +129,8 @@ public class FipsDistTest {
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class); RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath(); Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
// https-trust-store-type should be automatically set to pkcs12 in fips-mode=enabled // https-trust-store-type should be automatically set to pkcs12 in fips-mode=non-strict
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=enabled", "--https-key-store-password=passwordpassword", CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword"); "--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
cliResult.assertStarted(); cliResult.assertStarted();
}); });

View file

@ -75,13 +75,13 @@ public class ImportAtStartupDistTest {
@Test @Test
@BeforeStartDistribution(CreateRealmConfigurationFile.class) @BeforeStartDistribution(CreateRealmConfigurationFile.class)
void testImportFromFileCreatedByExportAllRealms(KeycloakDistribution dist) throws IOException { void testImportFromFileCreatedByExportAllRealms(KeycloakDistribution dist) throws IOException {
dist.run("start-dev", "--import-realm"); dist.run("start-dev", "--import-realm", "--storage=chm");
dist.run("export", "--file=../data/import/realm.json"); dist.run("export", "--file=../data/import/realm.json");
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class); RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath()); FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath());
CLIResult result = dist.run("start-dev", "--import-realm"); CLIResult result = dist.run("start-dev", "--import-realm", "--storage=chm");
result.assertMessage("Realm 'quickstart-realm' imported"); result.assertMessage("Realm 'quickstart-realm' imported");
result.assertMessage("Realm 'master' already exists. Import skipped"); result.assertMessage("Realm 'master' already exists. Import skipped");
} }
@ -89,13 +89,13 @@ public class ImportAtStartupDistTest {
@Test @Test
@BeforeStartDistribution(CreateRealmConfigurationFile.class) @BeforeStartDistribution(CreateRealmConfigurationFile.class)
void testImportFromFileCreatedByExportSingleRealm(KeycloakDistribution dist) throws IOException { void testImportFromFileCreatedByExportSingleRealm(KeycloakDistribution dist) throws IOException {
dist.run("start-dev", "--import-realm"); dist.run("start-dev", "--import-realm", "--storage=chm");
dist.run("export", "--realm=quickstart-realm", "--file=../data/import/realm.json"); dist.run("export", "--realm=quickstart-realm", "--file=../data/import/realm.json");
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class); RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath()); FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath());
CLIResult result = dist.run("start-dev", "--import-realm"); CLIResult result = dist.run("start-dev", "--import-realm", "--storage=chm");
result.assertMessage("Realm 'quickstart-realm' imported"); result.assertMessage("Realm 'quickstart-realm' imported");
result.assertNoMessage("Not importing realm master from file"); result.assertNoMessage("Not importing realm master from file");
} }
@ -103,14 +103,14 @@ public class ImportAtStartupDistTest {
@Test @Test
@BeforeStartDistribution(CreateRealmConfigurationFile.class) @BeforeStartDistribution(CreateRealmConfigurationFile.class)
void testImportFromDirCreatedByExport(KeycloakDistribution dist) throws IOException { void testImportFromDirCreatedByExport(KeycloakDistribution dist) throws IOException {
dist.run("start-dev", "--import-realm"); dist.run("start-dev", "--import-realm", "--storage=chm");
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class); RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("import").toAbsolutePath()); FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("import").toAbsolutePath());
dist.run("export", "--dir=../data/import"); dist.run("export", "--dir=../data/import");
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath()); FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("chm").toAbsolutePath());
CLIResult result = dist.run("start-dev", "--import-realm"); CLIResult result = dist.run("start-dev", "--import-realm", "--storage=chm");
result.assertMessage("Realm 'quickstart-realm' imported"); result.assertMessage("Realm 'quickstart-realm' imported");
result.assertNoMessage("Not importing realm master from file"); result.assertNoMessage("Not importing realm master from file");
} }

View file

@ -46,14 +46,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -46,14 +46,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -69,14 +69,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -69,14 +69,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -129,14 +129,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
@ -280,11 +280,11 @@ Logging:
categories and their levels. For the root category, you don't need to categories and their levels. For the root category, you don't need to
specify a category. Default: info. specify a category. Default: info.
Security (Experimental): Security (Preview):
--fips-mode <mode> Experimental: Sets the FIPS mode. If 'enabled' is set, FIPS is enabled but on --fips-mode <mode> Preview: Sets the FIPS mode. If 'non-strict' is set, FIPS is enabled but on
non-approved mode. For full FIPS compliance, set 'strict' to run on approved non-approved mode. For full FIPS compliance, set 'strict' to run on approved
mode. Possible values are: enabled, strict, disabled. Default: disabled. mode. Possible values are: non-strict, strict. Default: disabled.
Do NOT start the server using this command when deploying to production. Do NOT start the server using this command when deploying to production.

View file

@ -129,14 +129,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
@ -280,11 +280,11 @@ Logging:
categories and their levels. For the root category, you don't need to categories and their levels. For the root category, you don't need to
specify a category. Default: info. specify a category. Default: info.
Security (Experimental): Security (Preview):
--fips-mode <mode> Experimental: Sets the FIPS mode. If 'enabled' is set, FIPS is enabled but on --fips-mode <mode> Preview: Sets the FIPS mode. If 'non-strict' is set, FIPS is enabled but on
non-approved mode. For full FIPS compliance, set 'strict' to run on approved non-approved mode. For full FIPS compliance, set 'strict' to run on approved
mode. Possible values are: enabled, strict, disabled. Default: disabled. mode. Possible values are: non-strict, strict. Default: disabled.
Do NOT start the server using this command when deploying to production. Do NOT start the server using this command when deploying to production.

View file

@ -75,14 +75,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -75,14 +75,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.

View file

@ -135,14 +135,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
@ -286,11 +286,11 @@ Logging:
categories and their levels. For the root category, you don't need to categories and their levels. For the root category, you don't need to
specify a category. Default: info. specify a category. Default: info.
Security (Experimental): Security (Preview):
--fips-mode <mode> Experimental: Sets the FIPS mode. If 'enabled' is set, FIPS is enabled but on --fips-mode <mode> Preview: Sets the FIPS mode. If 'non-strict' is set, FIPS is enabled but on
non-approved mode. For full FIPS compliance, set 'strict' to run on approved non-approved mode. For full FIPS compliance, set 'strict' to run on approved
mode. Possible values are: enabled, strict, disabled. Default: disabled. mode. Possible values are: non-strict, strict. Default: disabled.
By default, this command tries to update the server configuration by running a By default, this command tries to update the server configuration by running a
'build' before starting the server. You can disable this behavior by using the 'build' before starting the server. You can disable this behavior by using the

View file

@ -135,14 +135,14 @@ Feature:
--features <feature> Enables a set of one or more features. Possible values are: account-api, --features <feature> Enables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
--features-disabled <feature> --features-disabled <feature>
Disables a set of one or more features. Possible values are: account-api, Disables a set of one or more features. Possible values are: account-api,
account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, account2, admin-api, admin-fine-grained-authz, admin2, authorization, ciba,
client-policies, client-secret-rotation, declarative-user-profile, docker, client-policies, client-secret-rotation, declarative-user-profile, docker,
dynamic-scopes, impersonation, js-adapter, kerberos, map-storage, dynamic-scopes, fips, impersonation, js-adapter, kerberos, map-storage,
openshift-integration, par, preview, recovery-codes, scripts, openshift-integration, par, preview, recovery-codes, scripts,
step-up-authentication, token-exchange, update-email, web-authn. step-up-authentication, token-exchange, update-email, web-authn.
@ -286,11 +286,11 @@ Logging:
categories and their levels. For the root category, you don't need to categories and their levels. For the root category, you don't need to
specify a category. Default: info. specify a category. Default: info.
Security (Experimental): Security (Preview):
--fips-mode <mode> Experimental: Sets the FIPS mode. If 'enabled' is set, FIPS is enabled but on --fips-mode <mode> Preview: Sets the FIPS mode. If 'non-strict' is set, FIPS is enabled but on
non-approved mode. For full FIPS compliance, set 'strict' to run on approved non-approved mode. For full FIPS compliance, set 'strict' to run on approved
mode. Possible values are: enabled, strict, disabled. Default: disabled. mode. Possible values are: non-strict, strict. Default: disabled.
By default, this command tries to update the server configuration by running a By default, this command tries to update the server configuration by running a
'build' before starting the server. You can disable this behavior by using the 'build' before starting the server. You can disable this behavior by using the

View file

@ -304,7 +304,7 @@
<profile> <profile>
<id>auth-server-fips140-2</id> <id>auth-server-fips140-2</id>
<properties> <properties>
<auth.server.fips.mode>enabled</auth.server.fips.mode> <auth.server.fips.mode>non-strict</auth.server.fips.mode>
</properties> </properties>
<dependencies> <dependencies>

View file

@ -131,7 +131,7 @@ public class AuthServerTestEnricher {
public static final String AUTH_SERVER_FIPS_MODE_PROPERTY = "auth.server.fips.mode"; public static final String AUTH_SERVER_FIPS_MODE_PROPERTY = "auth.server.fips.mode";
public static final FipsMode AUTH_SERVER_FIPS_MODE = FipsMode.valueOf(System.getProperty(AUTH_SERVER_FIPS_MODE_PROPERTY, FipsMode.disabled.toString())); public static final FipsMode AUTH_SERVER_FIPS_MODE = FipsMode.valueOfOption(System.getProperty(AUTH_SERVER_FIPS_MODE_PROPERTY, FipsMode.DISABLED.toString()));
public static final String CACHE_SERVER_LIFECYCLE_SKIP_PROPERTY = "cache.server.lifecycle.skip"; public static final String CACHE_SERVER_LIFECYCLE_SKIP_PROPERTY = "cache.server.lifecycle.skip";
public static final boolean CACHE_SERVER_LIFECYCLE_SKIP = Boolean.parseBoolean(System.getProperty(CACHE_SERVER_LIFECYCLE_SKIP_PROPERTY, "false")); public static final boolean CACHE_SERVER_LIFECYCLE_SKIP = Boolean.parseBoolean(System.getProperty(CACHE_SERVER_LIFECYCLE_SKIP_PROPERTY, "false"));

View file

@ -173,7 +173,7 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo
log.debugf("FIPS Mode: %s", configuration.getFipsMode()); log.debugf("FIPS Mode: %s", configuration.getFipsMode());
// only run build during first execution of the server (if the DB is specified), restarts or when running cluster tests // only run build during first execution of the server (if the DB is specified), restarts or when running cluster tests
if (restart.get() || shouldSetUpDb.get() || "ha".equals(getClusterConfig.get()) || configuration.getFipsMode() != FipsMode.disabled) { if (restart.get() || shouldSetUpDb.get() || "ha".equals(getClusterConfig.get()) || configuration.getFipsMode() != FipsMode.DISABLED) {
commands.removeIf("--optimized"::equals); commands.removeIf("--optimized"::equals);
commands.add("--http-relative-path=/auth"); commands.add("--http-relative-path=/auth");
@ -187,7 +187,7 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo
} }
} }
if (configuration.getFipsMode() != FipsMode.disabled) { if (configuration.getFipsMode() != FipsMode.DISABLED) {
addFipsOptions(commands); addFipsOptions(commands);
} }
} }
@ -325,6 +325,7 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo
} }
private void addFipsOptions(List<String> commands) { private void addFipsOptions(List<String> commands) {
commands.add("--features=fips");
commands.add("--fips-mode=" + configuration.getFipsMode().toString()); commands.add("--fips-mode=" + configuration.getFipsMode().toString());
log.debugf("Keystore file: %s, truststore file: %s", log.debugf("Keystore file: %s, truststore file: %s",
@ -339,7 +340,7 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo
// BCFIPS approved mode requires passwords of at least 112 bits (14 characters) to be used. To bypass this, we use this by default // BCFIPS approved mode requires passwords of at least 112 bits (14 characters) to be used. To bypass this, we use this by default
// as testsuite uses shorter passwords everywhere // as testsuite uses shorter passwords everywhere
if (FipsMode.strict == configuration.getFipsMode()) { if (FipsMode.STRICT == configuration.getFipsMode()) {
commands.add("--spi-password-hashing-pbkdf2-max-padding-length=14"); commands.add("--spi-password-hashing-pbkdf2-max-padding-length=14");
commands.add("--spi-password-hashing-pbkdf2-sha256-max-padding-length=14"); commands.add("--spi-password-hashing-pbkdf2-sha256-max-padding-length=14");
commands.add("--spi-password-hashing-pbkdf2-sha512-max-padding-length=14"); commands.add("--spi-password-hashing-pbkdf2-sha512-max-padding-length=14");

View file

@ -45,7 +45,7 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
private boolean reaugmentBeforeStart; private boolean reaugmentBeforeStart;
private String importFile = System.getProperty("migration.import.file.name"); private String importFile = System.getProperty("migration.import.file.name");
private FipsMode fipsMode = FipsMode.valueOf(System.getProperty("auth.server.fips.mode")); private FipsMode fipsMode = FipsMode.valueOfOption(System.getProperty("auth.server.fips.mode"));
@Override @Override
public void validate() throws ConfigurationException { public void validate() throws ConfigurationException {

View file

@ -75,7 +75,7 @@ public abstract class AbstractCliTest extends AbstractKeycloakTest {
} }
private boolean isFipsDisabled() { private boolean isFipsDisabled() {
return AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.disabled; return AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.DISABLED;
} }
} }

View file

@ -213,7 +213,7 @@ public class KcRegCreateTest extends AbstractRegCliTest {
} }
// TODO: SAML is not tested with FIPS enabled as it does not work. This needs to be revisited when SAML works with FIPS // TODO: SAML is not tested with FIPS enabled as it does not work. This needs to be revisited when SAML works with FIPS
if (AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.disabled) { if (AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.DISABLED) {
// test create saml formated xml - format autodetection // test create saml formated xml - format autodetection
File samlSpMetaFile = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/saml-sp-metadata.xml"); File samlSpMetaFile = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/saml-sp-metadata.xml");

View file

@ -1569,7 +1569,7 @@
<profile> <profile>
<id>auth-server-fips140-2</id> <id>auth-server-fips140-2</id>
<properties> <properties>
<auth.server.fips.mode>enabled</auth.server.fips.mode> <auth.server.fips.mode>non-strict</auth.server.fips.mode>
<auth.server.supported.keystore.types>PKCS12,BCFKS</auth.server.supported.keystore.types> <auth.server.supported.keystore.types>PKCS12,BCFKS</auth.server.supported.keystore.types>
<auth.server.kerberos.supported>false</auth.server.kerberos.supported> <auth.server.kerberos.supported>false</auth.server.kerberos.supported>