fix: fail to start if the admin user can't be added (#31207)
also allowing the bootstrap options to be used by the cli, which requires hidden options to stay hidden and a minor refactoring for clarity closes: #31160 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
14a9927e29
commit
d970521415
12 changed files with 43 additions and 112 deletions
|
@ -157,10 +157,14 @@ public final class Help extends CommandLine.Help {
|
|||
}
|
||||
|
||||
private boolean isVisible(OptionSpec option) {
|
||||
if (option.description().length == 0) {
|
||||
// do not show options without a description
|
||||
if (option.description().length == 0 || option.hidden()) {
|
||||
// do not show options without a description nor hidden
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ALL_OPTIONS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String optionName = undecorateDuplicitOptionName(option.longestName());
|
||||
|
||||
|
@ -172,30 +176,13 @@ public final class Help extends CommandLine.Help {
|
|||
|
||||
if (mapper == null) {
|
||||
final var disabledMapper = PropertyMappers.getDisabledMapper(optionName);
|
||||
final var isDisabledMapper = disabledMapper.isPresent();
|
||||
|
||||
|
||||
// Show disabled mappers, which do not have a description when they're enabled
|
||||
final var isEnabledWhenEmpty = isDisabledMapper && disabledMapper.get().getEnabledWhen().isEmpty();
|
||||
if (isEnabledWhenEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ALL_OPTIONS && isDisabledMapper) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// only filter mapped options, defaults to the hidden marker
|
||||
return !option.hidden() && !isDisabledMapper;
|
||||
return disabledMapper.flatMap(PropertyMapper::getEnabledWhen).isEmpty();
|
||||
}
|
||||
|
||||
boolean isUnsupportedOption = !PropertyMappers.isSupported(mapper);
|
||||
|
||||
if (isUnsupportedOption) {
|
||||
// unsupported options removed from help if all options are not requested
|
||||
return !option.hidden() && ALL_OPTIONS;
|
||||
}
|
||||
|
||||
return !option.hidden();
|
||||
// unsupported options removed from help if all options are not requested
|
||||
return PropertyMappers.isSupported(mapper);
|
||||
}
|
||||
|
||||
public static void setAllOptions(boolean allOptions) {
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
package org.keycloak.quarkus.runtime.cli.command;
|
||||
|
||||
import org.keycloak.common.util.IoUtils;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.quarkus.runtime.cli.PropertyException;
|
||||
import org.keycloak.quarkus.runtime.integration.jaxrs.QuarkusKeycloakApplication;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
||||
import picocli.CommandLine.ArgGroup;
|
||||
import picocli.CommandLine.Command;
|
||||
|
@ -97,7 +100,9 @@ public class BootstrapAdminService extends AbstractNonServerCommand {
|
|||
@Override
|
||||
public void onStart(QuarkusKeycloakApplication application) {
|
||||
//BootstrapAdmin bootstrap = spec.commandLine().getParent().getCommand();
|
||||
application.createTemporaryMasterRealmAdminService(clientId, clientSecret, /*bootstrap.expiration,*/ null);
|
||||
KeycloakSessionFactory sessionFactory = KeycloakApplication.getSessionFactory();
|
||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> application
|
||||
.createTemporaryMasterRealmAdminService(clientId, clientSecret, /* bootstrap.expiration, */ session));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
package org.keycloak.quarkus.runtime.cli.command;
|
||||
|
||||
import org.keycloak.common.util.IoUtils;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.quarkus.runtime.cli.PropertyException;
|
||||
import org.keycloak.quarkus.runtime.integration.jaxrs.QuarkusKeycloakApplication;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
||||
import picocli.CommandLine.ArgGroup;
|
||||
import picocli.CommandLine.Command;
|
||||
|
@ -97,7 +100,9 @@ public class BootstrapAdminUser extends AbstractNonServerCommand {
|
|||
@Override
|
||||
public void onStart(QuarkusKeycloakApplication application) {
|
||||
//BootstrapAdmin bootstrap = spec.commandLine().getParent().getCommand();
|
||||
application.createTemporaryMasterRealmAdminUser(username, password, /*bootstrap.expiration,*/ null);
|
||||
KeycloakSessionFactory sessionFactory = KeycloakApplication.getSessionFactory();
|
||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> application
|
||||
.createTemporaryMasterRealmAdminUser(username, password, /* bootstrap.expiration, */ session));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ public final class PropertyMappers {
|
|||
MAPPERS.addAll(ExportPropertyMappers.getMappers());
|
||||
MAPPERS.addAll(ImportPropertyMappers.getMappers());
|
||||
MAPPERS.addAll(TruststorePropertyMappers.getMappers());
|
||||
MAPPERS.addAll(BootstrapAdminPropertyMappers.getMappers());
|
||||
}
|
||||
|
||||
public static ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
|
||||
|
|
|
@ -98,33 +98,12 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
|
|||
}
|
||||
}
|
||||
|
||||
public void createTemporaryMasterRealmAdminUser(String adminUserName, String adminPassword, /*Integer adminExpiration,*/ KeycloakSession existingSession) {
|
||||
KeycloakSessionTask task = session -> {
|
||||
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminUser(adminUserName, adminPassword /*, adminExpiration*/, false);
|
||||
};
|
||||
|
||||
runAdminTask(adminUserName, existingSession, task);
|
||||
public void createTemporaryMasterRealmAdminUser(String adminUserName, String adminPassword, /*Integer adminExpiration,*/ KeycloakSession session) {
|
||||
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminUser(adminUserName, adminPassword /*, adminExpiration*/, false);
|
||||
}
|
||||
|
||||
public void createTemporaryMasterRealmAdminService(String clientId, String clientSecret, /*Integer adminExpiration,*/ KeycloakSession existingSession) {
|
||||
KeycloakSessionTask task = session -> {
|
||||
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminService(clientId, clientSecret /*, adminExpiration*/);
|
||||
};
|
||||
|
||||
runAdminTask(clientId, existingSession, task);
|
||||
}
|
||||
|
||||
private void runAdminTask(String adminUserName, KeycloakSession existingSession, KeycloakSessionTask task) {
|
||||
try {
|
||||
if (existingSession == null) {
|
||||
KeycloakSessionFactory sessionFactory = KeycloakApplication.getSessionFactory();
|
||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, task);
|
||||
} else {
|
||||
task.run(existingSession);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ServicesLogger.LOGGER.addUserFailed(t, adminUserName, Config.getAdminRealm());
|
||||
}
|
||||
public void createTemporaryMasterRealmAdminService(String clientId, String clientSecret, /*Integer adminExpiration,*/ KeycloakSession session) {
|
||||
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminService(clientId, clientSecret /*, adminExpiration*/);
|
||||
}
|
||||
|
||||
private String getEnvOrProp(String envKey, String propKey) {
|
||||
|
|
|
@ -63,6 +63,13 @@ public class BootstrapAdminDistTest {
|
|||
void createAdmin(LaunchResult result) {
|
||||
assertTrue(result.getErrorOutput().isEmpty(), result.getErrorOutput());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--bootstrap-admin-password=MY_PASSWORD" })
|
||||
void createAdminWithCliOptions(LaunchResult result) {
|
||||
assertTrue(result.getErrorOutput().isEmpty(), result.getErrorOutput());
|
||||
result.getOutput().contains("Created temporary admin user with username temp-admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "bootstrap-admin", "service", "--no-prompt" })
|
||||
|
|
|
@ -48,30 +48,19 @@ public class FipsDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testFipsApprovedModePasswordFails(KeycloakDistribution dist) {
|
||||
void testFipsApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", "admin");
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "admin");
|
||||
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict");
|
||||
cliResult.assertStarted();
|
||||
cliResult.assertMessage(
|
||||
"org.bouncycastle.crypto.fips.FipsUnapprovedOperationError: password must be at least 112 bits");
|
||||
cliResult.assertMessage("password must be at least 112 bits");
|
||||
cliResult.assertMessage("Java security providers: [ \n"
|
||||
+ " KC(" + BCFIPS_VERSION + " Approved Mode, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFipsApprovedModePasswordSucceeds(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", "admin");
|
||||
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "adminadminadmin");
|
||||
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict");
|
||||
cliResult = dist.run("start", "--fips-mode=strict");
|
||||
cliResult.assertStarted();
|
||||
cliResult.assertMessage("Java security providers: [ \n"
|
||||
+ " KC(" + BCFIPS_VERSION + " Approved Mode, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
cliResult.assertMessage("Created temporary admin user with username admin");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -171,16 +171,10 @@ Logging:
|
|||
DEPRECATED. Set the format for the GELF timestamp field. Uses Java
|
||||
SimpleDateFormat pattern. Default: yyyy-MM-dd HH:mm:ss,SSS. Available only
|
||||
when GELF is activated.
|
||||
--log-gelf-version <version>
|
||||
The GELF version to be used. Possible values are: 1.0, 1.1. Default: 1.1.
|
||||
Available only when GELF is activated.
|
||||
--log-level <category:level>
|
||||
The log level of the root category or a comma-separated list of individual
|
||||
categories and their levels. For the root category, you don't need to
|
||||
specify a category. Default: info.
|
||||
--log-syslog-app-name <name>
|
||||
The app name used when formatting the message in RFC5424 format. Default:
|
||||
keycloak. Available only when Syslog is activated.
|
||||
--log-syslog-endpoint <host:port>
|
||||
The IP address and port of the syslog server. Default: localhost:514.
|
||||
Available only when Syslog is activated.
|
||||
|
@ -217,4 +211,4 @@ Export:
|
|||
--users-per-file <number>
|
||||
Set the number of users per file. It is used only if 'users' is set to
|
||||
'different_files'. Increasing this number leads to exponentially increasing
|
||||
export times. Default: 50.
|
||||
export times. Default: 50.
|
|
@ -171,16 +171,10 @@ Logging:
|
|||
DEPRECATED. Set the format for the GELF timestamp field. Uses Java
|
||||
SimpleDateFormat pattern. Default: yyyy-MM-dd HH:mm:ss,SSS. Available only
|
||||
when GELF is activated.
|
||||
--log-gelf-version <version>
|
||||
The GELF version to be used. Possible values are: 1.0, 1.1. Default: 1.1.
|
||||
Available only when GELF is activated.
|
||||
--log-level <category:level>
|
||||
The log level of the root category or a comma-separated list of individual
|
||||
categories and their levels. For the root category, you don't need to
|
||||
specify a category. Default: info.
|
||||
--log-syslog-app-name <name>
|
||||
The app name used when formatting the message in RFC5424 format. Default:
|
||||
keycloak. Available only when Syslog is activated.
|
||||
--log-syslog-endpoint <host:port>
|
||||
The IP address and port of the syslog server. Default: localhost:514.
|
||||
Available only when Syslog is activated.
|
||||
|
@ -211,4 +205,4 @@ Import:
|
|||
--file <file> Set the path to a file that will be read.
|
||||
--override <true|false>
|
||||
Set if existing data should be overwritten. If set to false, data will be
|
||||
ignored. Default: true.
|
||||
ignored. Default: true.
|
|
@ -191,10 +191,6 @@ Hostname v1 (Deprecated):
|
|||
headers to allow internal and external applications. If all applications use
|
||||
the public URL this option should be enabled. Default: false. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-strict-https <true|false>
|
||||
DEPRECATED. Forces frontend URLs to use the 'https' scheme. If set to false,
|
||||
the HTTP scheme is inferred from requests. Default: true. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-url <url> DEPRECATED. Set the base URL for frontend URLs, including scheme, host, port
|
||||
and path. Available only when hostname:v1 feature is enabled.
|
||||
|
||||
|
@ -385,16 +381,10 @@ Logging:
|
|||
DEPRECATED. Set the format for the GELF timestamp field. Uses Java
|
||||
SimpleDateFormat pattern. Default: yyyy-MM-dd HH:mm:ss,SSS. Available only
|
||||
when GELF is activated.
|
||||
--log-gelf-version <version>
|
||||
The GELF version to be used. Possible values are: 1.0, 1.1. Default: 1.1.
|
||||
Available only when GELF is activated.
|
||||
--log-level <category:level>
|
||||
The log level of the root category or a comma-separated list of individual
|
||||
categories and their levels. For the root category, you don't need to
|
||||
specify a category. Default: info.
|
||||
--log-syslog-app-name <name>
|
||||
The app name used when formatting the message in RFC5424 format. Default:
|
||||
keycloak. Available only when Syslog is activated.
|
||||
--log-syslog-endpoint <host:port>
|
||||
The IP address and port of the syslog server. Default: localhost:514.
|
||||
Available only when Syslog is activated.
|
||||
|
@ -431,4 +421,4 @@ Security:
|
|||
Do NOT start the server using this command when deploying to production.
|
||||
|
||||
Use 'kc.sh start-dev --help-all' to list all available options, including build
|
||||
options.
|
||||
options.
|
|
@ -192,10 +192,6 @@ Hostname v1 (Deprecated):
|
|||
headers to allow internal and external applications. If all applications use
|
||||
the public URL this option should be enabled. Default: false. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-strict-https <true|false>
|
||||
DEPRECATED. Forces frontend URLs to use the 'https' scheme. If set to false,
|
||||
the HTTP scheme is inferred from requests. Default: true. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-url <url> DEPRECATED. Set the base URL for frontend URLs, including scheme, host, port
|
||||
and path. Available only when hostname:v1 feature is enabled.
|
||||
|
||||
|
@ -386,16 +382,10 @@ Logging:
|
|||
DEPRECATED. Set the format for the GELF timestamp field. Uses Java
|
||||
SimpleDateFormat pattern. Default: yyyy-MM-dd HH:mm:ss,SSS. Available only
|
||||
when GELF is activated.
|
||||
--log-gelf-version <version>
|
||||
The GELF version to be used. Possible values are: 1.0, 1.1. Default: 1.1.
|
||||
Available only when GELF is activated.
|
||||
--log-level <category:level>
|
||||
The log level of the root category or a comma-separated list of individual
|
||||
categories and their levels. For the root category, you don't need to
|
||||
specify a category. Default: info.
|
||||
--log-syslog-app-name <name>
|
||||
The app name used when formatting the message in RFC5424 format. Default:
|
||||
keycloak. Available only when Syslog is activated.
|
||||
--log-syslog-endpoint <host:port>
|
||||
The IP address and port of the syslog server. Default: localhost:514.
|
||||
Available only when Syslog is activated.
|
||||
|
@ -436,4 +426,4 @@ By default, this command tries to update the server configuration by running a
|
|||
$ kc.sh start '--optimized'
|
||||
|
||||
By doing that, the server should start faster based on any previous
|
||||
configuration you have set when manually running the 'build' command.
|
||||
configuration you have set when manually running the 'build' command.
|
|
@ -177,10 +177,6 @@ Hostname v1 (Deprecated):
|
|||
headers to allow internal and external applications. If all applications use
|
||||
the public URL this option should be enabled. Default: false. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-strict-https <true|false>
|
||||
DEPRECATED. Forces frontend URLs to use the 'https' scheme. If set to false,
|
||||
the HTTP scheme is inferred from requests. Default: true. Available only
|
||||
when hostname:v1 feature is enabled.
|
||||
--hostname-url <url> DEPRECATED. Set the base URL for frontend URLs, including scheme, host, port
|
||||
and path. Available only when hostname:v1 feature is enabled.
|
||||
|
||||
|
@ -337,16 +333,10 @@ Logging:
|
|||
DEPRECATED. Set the format for the GELF timestamp field. Uses Java
|
||||
SimpleDateFormat pattern. Default: yyyy-MM-dd HH:mm:ss,SSS. Available only
|
||||
when GELF is activated.
|
||||
--log-gelf-version <version>
|
||||
The GELF version to be used. Possible values are: 1.0, 1.1. Default: 1.1.
|
||||
Available only when GELF is activated.
|
||||
--log-level <category:level>
|
||||
The log level of the root category or a comma-separated list of individual
|
||||
categories and their levels. For the root category, you don't need to
|
||||
specify a category. Default: info.
|
||||
--log-syslog-app-name <name>
|
||||
The app name used when formatting the message in RFC5424 format. Default:
|
||||
keycloak. Available only when Syslog is activated.
|
||||
--log-syslog-endpoint <host:port>
|
||||
The IP address and port of the syslog server. Default: localhost:514.
|
||||
Available only when Syslog is activated.
|
||||
|
@ -378,4 +368,4 @@ By default, this command tries to update the server configuration by running a
|
|||
$ kc.sh start '--optimized'
|
||||
|
||||
By doing that, the server should start faster based on any previous
|
||||
configuration you have set when manually running the 'build' command.
|
||||
configuration you have set when manually running the 'build' command.
|
Loading…
Reference in a new issue