Add new --proxy-headers option (#25178)

* Add new `--proxy-headers` option

Closes #23431

Signed-off-by: Václav Muzikář <vmuzikar@redhat.com>

Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Co-authored-by: Alexander Schwartz <aschwart@redhat.com>

* Address review comments vol. 03

Signed-off-by: Václav Muzikář <vmuzikar@redhat.com>

* Address review comments vol. 04

Signed-off-by: Václav Muzikář <vmuzikar@redhat.com>

---------

Signed-off-by: Václav Muzikář <vmuzikar@redhat.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Václav Muzikář 2023-12-13 14:48:12 +01:00 committed by GitHub
parent 0cf1e88f60
commit e4c348e99e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 564 additions and 179 deletions

View file

@ -29,6 +29,12 @@ Proceed to https://www.keycloak.org/server/features[Enabling and disabling featu
The Keycloak CR now includes an `startOptimized` field, which may be used to override the default assumption about whether to use the `--optimized` flag for the start command.
As a result, you can use the CR to configure build time options also when a custom Keycloak image is used.
= Enhanced reverse proxy settings
It is now possible to separately enable parsing of either `Forwarded` or `X-Forwarded-*` headers via the new `--proxy-headers` option.
For details consult the https://www.keycloak.org/server/reverseproxy[Reverse Proxy Guide].
The original `--proxy` option is now deprecated and will be removed in a future release. For migration instructions consult the link:{upgradingguide_link}[{upgradingguide_name}].
= Breaking changes to the User Profile SPI
In this release, there are changes to the User Profile SPI that might impact existing implementations based on this SPI. For more details, check the

View file

@ -19,6 +19,29 @@ The `spi-truststore-file-*` options and the truststore related options `https-tr
The `tls-hostname-verifier` property should be used instead of the `spi-truststore-file-hostname-verification-policy` property.
= Deprecated `--proxy` option
The `--proxy` option has been deprecated and will be removed in a future release. The following table explains how the deprecated option maps to supported options.
[%autowidth,cols="a,a"]
|===
| Deprecated usage | New usage
|`kc.sh` (no `proxy` option set)
|`kc.sh`
|`kc.sh --proxy none`
|`kc.sh`
|`kc.sh --proxy edge`
|`kc.sh --proxy-headers forwarded\|xforwarded --http-enabled true`
|`kc.sh --proxy passthrough`
|`kc.sh --hostname-port 80\|443` (depending if HTTPS is used)
|`kc.sh --proxy reencrypt`
|`kc.sh --proxy-headers forwarded\|xforwarded`
|===
NOTE: For hardened security, the `--proxy-headers` option does not allow selecting both `forwarded` and `xforwarded` values at the same time (as it was
the case before for `--proxy edge` and `--proxy reencrypt`).
= Breaking changes to the User Profile SPI
If you are using the User Profile SPI in your extension, you might be impacted by the API changes introduced in this release.

View file

@ -40,7 +40,7 @@ Most of the time, it should be enough to set the `hostname` option in order to c
When using the `hostname` option the server is going to resolve the HTTP scheme, port, and path, automatically so that:
* `https` scheme is used unless you set `hostname-strict-https=false`
* if the `proxy` option is set, the proxy will use the default ports (i.e.: 80 and 443). If the proxy uses a different port, it needs to be specified via the `hostname-port` configuration option
* if the `proxy-headers` option is set, the proxy will use the default ports (i.e.: 80 and 443). If the proxy uses a different port, it needs to be specified via the `hostname-url` configuration option
However, if you want to set not only the host but also a scheme, port, and path, you can set the `hostname-url` option:
@ -51,7 +51,7 @@ the `hostname` and `hostname-url` are mutually exclusive.
[NOTE]
====
By `hostname` and `proxy` configuration options you affect only the static resources URLs, redirect URIs, OIDC well-known endpoints, etc. In order to change, where/on which port the server actually listens on, you need to use the `http/tls` configuration options (e.g. `http-host`, `https-port`, etc.). For more details, see <@links.server id="enabletls"/> and <@links.server id="all-config"/>.
By `hostname` and `proxy-headers` configuration options you affect only the static resources URLs, redirect URIs, OIDC well-known endpoints, etc. In order to change, where/on which port the server actually listens on, you need to use the `http/tls` configuration options (e.g. `http-host`, `https-port`, etc.). For more details, see <@links.server id="enabletls"/> and <@links.server id="all-config"/>.
====
=== Backend
@ -101,7 +101,7 @@ Note that the `start` command requires setting up TLS. The corresponding options
In this example, the server is running behind a TLS termination proxy and publicly available from `https://mykeycloak`.
.Configuration:
<@kc.start parameters="--hostname=mykeycloak --proxy=edge"/>
<@kc.start parameters="--hostname=mykeycloak --http-enabled=true --proxy-headers=forwarded|xforwarded"/>
=== Exposing the server without a proxy
@ -130,14 +130,12 @@ In this example, the server is accessible using a port other than the default po
=== Exposing {project_name} behind a TLS reencrypt proxy using different ports
In this example, the server is running behind a proxy and both the server and the proxy are using their own certificates, so the communication between {project_name} and the proxy is encrypted. Because we want the proxy to use its own certificate, the proxy mode `reencrypt` will be used. We need to keep in mind that the proxy configuration options (as well as hostname configuration options) are not changing the ports on which the server actually is listening on (it changes only the ports of static resources like JavaScript and CSS links, OIDC well-known endpoints, redirect URIs, etc.). Therefore, we need to use HTTP configuration options to change the {project_name} server to internally listen on a different port, e.g. 8543. The proxy will be listening on the port 8443 (the port visible while accessing the console via a browser). The example hostname `my-keycloak.org` will be used for the server and similarly the admin console will be accessible via the `admin.my-keycloak.org` subdomain.
In this example, the server is running behind a proxy and both the server and the proxy are using their own certificates, so the communication between {project_name} and the proxy is encrypted. The reverse proxy uses the `Forwarded` header and does not set the `X-Forwarded-*` headers. We need to keep in mind that the proxy configuration options (as well as hostname configuration options) are not changing the ports on which the server actually is listening on (it changes only the ports of static resources like JavaScript and CSS links, OIDC well-known endpoints, redirect URIs, etc.). Therefore, we need to use HTTP configuration options to change the {project_name} server to internally listen on a different port, e.g. 8543. The proxy will be listening on the port 8443 (the port visible while accessing the console via a browser). The example hostname `my-keycloak.org` will be used for the server and similarly the admin console will be accessible via the `admin.my-keycloak.org` subdomain.
.{project_name} configuration:
<@kc.start parameters="--proxy=reencrypt --https-port=8543 --hostname-url=https://my-keycloak.org:8443 --hostname-admin-url=https://admin.my-keycloak.org:8443"/>
<@kc.start parameters="--proxy-headers=forwarded --https-port=8543 --hostname-url=https://my-keycloak.org:8443 --hostname-admin-url=https://admin.my-keycloak.org:8443"/>
Note: there is currently no difference between the `passthrough` and `reencrypt` modes. For now, this is meant for future-proof configuration compatibility. The only difference is that when the `edge` proxy mode is used, HTTP is implicitly enabled (again as mentioned above, this does not affect the server behaviour).
WARNING: Usage any of the proxy modes makes {project_name} rely on Forwarded and X-Forwarded-* headers.
WARNING: Usage of the `proxy-headers` option rely on `Forwarded` and `X-Forwarded-*` headers, respectively, that have to be set and overwritten by the reverse proxy.
Misconfiguration may leave {project_name} exposed to security issues. For more details, see <@links.server id="reverseproxy"/>.
== Troubleshooting

View file

@ -8,11 +8,29 @@ title="Using a reverse proxy"
summary="Learn how to configure {project_name} together with a reverse proxy, api gateway, or load balancer."
includedOptions="proxy proxy-* hostname-path hostname-url http-relative-path">
Distributed environments frequently require the use of a reverse proxy.
For {project_name}, your choice of proxy modes depends on the TLS termination in your environment.
Distributed environments frequently require the use of a reverse proxy. {project_name} offers several options to securely integrate with such environments.
== Configure the reverse proxy headers
{project_name} will parse the reverse proxy headers based on the `proxy-headers` option which accepts several values:
* By default if the option is not specified, no reverse proxy headers are parsed.
* `forwarded` enables parsing of the `Forwarded` header as per https://www.rfc-editor.org/rfc/rfc7239.html[RFC7239].
* `xforwarded` enables parsing of non-standard `X-Forwarded-*` headers, such as `X-Forwarded-For`, `X-Forwarded-Proto`, `X-Forwarded-Host`, and `X-Forwarded-Port`.
For example:
<@kc.start parameters="--proxy-headers forwarded"/>
WARNING: If either `forwarded` or `xforwarded` is selected, make sure your reverse proxy properly sets and overwrites the `Forwarded` or `X-Forwarded-*` headers respectively. To set these headers, consult the documentation for your reverse proxy. Misconfiguration will leave {project_name} exposed to security vulnerabilities.
Take extra precautions to ensure that the client address is properly set by your reverse proxy via the `Forwarded` or `X-Forwarded-For` headers.
If this header is incorrectly configured, rogue clients can set this header and trick {project_name} into thinking the client is connected from a different IP address than the actual address. This precaution can be more critical if you do any deny or allow listing of IP addresses.
== Proxy modes
The following proxy modes are available:
NOTE: The support for setting proxy modes is deprecated and will be removed in a future {project_name} release. Consider configuring accepted reverse proxy headers instead as described in the chapter above. For migration instructions consult the https://www.keycloak.org/docs/latest/upgrading/index.html#deprecated-proxy-option[Upgrading Guide].
For {project_name}, your choice of proxy modes depends on the TLS termination in your environment. The following proxy modes are available:
edge:: Enables communication through HTTP between the proxy and {project_name}.
This mode is suitable for deployments with a highly secure internal network where the reverse proxy keeps a secure connection (HTTP over TLS) with clients while communicating with {project_name} using HTTP.
@ -24,26 +42,15 @@ Different keys and certificates are used on the reverse proxy as well as on {pro
passthrough:: The proxy forwards the HTTPS connection to {project_name} without terminating TLS.
The secure connections between the server and clients are based on the keys and certificates used by the {project_name} server.
== Configure the proxy mode in {project_name}
To select the proxy mode, enter this command:
<@kc.start parameters="--proxy <mode>"/>
== Configure the reverse proxy
Some {project_name} features rely on the assumption that the remote address of the HTTP request connecting to {project_name} is the real IP address of the clients machine.
When in **edge** or **reencrypt** proxy mode, {project_name} will parse the following headers and expects the reverse proxy to set them:
* `Forwarded` as per https://www.rfc-editor.org/rfc/rfc7239.html[RFC7239]
* Non-standard `X-Forwarded`
* Non-standard `X-Forwarded-*`, such as `X-Forwarded-For`, `X-Forwarded-Proto`, `X-Forwarded-Host`, and `X-Forwarded-Port`
To set these headers, consult the documentation for your reverse proxy.
=== Configure the proxy mode in {project_name}
To select the proxy mode, enter this command:
Take extra precautions to ensure that the client address is properly set by your reverse proxy via the `Forwarded` or `X-Forwarded-For` headers.
If this header is incorrectly configured, rogue clients can set this header and trick {project_name} into thinking the client is connected from a different IP address than the actual address.
This precaution can be more critical if you do any deny or allow listing of IP addresses.
<@kc.start parameters="--proxy <mode>"/>
== Different context-path on reverse proxy
@ -56,7 +63,7 @@ Alternatively you can also change the context path of {project_name} itself to m
By default, {project_name} needs to know under which hostname it will be called. If your reverse proxy is configured to check for the correct hostname, you can set {project_name} to accept any hostname.
<@kc.start parameters="--proxy <mode> --hostname-strict=false"/>
<@kc.start parameters="--proxy-headers=forwarded|xforwarded --hostname-strict=false"/>
== Enable sticky sessions

View file

@ -22,6 +22,12 @@
*CLI:* `${option.keyCli}` +
*Env:* `${option.keyEnv}`
--
<#if option.deprecated?has_content>
*DEPRECATED.*
${option.deprecated.note!}<#if option.deprecated.newOptionsKeys?has_content><#if option.deprecated.note?has_content> </#if>Use: <#list option.deprecated.newOptionsKeys as key>`+${key}+`<#if key?has_next>, </#if></#list>.</#if>
</#if>
|<#if option.expectedValues?has_content>
<#list option.expectedValues as value>`+${value!}+`<#if option.defaultValue?has_content && value = option.defaultValue> (default)</#if><#if value?has_next>, </#if></#list>
<#else>

View file

@ -6,6 +6,7 @@ import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvi
import org.apache.commons.lang3.ArrayUtils;
import org.keycloak.config.ConfigSupportLevel;
import org.keycloak.config.DeprecatedMetadata;
import org.keycloak.config.OptionCategory;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderFactory;
@ -32,11 +33,12 @@ public class Options {
private final Map<String, Option> options;
private final Map<String, Map<String, List<Option>>> providerOptions = new LinkedHashMap<>();
@SuppressWarnings("unchecked")
public Options() {
options = PropertyMappers.getMappers().stream()
.filter(m -> !m.isHidden())
.filter(propertyMapper -> Objects.nonNull(propertyMapper.getDescription()))
.map(m -> new Option(m.getFrom(), m.getCategory(), m.isBuildTime(), null, m.getDescription(), (String) m.getDefaultValue().map(Object::toString).orElse(null), m.getExpectedValues()))
.map(m -> new Option(m.getFrom(), m.getCategory(), m.isBuildTime(), null, m.getDescription(), (String) m.getDefaultValue().map(Object::toString).orElse(null), m.getExpectedValues(), (DeprecatedMetadata) m.getDeprecatedMetadata().orElse(null)))
.sorted(Comparator.comparing(Option::getKey))
.collect(Collectors.toMap(Option::getKey, o -> o, (o1, o2) -> o1, LinkedHashMap::new)); // Need to ignore duplicate keys??
ProviderManager providerManager = Providers.getProviderManager(Thread.currentThread().getContextClassLoader());
@ -59,7 +61,8 @@ public class Options {
m.getType(),
m.getHelpText(),
m.getDefaultValue() == null ? null : m.getDefaultValue().toString(),
m.getOptions() == null ? Collections.emptyList() : m.getOptions()))
m.getOptions() == null ? Collections.emptyList() : m.getOptions(),
null))
.sorted(Comparator.comparing(Option::getKey)).collect(Collectors.toList());
ArrayList<String> booleanValues = new ArrayList<>();
@ -115,8 +118,9 @@ public class Options {
private String description;
private String defaultValue;
private List<String> expectedValues;
private DeprecatedMetadata deprecated;
public Option(String key, OptionCategory category, boolean build, String type, String description, String defaultValue, Iterable<String> expectedValues) {
public Option(String key, OptionCategory category, boolean build, String type, String description, String defaultValue, Iterable<String> expectedValues, DeprecatedMetadata deprecatedMetadata) {
this.key = key;
this.category = category;
this.build = build;
@ -124,6 +128,7 @@ public class Options {
this.description = description;
this.defaultValue = defaultValue;
this.expectedValues = StreamSupport.stream(expectedValues.spliterator(), false).collect(Collectors.toList());
this.deprecated = deprecatedMetadata;
}
public boolean isBuild() {
@ -172,6 +177,10 @@ public class Options {
public List<String> getExpectedValues() {
return expectedValues;
}
public DeprecatedMetadata getDeprecated() {
return deprecated;
}
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright 2023 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.config;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
public class DeprecatedMetadata {
private final Set<String> newOptionsKeys;
private final String note;
public DeprecatedMetadata() {
newOptionsKeys = Collections.emptySet();
note = null;
}
public DeprecatedMetadata(Set<String> newOptionsKeys, String note) {
this.newOptionsKeys = newOptionsKeys == null ? Collections.emptySet() : Collections.unmodifiableSet(newOptionsKeys);
this.note = note;
}
public Set<String> getNewOptionsKeys() {
return newOptionsKeys;
}
public String getNote() {
return note;
}
}

View file

@ -89,19 +89,22 @@ public class HttpOptions {
public static final Option HTTPS_TRUST_STORE_FILE = new OptionBuilder<>("https-trust-store-file", File.class)
.category(OptionCategory.HTTP)
.description("DEPRECATED: The trust store which holds the certificate information of the certificates to trust.")
.description("The trust store which holds the certificate information of the certificates to trust.")
.deprecated("Use the System Truststore instead, see the docs for details.")
.build();
public static final Option HTTPS_TRUST_STORE_PASSWORD = new OptionBuilder<>("https-trust-store-password", String.class)
.category(OptionCategory.HTTP)
.description("DEPRECATED: The password of the trust store file.")
.description("The password of the trust store file.")
.deprecated("Use the System Truststore instead, see the docs for details.")
.build();
public static final Option<String> HTTPS_TRUST_STORE_TYPE = new OptionBuilder<>("https-trust-store-type", String.class)
.category(OptionCategory.HTTP)
.description("DEPRECATED: 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 '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
.deprecated("Use the System Truststore instead, see the docs for details.")
.build();
public static final Option<Boolean> HTTP_SERVER_ENABLED = new OptionBuilder<>("http-server-enabled", Boolean.class)

View file

@ -8,8 +8,8 @@ public class MultiOption<T> extends Option<T> {
private final Class auxiliaryType;
public MultiOption(Class type, Class auxiliaryType, String key, OptionCategory category, boolean hidden, boolean buildTime, String description, Optional defaultValue, Supplier<List<String>> expectedValues) {
super(type, key, category, hidden, buildTime, description, defaultValue, expectedValues);
public MultiOption(Class type, Class auxiliaryType, String key, OptionCategory category, boolean hidden, boolean buildTime, String description, Optional defaultValue, Supplier<List<String>> expectedValues, DeprecatedMetadata deprecatedMetadata) {
super(type, key, category, hidden, buildTime, description, defaultValue, expectedValues, deprecatedMetadata);
this.auxiliaryType = auxiliaryType;
}

View file

@ -14,8 +14,9 @@ public class Option<T> {
private final String description;
private final Optional<T> defaultValue;
private final Supplier<List<String>> expectedValues;
private final DeprecatedMetadata deprecatedMetadata;
public Option(Class<T> type, String key, OptionCategory category, boolean hidden, boolean buildTime, String description, Optional<T> defaultValue, Supplier<List<String>> expectedValues) {
public Option(Class<T> type, String key, OptionCategory category, boolean hidden, boolean buildTime, String description, Optional<T> defaultValue, Supplier<List<String>> expectedValues, DeprecatedMetadata deprecatedMetadata) {
this.type = type;
this.key = key;
this.category = category;
@ -24,6 +25,7 @@ public class Option<T> {
this.description = getDescriptionByCategorySupportLevel(description);
this.defaultValue = defaultValue;
this.expectedValues = expectedValues;
this.deprecatedMetadata = deprecatedMetadata;
}
public Class<T> getType() {
@ -54,6 +56,10 @@ public class Option<T> {
return expectedValues.get();
}
public Optional<DeprecatedMetadata> getDeprecatedMetadata() {
return Optional.ofNullable(deprecatedMetadata);
}
public Option<T> withRuntimeSpecificDefault(T defaultValue) {
return new Option<T>(
this.type,
@ -63,7 +69,8 @@ public class Option<T> {
this.buildTime,
this.description,
Optional.ofNullable(defaultValue),
this.expectedValues
this.expectedValues,
this.deprecatedMetadata
);
}

View file

@ -2,6 +2,7 @@ package org.keycloak.config;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -26,6 +27,7 @@ public class OptionBuilder<T> {
private String description;
private Optional<T> defaultValue;
private Supplier<List<String>> expectedValues;
private DeprecatedMetadata deprecatedMetadata;
public OptionBuilder(String key, Class<T> type) {
this(key, type, null);
@ -111,12 +113,32 @@ public class OptionBuilder<T> {
return this;
}
public OptionBuilder<T> deprecated() {
this.deprecatedMetadata = new DeprecatedMetadata();
return this;
}
public OptionBuilder<T> deprecated(String note) {
this.deprecatedMetadata = new DeprecatedMetadata(null, note);
return this;
}
public OptionBuilder<T> deprecated(Set<String> newOptionsKeys) {
this.deprecatedMetadata = new DeprecatedMetadata(newOptionsKeys, null);
return this;
}
public OptionBuilder<T> deprecated(String note, Set<String> newOptionsKeys) {
this.deprecatedMetadata = new DeprecatedMetadata(newOptionsKeys, note);
return this;
}
public Option<T> build() {
if (auxiliaryType != null) {
return new MultiOption<T>(type, auxiliaryType, key, category, hidden, build, description, defaultValue, expectedValues);
return new MultiOption<T>(type, auxiliaryType, key, category, hidden, build, description, defaultValue, expectedValues, deprecatedMetadata);
} else {
return new Option<T>(type, key, category, hidden, build, description, defaultValue, expectedValues);
return new Option<T>(type, key, category, hidden, build, description, defaultValue, expectedValues, deprecatedMetadata);
}
}

View file

@ -1,7 +1,14 @@
package org.keycloak.config;
import java.util.Set;
public class ProxyOptions {
public enum Headers {
forwarded,
xforwarded
}
public enum Mode {
none(false),
edge,
@ -23,10 +30,16 @@ public class ProxyOptions {
}
}
public static final Option<Headers> PROXY_HEADERS = new OptionBuilder<>("proxy-headers", Headers.class)
.category(OptionCategory.PROXY)
.description("The proxy headers that should be accepted by the server. Misconfiguration might leave the server exposed to security vulnerabilities. Takes precedence over the deprecated proxy option.")
.build();
public static final Option<Mode> PROXY = new OptionBuilder<>("proxy", Mode.class)
.category(OptionCategory.PROXY)
.description("The proxy address forwarding mode if the server is behind a reverse proxy.")
.defaultValue(Mode.none)
.deprecated(Set.of(PROXY_HEADERS.getKey()))
.build();
public static final Option<Boolean> PROXY_FORWARDED_HOST = new OptionBuilder<>("proxy-forwarded-host", Boolean.class)

View file

@ -47,16 +47,14 @@ public class OptionRenderer implements CommandLine.Help.IOptionRenderer {
Text shortName = names.length > 1 ? scheme.optionText(names[0]) : EMPTY_TEXT;
Text longName = createLongName(option, scheme);
Text[][] result = new Text[1][];
String[] descriptions = option.description();
Text description = scheme.text(option.description()[0]);
// for better formatting, only a single line is expected in the description
// formatting is done by customizations to the text table
if (descriptions.length > 1) {
if (option.description().length > 1) {
throw new CommandLine.PicocliException("Option[" + option + "] description should have a single line.");
}
Text description = formatDescription(descriptions, option, scheme);
if (EMPTY_TEXT.equals(shortName)) {
result[0] = new Text[] { longName, description };
} else {
@ -66,26 +64,6 @@ public class OptionRenderer implements CommandLine.Help.IOptionRenderer {
return result;
}
private Text formatDescription(String[] descriptions, OptionSpec option, ColorScheme scheme) {
String description = descriptions[0];
String defaultValue = option.defaultValue();
Iterable<String> completionCandidates = option.completionCandidates();
if (!option.type().equals(Boolean.class) && completionCandidates != null) {
List<String> expectedValues = StreamSupport.stream(completionCandidates.spliterator(), false).collect(Collectors.toList());
if (!expectedValues.isEmpty()) {
description = description + " Possible values are: " + String.join(", ", expectedValues) + ".";
}
}
if (defaultValue != null) {
description = description + " Default: " + defaultValue + ".";
}
return scheme.text(description);
}
private Text createLongName(OptionSpec option, ColorScheme scheme) {
Text name = scheme.optionText(option.longestName());
String paramLabel = formatParamLabel(option);

View file

@ -30,6 +30,7 @@ import static org.keycloak.quarkus.runtime.Environment.isDevMode;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getCurrentBuiltTimeProperty;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getRawPersistedProperty;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getRuntimeProperty;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.formatValue;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.isBuildTimeProperty;
import static org.keycloak.utils.StringUtil.isNotBlank;
@ -41,6 +42,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -52,6 +54,8 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.logging.Logger;
import org.keycloak.config.DeprecatedMetadata;
import org.keycloak.config.MultiOption;
import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.cli.command.AbstractCommand;
@ -271,6 +275,7 @@ public final class Picocli {
List<String> ignoredBuildTime = new ArrayList<>();
List<String> ignoredRunTime = new ArrayList<>();
Set<String> deprecatedInUse = new HashSet<>();
for (OptionCategory category : abstractCommand.getOptionCategories()) {
List<PropertyMapper> mappers = new ArrayList<>();
Optional.ofNullable(PropertyMappers.getRuntimeMappers().get(category)).ifPresent(mappers::addAll);
@ -307,21 +312,53 @@ public final class Picocli {
throw new PropertyException(PropertyMapperParameterConsumer.getErrorMessage(mapper.getFrom(),
value, mapper.getExpectedValues(), mapper.getExpectedValues()) + ". From ConfigSource " + configSource.getName());
}
mapper.getDeprecatedMetadata().ifPresent(d -> {
DeprecatedMetadata metadata = (DeprecatedMetadata) d;
String optionName = mapper.getFrom();
if (optionName.startsWith(NS_KEYCLOAK_PREFIX)) {
optionName = optionName.substring(NS_KEYCLOAK_PREFIX.length());
}
StringBuilder sb = new StringBuilder("\t- ");
sb.append(optionName);
if (metadata.getNote() != null || !metadata.getNewOptionsKeys().isEmpty()) {
sb.append(":");
}
if (metadata.getNote() != null) {
sb.append(" ");
sb.append(metadata.getNote());
if (!metadata.getNote().endsWith(".")) {
sb.append(".");
}
}
if (!metadata.getNewOptionsKeys().isEmpty()) {
sb.append(" Use ");
sb.append(String.join(", ", metadata.getNewOptionsKeys()));
sb.append(".");
}
deprecatedInUse.add(sb.toString());
});
}
}
Logger logger = Logger.getLogger(Picocli.class); // logger can't be instantiated in a class field
if (!ignoredBuildTime.isEmpty()) {
outputIgnoredProperties(ignoredBuildTime, true, out);
outputIgnoredProperties(ignoredBuildTime, true, logger);
} else if (!ignoredRunTime.isEmpty()) {
outputIgnoredProperties(ignoredRunTime, false, out);
outputIgnoredProperties(ignoredRunTime, false, logger);
}
if (!deprecatedInUse.isEmpty()) {
logger.warn("The following used options are DEPRECATED and will be removed in a future release:\n" + String.join("\n", deprecatedInUse));
}
}
private static void outputIgnoredProperties(List<String> properties, boolean build, PrintWriter out) {
out.write(String.format("The following %s time non-cli properties were found, but will be ignored during %s time: %s\n",
private static void outputIgnoredProperties(List<String> properties, boolean build, Logger logger) {
logger.warn(String.format("The following %s time non-cli options were found, but will be ignored during %s time: %s\n",
build ? "build" : "run", build ? "run" : "build",
properties.stream().collect(Collectors.joining(", "))));
out.flush();
}
private static boolean hasConfigChanges(CommandLine cmdCommand) {
@ -563,7 +600,7 @@ public final class Picocli {
}
OptionSpec.Builder optBuilder = OptionSpec.builder(name)
.description(description)
.description(getDecoratedOptionDescription(mapper))
.paramLabel(mapper.getParamLabel())
.completionCandidates(new Iterable<String>() {
@Override
@ -598,6 +635,41 @@ public final class Picocli {
}
}
private static String getDecoratedOptionDescription(PropertyMapper<?> mapper) {
StringBuilder transformedDesc = new StringBuilder(mapper.getDescription());
if (mapper.getType() != Boolean.class && !mapper.getExpectedValues().isEmpty()) {
transformedDesc.append(" Possible values are: " + String.join(", ", mapper.getExpectedValues()) + ".");
}
mapper.getDefaultValue().map(d -> " Default: " + d + ".").ifPresent(transformedDesc::append);
mapper.getDeprecatedMetadata().ifPresent(deprecatedMetadata -> {
List<String> deprecatedDetails = new ArrayList<>();
String note = deprecatedMetadata.getNote();
if (note != null) {
if (!note.endsWith(".")) {
note += ".";
}
deprecatedDetails.add(note);
}
if (!deprecatedMetadata.getNewOptionsKeys().isEmpty()) {
String s = deprecatedMetadata.getNewOptionsKeys().size() > 1 ? "s" : "";
deprecatedDetails.add("Use the following option" + s + " instead: " + String.join(", ", deprecatedMetadata.getNewOptionsKeys()) + ".");
}
transformedDesc.insert(0, "@|bold DEPRECATED.|@ ");
if (!deprecatedDetails.isEmpty()) {
transformedDesc
.append(" @|bold ")
.append(String.join(" ", deprecatedDetails))
.append("|@");
}
});
return transformedDesc.toString();
}
public static void println(CommandLine cmd, String message) {
cmd.getOut().println(message);
}

View file

@ -31,6 +31,8 @@ import java.util.function.BiFunction;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue;
import org.jboss.logging.Logger;
import org.keycloak.config.DeprecatedMetadata;
import org.keycloak.config.Option;
import org.keycloak.config.OptionBuilder;
import org.keycloak.config.OptionCategory;
@ -60,6 +62,8 @@ public class PropertyMapper<T> {
private final String envVarFormat;
private String cliFormat;
private static final Logger logger = Logger.getLogger(PropertyMapper.class);
PropertyMapper(Option<T> option, String to, BiFunction<Optional<String>, ConfigSourceInterceptorContext, Optional<String>> mapper,
String mapFrom, String paramLabel, boolean mask) {
this.option = option;
@ -190,6 +194,10 @@ public class PropertyMapper<T> {
return mask;
}
public Optional<DeprecatedMetadata> getDeprecatedMetadata() {
return option.getDeprecatedMetadata();
}
private ConfigValue transformValue(String name, Optional<String> value, ConfigSourceInterceptorContext context, String configSourceName) {
if (value == null) {
return null;

View file

@ -1,14 +1,13 @@
package org.keycloak.quarkus.runtime.configuration.mappers;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue;
import org.keycloak.config.ProxyOptions;
import java.util.Optional;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
import static org.keycloak.quarkus.runtime.integration.QuarkusPlatform.addInitializationException;
import org.keycloak.config.ProxyOptions;
import org.keycloak.quarkus.runtime.Messages;
final class ProxyPropertyMappers {
@ -16,36 +15,56 @@ final class ProxyPropertyMappers {
public static PropertyMapper[] getProxyPropertyMappers() {
return new PropertyMapper[] {
fromOption(ProxyOptions.PROXY)
fromOption(ProxyOptions.PROXY_HEADERS)
.to("quarkus.http.proxy.proxy-address-forwarding")
.transformer(ProxyPropertyMappers::isProxyHeadersEnabled)
.transformer((v, c) -> proxyEnabled(null, v, c))
.paramLabel("headers")
.build(),
fromOption(ProxyOptions.PROXY)
.paramLabel("mode")
.build(),
fromOption(ProxyOptions.PROXY_FORWARDED_HOST)
.to("quarkus.http.proxy.enable-forwarded-host")
.mapFrom("proxy")
.transformer(ProxyPropertyMappers::isProxyHeadersEnabled)
.mapFrom("proxy-headers")
.transformer((v, c) -> proxyEnabled(null, v, c))
.build(),
fromOption(ProxyOptions.PROXY_FORWARDED_HEADER_ENABLED)
.to("quarkus.http.proxy.allow-forwarded")
.mapFrom("proxy")
.transformer(ProxyPropertyMappers::isProxyHeadersEnabled)
.mapFrom("proxy-headers")
.transformer((v, c) -> proxyEnabled(ProxyOptions.Headers.forwarded, v, c))
.build(),
fromOption(ProxyOptions.PROXY_X_FORWARDED_HEADER_ENABLED)
.to("quarkus.http.proxy.allow-x-forwarded")
.mapFrom("proxy")
.transformer(ProxyPropertyMappers::isProxyHeadersEnabled)
.mapFrom("proxy-headers")
.transformer((v, c) -> proxyEnabled(ProxyOptions.Headers.xforwarded, v, c))
.build()
};
}
private static Optional<String> isProxyHeadersEnabled(Optional<String> value, ConfigSourceInterceptorContext context) {
try {
return Optional.of(String.valueOf(ProxyOptions.Mode.valueOf(value.get()).isProxyHeadersEnabled()));
} catch (IllegalArgumentException iae) {
addInitializationException(Messages.invalidProxyMode(value.get()));
return Optional.of(Boolean.FALSE.toString());
private static Optional<String> proxyEnabled(ProxyOptions.Headers testHeader, Optional<String> value, ConfigSourceInterceptorContext context) {
boolean enabled;
if (value.isPresent()) { // proxy-headers explicitly configured
if (testHeader != null) {
enabled = ProxyOptions.Headers.valueOf(value.get()).equals(testHeader);
} else {
enabled = true;
}
} else { // fallback to the deprecated proxy option
String proxyKey = NS_KEYCLOAK_PREFIX + ProxyOptions.PROXY.getKey();
ConfigValue proxyOptionConfigValue = context.proceed(proxyKey);
ProxyOptions.Mode proxyMode;
if (proxyOptionConfigValue == null) { // neither proxy-headers nor proxy options are configured, falling back to default proxy value which is "none"
proxyMode = (ProxyOptions.Mode) PropertyMappers.getMapper(proxyKey).getDefaultValue().orElseThrow();
} else {
proxyMode = ProxyOptions.Mode.valueOf(proxyOptionConfigValue.getValue());
}
enabled = proxyMode.isProxyHeadersEnabled();
}
return Optional.of(String.valueOf(enabled));
}
}

View file

@ -19,6 +19,7 @@ package org.keycloak.quarkus.runtime.hostname;
import static org.keycloak.common.util.UriUtils.checkUrl;
import static org.keycloak.config.ProxyOptions.PROXY;
import static org.keycloak.config.ProxyOptions.PROXY_HEADERS;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfigValue;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getKcConfigValue;
import static org.keycloak.urls.UrlType.ADMIN;
@ -289,7 +290,13 @@ public final class DefaultHostnameProvider implements HostnameProvider, Hostname
}
defaultPath = config.get("path", frontEndBaseUri == null ? null : frontEndBaseUri.getPath());
if (getKcConfigValue(PROXY_HEADERS.getKey()).getValue() != null) { // proxy-headers option was explicitly configured
noProxy = false;
} else { // falling back to proxy option
noProxy = Mode.none.equals(ProxyOptions.Mode.valueOf(getKcConfigValue(PROXY.getKey()).getValue()));
}
defaultTlsPort = Integer.parseInt(httpsPort);
if (defaultTlsPort == DEFAULT_HTTPS_PORT_VALUE) {

View file

@ -72,6 +72,13 @@ public class HostnameDistTest {
assertFrontEndUrl("https://mykeycloak.org:8443", "https://mykeycloak.org/");
}
@Test
@Launch({ "start", "--hostname=mykeycloak.org", "--proxy-headers=forwarded" })
public void testUseDefaultPortsWhenProxyHeadersIsSet() {
assertFrontEndUrl("http://mykeycloak.org:8080", "https://mykeycloak.org/");
assertFrontEndUrl("https://mykeycloak.org:8443", "https://mykeycloak.org/");
}
@Test
@Launch({ "start", "--hostname=mykeycloak.org", "--proxy=edge", "--hostname-strict-https=false" })
public void testUseDefaultPortsWhenProxyIsSetNoStrictHttps() {

View file

@ -46,7 +46,8 @@ public class ProxyDistTest {
assertFrontEndUrl("http://mykeycloak.org:8080", "http://mykeycloak.org:8080/");
assertFrontEndUrl("http://localhost:8080", "http://mykeycloak.org:8080/");
assertFrontEndUrl("https://localhost:8443", "https://mykeycloak.org:8443/");
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
assertForwardedHeaderIsIgnored();
assertXForwardedHeadersAreIgnored();
}
@Test
@ -58,7 +59,7 @@ public class ProxyDistTest {
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy=edge" })
public void testForwardedHeadersWithEdge() {
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://mykeycloak.org:8080").then().body(containsString("https://test:1234/admin"));
assertForwardedHeader();
}
@Test
@ -67,6 +68,41 @@ public class ProxyDistTest {
assertXForwardedHeaders();
}
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy=passthrough" })
public void testProxyHeadersIgnoredWithPassthrough() {
assertForwardedHeaderIsIgnored();
assertXForwardedHeadersAreIgnored();
}
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy-headers=forwarded" })
public void testForwardedProxyHeaders() {
assertForwardedHeader();
assertXForwardedHeadersAreIgnored();
}
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy-headers=xforwarded" })
public void testXForwardedProxyHeaders() {
assertForwardedHeaderIsIgnored();
assertXForwardedHeaders();
}
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy-headers=xforwarded", "--proxy=reencrypt" })
public void testProxyHeadersTakePrecedenceOverProxyReencryptOption() {
assertForwardedHeaderIsIgnored();
assertXForwardedHeaders();
}
@Test
@Launch({ "start-dev", "--hostname=mykeycloak.org", "--proxy-headers=xforwarded", "--proxy=none" })
public void testProxyHeadersTakePrecedenceOverProxyNoneOption() {
assertForwardedHeaderIsIgnored();
assertXForwardedHeaders();
}
@Test
@Launch({ "start-dev", "--hostname-url=http://mykeycloak.org:1234", "--hostname-admin-url=http://mykeycloakadmin.127.0.0.1.nip.io:1234", "--proxy=edge" })
public void testIgnoreForwardedHeadersWhenFrontendUrlSet() {
@ -74,6 +110,14 @@ public class ProxyDistTest {
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().body(containsString("http://mykeycloakadmin.127.0.0.1.nip.io:1234/admin"));
}
private void assertForwardedHeader() {
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://mykeycloak.org:8080").then().body(containsString("https://test:1234/admin"));
}
private void assertForwardedHeaderIsIgnored() {
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080"));
}
private void assertXForwardedHeaders() {
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().body(containsString("http://test:8080/admin"));
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().body(containsString("http://test:8080/admin"));
@ -83,6 +127,14 @@ public class ProxyDistTest {
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().body(containsString("https://localhost:8443/admin"));
}
private void assertXForwardedHeadersAreIgnored() {
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().body(containsString("http://mykeycloak.org:8080/admin"));
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
given().header("X-Forwarded-Host", "test").when().get("https://localhost:8443").then().body(containsString("https://localhost:8443/admin"));
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
}
private OIDCConfigurationRepresentation getServerMetadata(String baseUrl) {
return when().get(baseUrl + "/realms/master/.well-known/openid-configuration").as(OIDCConfigurationRepresentation.class);
}

View file

@ -150,14 +150,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -183,8 +186,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -145,14 +145,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -169,8 +172,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -150,14 +150,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -183,8 +186,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -145,14 +145,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -169,8 +172,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -151,14 +151,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -184,8 +187,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -146,14 +146,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -170,8 +173,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -151,14 +151,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -184,8 +187,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -146,14 +146,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Health:
@ -170,8 +173,13 @@ Metrics:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -107,14 +107,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Config:
@ -127,8 +130,13 @@ Config:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -100,19 +100,27 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -107,14 +107,17 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Config:
@ -127,8 +130,13 @@ Config:
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -100,19 +100,27 @@ HTTP(S):
--https-protocols <protocols>
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
--https-trust-store-file <file>
DEPRECATED: The trust store which holds the certificate information of the
certificates to trust.
DEPRECATED. The trust store which holds the certificate information of the
certificates to trust. Use the System Truststore instead, see the docs for
details.
--https-trust-store-password <password>
DEPRECATED: The password of the trust store file.
DEPRECATED. The password of the trust store file. Use the System Truststore
instead, see the docs for details.
--https-trust-store-type <type>
DEPRECATED: The type of the trust store file. If not given, the type is
DEPRECATED. The type of the trust store file. If not given, the type is
automatically detected based on the file name. If 'fips-mode' is set to
'strict' and no value is set, it defaults to 'BCFKS'.
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
Truststore instead, see the docs for details.
Proxy:
--proxy <mode> The proxy address forwarding mode if the server is behind a reverse proxy.
Possible values are: none, edge, reencrypt, passthrough. Default: none.
--proxy <mode> DEPRECATED. The proxy address forwarding mode if the server is behind a
reverse proxy. Possible values are: none, edge, reencrypt, passthrough.
Default: none. Use the following option instead: proxy-headers.
--proxy-headers <headers>
The proxy headers that should be accepted by the server. Misconfiguration
might leave the server exposed to security vulnerabilities. Takes precedence
over the deprecated proxy option. Possible values are: forwarded, xforwarded.
Vault:

View file

@ -77,6 +77,10 @@ public class FileTruststoreProviderFactory implements TruststoreProviderFactory
String policy = config.get(HOSTNAME_VERIFICATION_POLICY);
String configuredType = config.get("type");
if (storepath != null || pass != null || configuredType != null) {
log.warn("Using deprecated 'spi-truststore-file-*' options. Consider using 'truststore-paths' option.");
}
HostnameVerificationPolicy verificationPolicy = null;
KeyStore truststore = null;
boolean system = false;