Make it possible to run the embedded distribution in FIPS mode
Closes keycloak#16962
This commit is contained in:
parent
782a145e14
commit
22e256149c
|
@ -23,13 +23,13 @@ public class HttpOptions {
|
|||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option HTTP_PORT = new OptionBuilder<>("http-port", Integer.class)
|
||||
public static final Option<Integer> HTTP_PORT = new OptionBuilder<>("http-port", Integer.class)
|
||||
.category(OptionCategory.HTTP)
|
||||
.description("The used HTTP port.")
|
||||
.defaultValue(8080)
|
||||
.build();
|
||||
|
||||
public static final Option HTTPS_PORT = new OptionBuilder<>("https-port", Integer.class)
|
||||
public static final Option<Integer> HTTPS_PORT = new OptionBuilder<>("https-port", Integer.class)
|
||||
.category(OptionCategory.HTTP)
|
||||
.description("The used HTTPS port.")
|
||||
.defaultValue(8443)
|
||||
|
|
|
@ -32,6 +32,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
import io.quarkus.runtime.LaunchMode;
|
||||
import io.quarkus.runtime.configuration.ProfileManager;
|
||||
import io.smallrye.config.SmallRyeConfig;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
|
||||
|
||||
|
@ -108,6 +110,7 @@ public final class Environment {
|
|||
public static void setProfile(String profile) {
|
||||
System.setProperty(PROFILE, profile);
|
||||
System.setProperty(ProfileManager.QUARKUS_PROFILE_PROP, profile);
|
||||
System.setProperty(SmallRyeConfig.SMALLRYE_CONFIG_PROFILE, profile);
|
||||
if (isTestLaunchMode()) {
|
||||
System.setProperty("mp.config.profile", profile);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.keycloak;
|
||||
|
||||
import static java.util.concurrent.CompletableFuture.runAsync;
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -27,9 +27,17 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
|
||||
import org.keycloak.common.Version;
|
||||
import org.keycloak.common.crypto.FipsMode;
|
||||
import org.keycloak.config.HttpOptions;
|
||||
import org.keycloak.config.LoggingOptions;
|
||||
import org.keycloak.config.Option;
|
||||
import org.keycloak.config.SecurityOptions;
|
||||
import org.keycloak.config.StorageOptions;
|
||||
import org.keycloak.platform.Platform;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.Picocli;
|
||||
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||
|
||||
import io.quarkus.bootstrap.app.AugmentAction;
|
||||
import io.quarkus.bootstrap.app.CuratedApplication;
|
||||
|
@ -49,6 +57,17 @@ import io.quarkus.runtime.configuration.QuarkusConfigFactory;
|
|||
|
||||
public class Keycloak {
|
||||
|
||||
static {
|
||||
System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager");
|
||||
System.setProperty("quarkus.http.test-port", "${kc.http-port}");
|
||||
System.setProperty("quarkus.http.test-ssl-port", "${kc.https-port}");
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
Keycloak.builder().start(args);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String version;
|
||||
|
@ -88,11 +107,75 @@ public class Keycloak {
|
|||
return start(List.of(args));
|
||||
}
|
||||
|
||||
public Keycloak start(List<String> args) {
|
||||
public Keycloak start(List<String> rawArgs) {
|
||||
if (homeDir == null) {
|
||||
homeDir = Platform.getPlatform().getTmpDirectory().toPath();
|
||||
}
|
||||
return new Keycloak(homeDir, version, dependencies).start(args);
|
||||
|
||||
List<String> args = new ArrayList<>(rawArgs);
|
||||
|
||||
addOptionIfNotSet(args, HttpOptions.HTTP_ENABLED, true);
|
||||
addOptionIfNotSet(args, HttpOptions.HTTP_PORT);
|
||||
addOptionIfNotSet(args, HttpOptions.HTTPS_PORT);
|
||||
addOptionIfNotSet(args, StorageOptions.STORAGE, StorageOptions.StorageType.chm);
|
||||
|
||||
boolean isFipsEnabled = ofNullable(getOptionValue(args, SecurityOptions.FIPS_MODE)).orElse(FipsMode.disabled).isFipsEnabled();
|
||||
|
||||
if (isFipsEnabled) {
|
||||
String logLevel = getOptionValue(args, LoggingOptions.LOG_LEVEL);
|
||||
|
||||
if (logLevel == null) {
|
||||
args.add("--log-level=org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE");
|
||||
}
|
||||
}
|
||||
|
||||
return new Keycloak(homeDir, version, dependencies, isFipsEnabled).start(args);
|
||||
}
|
||||
|
||||
private <T> void addOptionIfNotSet(List<String> args, Option<T> option) {
|
||||
addOptionIfNotSet(args, option, null);
|
||||
}
|
||||
|
||||
private <T> void addOptionIfNotSet(List<String> args, Option<T> option, T defaultValue) {
|
||||
T value = getOptionValue(args, option);
|
||||
|
||||
if (value == null) {
|
||||
defaultValue = ofNullable(defaultValue).orElseGet(option.getDefaultValue()::get);
|
||||
args.add(Configuration.toCliFormat(option.getKey()) + "=" + defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T getOptionValue(List<String> args, Option<T> option) {
|
||||
for (String arg : args) {
|
||||
if (arg.contains(option.getKey())) {
|
||||
if (arg.endsWith(option.getKey())) {
|
||||
throw new IllegalArgumentException("Option '" + arg + "' value must be set using '=' as a separator");
|
||||
}
|
||||
|
||||
String value = arg.substring(Picocli.ARG_PREFIX.length() + option.getKey().length() + 1);
|
||||
Class<T> type = option.getType();
|
||||
|
||||
if (type.equals(String.class)) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
if (type.isEnum()) {
|
||||
return (T) Enum.valueOf((Class<Enum>) type, value);
|
||||
}
|
||||
|
||||
if (Integer.class.isAssignableFrom(type)) {
|
||||
return (T) Integer.valueOf(value);
|
||||
}
|
||||
|
||||
if (Boolean.class.isAssignableFrom(type)) {
|
||||
return (T) Boolean.valueOf(value);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unsupported option type '" + type + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,14 +187,16 @@ public class Keycloak {
|
|||
private ApplicationModel applicationModel;
|
||||
private Path homeDir;
|
||||
private List<Dependency> dependencies;
|
||||
private boolean fipsEnabled;
|
||||
|
||||
public Keycloak() {
|
||||
this(null, Version.VERSION, List.of());
|
||||
this(null, Version.VERSION, List.of(), false);
|
||||
}
|
||||
|
||||
public Keycloak(Path homeDir, String version, List<Dependency> dependencies) {
|
||||
public Keycloak(Path homeDir, String version, List<Dependency> dependencies, boolean fipsEnabled) {
|
||||
this.homeDir = homeDir;
|
||||
this.dependencies = dependencies;
|
||||
this.fipsEnabled = fipsEnabled;
|
||||
try {
|
||||
applicationModel = createApplicationModel(version);
|
||||
} catch (Exception e) {
|
||||
|
@ -131,7 +216,6 @@ public class Keycloak {
|
|||
AugmentAction action = curated.createAugmentor();
|
||||
Environment.setHomeDir(homeDir);
|
||||
ConfigArgsConfigSource.setCliArgs(args.toArray(new String[0]));
|
||||
|
||||
StartupAction startupAction = action.createInitialRuntimeApplication();
|
||||
|
||||
application = startupAction.runMainClass(args.toArray(new String[0]));
|
||||
|
@ -162,20 +246,33 @@ public class Keycloak {
|
|||
|
||||
private WorkspaceModule createWorkspaceModule(String keycloakVersion) {
|
||||
Path moduleDir = createModuleDir();
|
||||
DependencyBuilder serverDependency = DependencyBuilder.newInstance()
|
||||
.setGroupId("org.keycloak")
|
||||
.setArtifactId("keycloak-quarkus-server")
|
||||
.setVersion(keycloakVersion)
|
||||
.addExclusion("org.jboss.logmanager", "log4j-jboss-logmanager");
|
||||
|
||||
if (fipsEnabled) {
|
||||
serverDependency.addExclusion("org.bouncycastle", "bcprov-jdk15on");
|
||||
serverDependency.addExclusion("org.bouncycastle", "bcpkix-jdk15on");
|
||||
serverDependency.addExclusion("org.keycloak", "keycloak-crypto-default");
|
||||
} else {
|
||||
serverDependency.addExclusion("org.keycloak", "keycloak-crypto-fips1402");
|
||||
}
|
||||
|
||||
WorkspaceModule.Mutable builder = WorkspaceModule.builder()
|
||||
.setModuleId(WorkspaceModuleId.of("io.playground", "keycloak-app", "1"))
|
||||
.setModuleId(WorkspaceModuleId.of("org.keycloak", "keycloak-embedded", "1"))
|
||||
.setModuleDir(moduleDir)
|
||||
.setBuildDir(moduleDir)
|
||||
.addDependencyConstraint(
|
||||
Dependency.pomImport("org.keycloak", "keycloak-quarkus-parent", keycloakVersion))
|
||||
.addDependency(DependencyBuilder.newInstance()
|
||||
.setGroupId("org.keycloak")
|
||||
.setArtifactId("keycloak-quarkus-server-app")
|
||||
.setVersion(keycloakVersion)
|
||||
.addExclusion("org.jboss.logmanager", "log4j-jboss-logmanager")
|
||||
.addExclusion("org.keycloak", "keycloak-crypto-fips1402") //TODO: enable fips
|
||||
.build());
|
||||
.addDependency(serverDependency.build());
|
||||
|
||||
if (fipsEnabled) {
|
||||
builder.addDependency(Dependency.of("org.bouncycastle", "bc-fips"));
|
||||
builder.addDependency(Dependency.of("org.bouncycastle", "bctls-fips"));
|
||||
builder.addDependency(Dependency.of("org.bouncycastle", "bcpkix-fips"));
|
||||
}
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
builder.addDependency(dependency);
|
||||
|
|
Loading…
Reference in New Issue