fix: adding filtering to ignore anything runtime during a build (#25434)

fix: adding filtering to ignore anything runtime during a build

closes: #25166

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Steven Hawkins 2023-12-18 07:50:47 -05:00 committed by GitHub
parent 2c341d4bc5
commit e148021a67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 24 deletions

View file

@ -66,3 +66,7 @@ mainly targeted for clients when updating or fetching any custom attribute for a
In order to resolve all the attributes including the root attributes, a new `getRawAttributes` method was added so that the resulting map also includes the root attributes. However, In order to resolve all the attributes including the root attributes, a new `getRawAttributes` method was added so that the resulting map also includes the root attributes. However,
this method is not available from the representation payload and it is targeted to be used by the server when managing user profiles. this method is not available from the representation payload and it is targeted to be used by the server when managing user profiles.
= `https-client-auth` is a build time option
Option `https-client-auth` had been treated as a run time option, however this is not supported by Quarkus. The option needs to be handled at build time instead.

View file

@ -46,6 +46,7 @@ public class HttpOptions {
.category(OptionCategory.HTTP) .category(OptionCategory.HTTP)
.description("Configures the server to require/request client authentication.") .description("Configures the server to require/request client authentication.")
.defaultValue(ClientAuth.none) .defaultValue(ClientAuth.none)
.buildTime(true)
.build(); .build();
public static final Option HTTPS_CIPHER_SUITES = new OptionBuilder<>("https-cipher-suites", String.class) public static final Option HTTPS_CIPHER_SUITES = new OptionBuilder<>("https-cipher-suites", String.class)

View file

@ -19,10 +19,18 @@ package org.keycloak.quarkus.runtime.configuration;
import io.smallrye.config.ConfigSourceInterceptor; import io.smallrye.config.ConfigSourceInterceptor;
import io.smallrye.config.ConfigSourceInterceptorContext; import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue; import io.smallrye.config.ConfigValue;
import org.apache.commons.collections4.iterators.FilterIterator;
import org.keycloak.common.util.StringPropertyReplacer; import org.keycloak.common.util.StringPropertyReplacer;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import java.util.Iterator;
import java.util.function.Function;
import static org.keycloak.quarkus.runtime.Environment.isRebuild;
/** /**
* <p>This interceptor is responsible for mapping Keycloak properties to their corresponding properties in Quarkus. * <p>This interceptor is responsible for mapping Keycloak properties to their corresponding properties in Quarkus.
* *
@ -38,6 +46,28 @@ import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
*/ */
public class PropertyMappingInterceptor implements ConfigSourceInterceptor { public class PropertyMappingInterceptor implements ConfigSourceInterceptor {
<T> Iterator<T> filterRuntime(Iterator<T> iter, Function<T, String> nameFunc) {
if (!isRebuild() && !Environment.isRebuildCheck()) {
return iter;
}
return new FilterIterator<>(iter, item -> !isRuntime(nameFunc.apply(item)));
}
static boolean isRuntime(String name) {
PropertyMapper<?> mapper = PropertyMappers.getMapper(name);
return mapper != null && mapper.isRunTime();
}
@Override
public Iterator<String> iterateNames(ConfigSourceInterceptorContext context) {
return filterRuntime(context.iterateNames(), Function.identity());
}
@Override
public Iterator<ConfigValue> iterateValues(ConfigSourceInterceptorContext context) {
return filterRuntime(context.iterateValues(), ConfigValue::getName);
}
@Override @Override
public ConfigValue getValue(ConfigSourceInterceptorContext context, String name) { public ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
ConfigValue value = PropertyMappers.getValue(context, name); ConfigValue value = PropertyMappers.getValue(context, name);

View file

@ -36,6 +36,7 @@ import org.keycloak.config.DeprecatedMetadata;
import org.keycloak.config.Option; import org.keycloak.config.Option;
import org.keycloak.config.OptionBuilder; import org.keycloak.config.OptionBuilder;
import org.keycloak.config.OptionCategory; import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider; import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
public class PropertyMapper<T> { public class PropertyMapper<T> {
@ -92,7 +93,7 @@ public class PropertyMapper<T> {
from = name.replace(to.substring(0, to.lastIndexOf('.')), from.substring(0, from.lastIndexOf(OPTION_PART_SEPARATOR_CHAR))); from = name.replace(to.substring(0, to.lastIndexOf('.')), from.substring(0, from.lastIndexOf(OPTION_PART_SEPARATOR_CHAR)));
} }
if (isRebuild() && isRunTime() && name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)) { if ((isRebuild() || Environment.isRebuildCheck()) && isRunTime()) {
// during re-aug do not resolve the server runtime properties and avoid they included by quarkus in the default value config source // during re-aug do not resolve the server runtime properties and avoid they included by quarkus in the default value config source
return ConfigValue.builder().withName(name).build(); return ConfigValue.builder().withName(name).build();
} }

View file

@ -24,6 +24,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.OPTIMIZED_BUILD_OPTION_LONG; import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.OPTIMIZED_BUILD_OPTION_LONG;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -130,16 +132,16 @@ public class QuarkusPropertiesDistTest {
void testMissingSmallRyeKeyStorePasswordProperty(LaunchResult result) { void testMissingSmallRyeKeyStorePasswordProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
cliResult.assertError("config-keystore-password must be specified"); cliResult.assertError("config-keystore-password must be specified");
cliResult.assertNoBuild();
} }
@Disabled("Ensuring config-keystore is used only at runtime removes proactive validation of the path when only the keystore is used")
@Test @Test
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false", "--config-keystore-password=secret" }) @Launch({ "start", "--http-enabled=true", "--hostname-strict=false", "--config-keystore-password=secret" })
@Order(10) @Order(10)
void testMissingSmallRyeKeyStorePathProperty(LaunchResult result) { void testMissingSmallRyeKeyStorePathProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
cliResult.assertError("config-keystore must be specified"); cliResult.assertError("config-keystore must be specified");
cliResult.assertNoBuild();
} }
@Test @Test
@ -149,7 +151,6 @@ public class QuarkusPropertiesDistTest {
void testInvalidSmallRyeKeyStorePathProperty(LaunchResult result) { void testInvalidSmallRyeKeyStorePathProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
cliResult.assertError("java.lang.IllegalArgumentException: config-keystore path does not exist: /invalid/path"); cliResult.assertError("java.lang.IllegalArgumentException: config-keystore path does not exist: /invalid/path");
cliResult.assertNoBuild();
} }
@Test @Test
@ -160,7 +161,7 @@ public class QuarkusPropertiesDistTest {
// keytool -importpass -alias kc.log-level -keystore keystore -storepass secret -storetype PKCS12 -v (with "debug" as the stored password) // keytool -importpass -alias kc.log-level -keystore keystore -storepass secret -storetype PKCS12 -v (with "debug" as the stored password)
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
assertTrue(cliResult.getOutput().contains("DEBUG")); assertTrue(cliResult.getOutput().contains("DEBUG"));
cliResult.assertBuild(); cliResult.assertStarted();
} }
@Test @Test

View file

@ -65,6 +65,9 @@ HTTP(S):
--http-relative-path <path> --http-relative-path <path>
Set the path relative to '/' for serving resources. The path must start with a Set the path relative to '/' for serving resources. The path must start with a
'/'. Default: /. '/'. Default: /.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
Health: Health:

View file

@ -65,6 +65,9 @@ HTTP(S):
--http-relative-path <path> --http-relative-path <path>
Set the path relative to '/' for serving resources. The path must start with a Set the path relative to '/' for serving resources. The path must start with a
'/'. Default: /. '/'. Default: /.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
Health: Health:
@ -81,7 +84,7 @@ Metrics:
Vault: Vault:
--vault <provider> Enables a vault provider. Possible values are: file. --vault <provider> Enables a vault provider. Possible values are: file, keystore.
Security: Security:

View file

@ -91,9 +91,6 @@ HTTP(S):
The file path to a private key in PEM format. The file path to a private key in PEM format.
--https-cipher-suites <ciphers> --https-cipher-suites <ciphers>
The cipher suites to use. If none is given, a reasonable default is selected. The cipher suites to use. If none is given, a reasonable default is selected.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
--https-key-store-file <file> --https-key-store-file <file>
The key store which holds the certificate information instead of specifying The key store which holds the certificate information instead of specifying
separate files. separate files.

View file

@ -17,6 +17,8 @@ Options:
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>
@ -38,8 +40,10 @@ Database:
--db-url-port <port> Sets the port of the default JDBC URL of the chosen vendor. If the `db-url` --db-url-port <port> Sets the port of the default JDBC URL of the chosen vendor. If the `db-url`
option is set, this option is ignored. option is set, this option is ignored.
--db-url-properties <properties> --db-url-properties <properties>
Sets the properties of the default JDBC URL of the chosen vendor. If the Sets the properties of the default JDBC URL of the chosen vendor. Make sure to
`db-url` option is set, this option is ignored. set the properties accordingly to the format expected by the database
vendor, as well as appending the right character at the beginning of this
property value. If the `db-url` option is set, this option is ignored.
--db-username <username> --db-username <username>
The username of the database user. The username of the database user.
@ -54,6 +58,9 @@ Hostname:
--hostname-admin-url <url> --hostname-admin-url <url>
Set the base URL for accessing the administration console, including scheme, Set the base URL for accessing the administration console, including scheme,
host, port and path host, port and path
--hostname-debug <true|false>
Toggle the hostname debug page that is accessible at
/realms/master/hostname-debug Default: false.
--hostname-path <path> --hostname-path <path>
This should be set if proxy uses a different context-path for Keycloak. This should be set if proxy uses a different context-path for Keycloak.
--hostname-port <port> --hostname-port <port>
@ -84,9 +91,6 @@ HTTP(S):
The file path to a private key in PEM format. The file path to a private key in PEM format.
--https-cipher-suites <ciphers> --https-cipher-suites <ciphers>
The cipher suites to use. If none is given, a reasonable default is selected. The cipher suites to use. If none is given, a reasonable default is selected.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
--https-key-store-file <file> --https-key-store-file <file>
The key store which holds the certificate information instead of specifying The key store which holds the certificate information instead of specifying
separate files. separate files.
@ -112,6 +116,15 @@ HTTP(S):
'strict' and no value is set, it defaults to 'BCFKS'. Use the System 'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details. Truststore instead, see the docs for details.
Config:
--config-keystore <config-keystore>
Specifies a path to the KeyStore Configuration Source.
--config-keystore-password <config-keystore-password>
Specifies a password to the KeyStore Configuration Source.
--config-keystore-type <config-keystore-type>
Specifies a type of the KeyStore Configuration Source. Default: PKCS12.
Proxy: Proxy:
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a --proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
@ -126,6 +139,9 @@ Vault:
--vault-dir <dir> If set, secrets can be obtained by reading the content of files within the --vault-dir <dir> If set, secrets can be obtained by reading the content of files within the
given directory. given directory.
--vault-file <file> Path to the keystore file.
--vault-pass <pass> Password for the vault keystore.
--vault-type <type> Specifies the type of the keystore file. Default: PKCS12.
Logging: Logging:

View file

@ -91,9 +91,6 @@ HTTP(S):
The file path to a private key in PEM format. The file path to a private key in PEM format.
--https-cipher-suites <ciphers> --https-cipher-suites <ciphers>
The cipher suites to use. If none is given, a reasonable default is selected. The cipher suites to use. If none is given, a reasonable default is selected.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
--https-key-store-file <file> --https-key-store-file <file>
The key store which holds the certificate information instead of specifying The key store which holds the certificate information instead of specifying
separate files. separate files.

View file

@ -17,6 +17,8 @@ Options:
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>
@ -38,8 +40,10 @@ Database:
--db-url-port <port> Sets the port of the default JDBC URL of the chosen vendor. If the `db-url` --db-url-port <port> Sets the port of the default JDBC URL of the chosen vendor. If the `db-url`
option is set, this option is ignored. option is set, this option is ignored.
--db-url-properties <properties> --db-url-properties <properties>
Sets the properties of the default JDBC URL of the chosen vendor. If the Sets the properties of the default JDBC URL of the chosen vendor. Make sure to
`db-url` option is set, this option is ignored. set the properties accordingly to the format expected by the database
vendor, as well as appending the right character at the beginning of this
property value. If the `db-url` option is set, this option is ignored.
--db-username <username> --db-username <username>
The username of the database user. The username of the database user.
@ -54,6 +58,9 @@ Hostname:
--hostname-admin-url <url> --hostname-admin-url <url>
Set the base URL for accessing the administration console, including scheme, Set the base URL for accessing the administration console, including scheme,
host, port and path host, port and path
--hostname-debug <true|false>
Toggle the hostname debug page that is accessible at
/realms/master/hostname-debug Default: false.
--hostname-path <path> --hostname-path <path>
This should be set if proxy uses a different context-path for Keycloak. This should be set if proxy uses a different context-path for Keycloak.
--hostname-port <port> --hostname-port <port>
@ -84,9 +91,6 @@ HTTP(S):
The file path to a private key in PEM format. The file path to a private key in PEM format.
--https-cipher-suites <ciphers> --https-cipher-suites <ciphers>
The cipher suites to use. If none is given, a reasonable default is selected. The cipher suites to use. If none is given, a reasonable default is selected.
--https-client-auth <auth>
Configures the server to require/request client authentication. Possible
values are: none, request, required. Default: none.
--https-key-store-file <file> --https-key-store-file <file>
The key store which holds the certificate information instead of specifying The key store which holds the certificate information instead of specifying
separate files. separate files.
@ -112,6 +116,15 @@ HTTP(S):
'strict' and no value is set, it defaults to 'BCFKS'. Use the System 'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details. Truststore instead, see the docs for details.
Config:
--config-keystore <config-keystore>
Specifies a path to the KeyStore Configuration Source.
--config-keystore-password <config-keystore-password>
Specifies a password to the KeyStore Configuration Source.
--config-keystore-type <config-keystore-type>
Specifies a type of the KeyStore Configuration Source. Default: PKCS12.
Proxy: Proxy:
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a --proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
@ -126,6 +139,9 @@ Vault:
--vault-dir <dir> If set, secrets can be obtained by reading the content of files within the --vault-dir <dir> If set, secrets can be obtained by reading the content of files within the
given directory. given directory.
--vault-file <file> Path to the keystore file.
--vault-pass <pass> Password for the vault keystore.
--vault-type <type> Specifies the type of the keystore file. Default: PKCS12.
Logging: Logging: