mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Restrict access to environment variables when at the server runtime
Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
edbf75e6ee
commit
7a76858fe4
@ -19,6 +19,7 @@ package org.keycloak.adapters.saml.config.parsers;
|
||||
|
||||
import org.keycloak.adapters.saml.config.Key;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
@ -60,20 +61,24 @@ public class KeyParser extends AbstractKeycloakSamlAdapterV1Parser<Key> {
|
||||
case CERTIFICATE_PEM:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
value = StaxParserUtil.getElementText(xmlEventReader);
|
||||
target.setCertificatePem(StringPropertyReplacer.replaceProperties(value));
|
||||
target.setCertificatePem(replaceProperties(value));
|
||||
break;
|
||||
|
||||
case PUBLIC_KEY_PEM:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
value = StaxParserUtil.getElementText(xmlEventReader);
|
||||
target.setPublicKeyPem(StringPropertyReplacer.replaceProperties(value));
|
||||
target.setPublicKeyPem(replaceProperties(value));
|
||||
break;
|
||||
|
||||
case PRIVATE_KEY_PEM:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
value = StaxParserUtil.getElementText(xmlEventReader);
|
||||
target.setPrivateKeyPem(StringPropertyReplacer.replaceProperties(value));
|
||||
target.setPrivateKeyPem(replaceProperties(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceProperties(String value) {
|
||||
return StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@ import static org.keycloak.constants.ServiceUrlConstants.AUTHZ_DISCOVERY_URL;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -33,7 +32,6 @@ import org.keycloak.authorization.client.util.TokenCallable;
|
||||
import org.keycloak.common.crypto.CryptoIntegration;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.util.SystemPropertiesJsonParserFactory;
|
||||
|
||||
/**
|
||||
* <p>This is class serves as an entry point for clients looking for access to Keycloak Authorization Services.
|
||||
|
||||
@ -15,7 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.util;
|
||||
package org.keycloak.authorization.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.io.IOContext;
|
||||
@ -24,19 +28,12 @@ import com.fasterxml.jackson.databind.MappingJsonFactory;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Provides replacing of system properties for parsed values
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class SystemPropertiesJsonParserFactory extends MappingJsonFactory {
|
||||
|
||||
private static final Properties properties = new SystemEnvProperties();
|
||||
class SystemPropertiesJsonParserFactory extends MappingJsonFactory {
|
||||
|
||||
@Override
|
||||
protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException {
|
||||
@ -71,7 +68,7 @@ public class SystemPropertiesJsonParserFactory extends MappingJsonFactory {
|
||||
@Override
|
||||
public String getText() throws IOException {
|
||||
String orig = super.getText();
|
||||
return StringPropertyReplacer.replaceProperties(orig, properties);
|
||||
return StringPropertyReplacer.replaceProperties(orig, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2024 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.authorization.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class JsonParserTest {
|
||||
|
||||
@Test
|
||||
public void testParsingSystemProps() throws IOException {
|
||||
System.setProperty("my.host", "foo");
|
||||
System.setProperty("con.pool.size", "200");
|
||||
System.setProperty("allow.any.hostname", "true");
|
||||
System.setProperty("socket.timeout.millis", "6000");
|
||||
System.setProperty("connection.timeout.millis", "7000");
|
||||
System.setProperty("connection.ttl.millis", "500");
|
||||
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream("keycloak.json");
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
|
||||
AdapterConfig config = mapper.readValue(is, AdapterConfig.class);
|
||||
Assert.assertEquals("http://foo:8080/auth", config.getAuthServerUrl());
|
||||
Assert.assertEquals("external", config.getSslRequired());
|
||||
Assert.assertEquals("angular-product${non.existing}", config.getResource());
|
||||
Assert.assertTrue(config.isPublicClient());
|
||||
Assert.assertTrue(config.isAllowAnyHostname());
|
||||
Assert.assertEquals(100, config.getCorsMaxAge());
|
||||
Assert.assertEquals(200, config.getConnectionPoolSize());
|
||||
Assert.assertEquals(6000L, config.getSocketTimeout());
|
||||
Assert.assertEquals(7000L, config.getConnectionTimeout());
|
||||
Assert.assertEquals(500L, config.getConnectionTTL());
|
||||
}
|
||||
}
|
||||
12
authz/client/src/test/resources/keycloak.json
Normal file
12
authz/client/src/test/resources/keycloak.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"auth-server-url" : "http://${my.host}:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"resource" : "angular-product${non.existing}",
|
||||
"public-client" : true,
|
||||
"allow-any-hostname": "${allow.any.hostname}",
|
||||
"cors-max-age": 100,
|
||||
"connection-pool-size": "${con.pool.size}",
|
||||
"socket-timeout-millis": "${socket.timeout.millis}",
|
||||
"connection-timeout-millis": "${connection.timeout.millis}",
|
||||
"connection-ttl-millis": "${connection.ttl.millis}"
|
||||
}
|
||||
@ -17,22 +17,20 @@
|
||||
package org.keycloak.common.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Properties;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A utility class for replacing properties in strings.
|
||||
* A utility class for replacing properties in strings.
|
||||
*
|
||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||
* @author <a href="Scott.Stark@jboss.org">Scott Stark</a>
|
||||
* @author <a href="claudio.vesco@previnet.it">Claudio Vesco</a>
|
||||
* @author <a href="mailto:adrian@jboss.com">Adrian Brock</a>
|
||||
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
|
||||
* @version <tt>$Revision: 2898 $</tt>
|
||||
* @version <tt>$Revision: 2898 $</tt>
|
||||
*/
|
||||
public final class StringPropertyReplacer
|
||||
{
|
||||
/** New line string constant */
|
||||
public static final String NEWLINE = System.getProperty("line.separator", "\n");
|
||||
|
||||
/** File separator value */
|
||||
private static final String FILE_SEPARATOR = File.separator;
|
||||
@ -51,7 +49,12 @@ public final class StringPropertyReplacer
|
||||
private static final int SEEN_DOLLAR = 1;
|
||||
private static final int IN_BRACKET = 2;
|
||||
|
||||
private static final Properties systemEnvProperties = new SystemEnvProperties();
|
||||
private static final PropertyResolver NULL_RESOLVER = property -> null;
|
||||
private static PropertyResolver DEFAULT_PROPERTY_RESOLVER;
|
||||
|
||||
public static void setDefaultPropertyResolver(PropertyResolver systemVariables) {
|
||||
DEFAULT_PROPERTY_RESOLVER = systemVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the input string and replace any occurrence of ${p} with
|
||||
@ -72,14 +75,13 @@ public final class StringPropertyReplacer
|
||||
* @return the input string with all property references replaced if any.
|
||||
* If there are no valid references the input string will be returned.
|
||||
*/
|
||||
public static String replaceProperties(final String string)
|
||||
{
|
||||
return replaceProperties(string, (Properties) null);
|
||||
public static String replaceProperties(final String string) {
|
||||
return replaceProperties(string, getDefaultPropertyResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the input string and replace any occurrence of ${p} with
|
||||
* the props.getProperty(p) value. If there is no such property p defined,
|
||||
* the value resolves from {@code resolver}. If there is no such property p defined,
|
||||
* then the ${p} reference will remain unchanged.
|
||||
*
|
||||
* If the property reference is of the form ${p:v} and there is no such property p,
|
||||
@ -93,17 +95,10 @@ public final class StringPropertyReplacer
|
||||
* value and the property ${:} is replaced with System.getProperty("path.separator").
|
||||
*
|
||||
* @param string - the string with possible ${} references
|
||||
* @param props - the source for ${x} property ref values, null means use System.getProperty()
|
||||
* @param resolver - the property resolver
|
||||
* @return the input string with all property references replaced if any.
|
||||
* If there are no valid references the input string will be returned.
|
||||
*/
|
||||
public static String replaceProperties(final String string, final Properties props) {
|
||||
if (props == null) {
|
||||
return replaceProperties(string, (PropertyResolver) null);
|
||||
}
|
||||
return replaceProperties(string, props::getProperty);
|
||||
}
|
||||
|
||||
public static String replaceProperties(final String string, PropertyResolver resolver)
|
||||
{
|
||||
if(string == null) {
|
||||
@ -171,10 +166,7 @@ public final class StringPropertyReplacer
|
||||
else
|
||||
{
|
||||
// check from the properties
|
||||
if (resolver != null)
|
||||
value = resolver.resolve(key);
|
||||
else
|
||||
value = systemEnvProperties.getProperty(key);
|
||||
value = resolveValue(resolver, key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
@ -183,10 +175,7 @@ public final class StringPropertyReplacer
|
||||
if (colon > 0)
|
||||
{
|
||||
String realKey = key.substring(0, colon);
|
||||
if (resolver != null)
|
||||
value = resolver.resolve(realKey);
|
||||
else
|
||||
value = systemEnvProperties.getProperty(realKey);
|
||||
value = resolveValue(resolver, realKey);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
@ -239,7 +228,7 @@ public final class StringPropertyReplacer
|
||||
throw new IllegalStateException("Infinite recursion happening when replacing properties on '" + buffer + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Done
|
||||
return buffer.toString();
|
||||
}
|
||||
@ -257,26 +246,32 @@ public final class StringPropertyReplacer
|
||||
{
|
||||
// Check the first part
|
||||
String key1 = key.substring(0, comma);
|
||||
if (resolver != null)
|
||||
value = resolver.resolve(key1);
|
||||
else
|
||||
value = systemEnvProperties.getProperty(key1);
|
||||
value = resolveValue(resolver, key1);
|
||||
}
|
||||
// Check the second part, if there is one and first lookup failed
|
||||
if (value == null && comma < key.length() - 1)
|
||||
{
|
||||
String key2 = key.substring(comma + 1);
|
||||
if (resolver != null)
|
||||
value = resolver.resolve(key2);
|
||||
else
|
||||
value = systemEnvProperties.getProperty(key2);
|
||||
value = resolveValue(resolver, key2);
|
||||
}
|
||||
}
|
||||
// Return whatever we've found or null
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public interface PropertyResolver {
|
||||
String resolve(String property);
|
||||
}
|
||||
|
||||
private static String resolveValue(PropertyResolver resolver, String key) {
|
||||
if (resolver == null) {
|
||||
return getDefaultPropertyResolver().resolve(key);
|
||||
}
|
||||
|
||||
return resolver.resolve(key);
|
||||
}
|
||||
|
||||
private static PropertyResolver getDefaultPropertyResolver() {
|
||||
return Optional.ofNullable(DEFAULT_PROPERTY_RESOLVER).orElse(NULL_RESOLVER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,19 +17,53 @@
|
||||
|
||||
package org.keycloak.common.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>An utility class to resolve the value of a key based on the environment variables
|
||||
* and system properties available at runtime. In most cases, you do not want to resolve whatever system variable is available at runtime but specify which ones
|
||||
* can be used when resolving placeholders.
|
||||
*
|
||||
* <p>To resolve to an environment variable, the key must have a format like {@code env.<key>} where {@code key} is the name of an environment variable.
|
||||
* For system properties, there is no specific format and the value is resolved from a system property that matches the key.
|
||||
*
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class SystemEnvProperties extends Properties {
|
||||
|
||||
/**
|
||||
* <p>An variation of {@link SystemEnvProperties} that gives unrestricted access to any system variable available at runtime.
|
||||
* Most of the time you don't want to use this class but favor creating a {@link SystemEnvProperties} instance that
|
||||
* filters which system variables should be available at runtime.
|
||||
*/
|
||||
public static final SystemEnvProperties UNFILTERED = new SystemEnvProperties(Collections.emptySet()) {
|
||||
@Override
|
||||
protected boolean isAllowed(String key) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final Set<String> allowedSystemVariables;
|
||||
|
||||
/**
|
||||
* Creates a new instance where system variables where only specific keys can be resolved from system variables.
|
||||
*
|
||||
* @param allowedSystemVariables the keys of system variables that should be available at runtime
|
||||
*/
|
||||
public SystemEnvProperties(Set<String> allowedSystemVariables) {
|
||||
this.allowedSystemVariables = Optional.ofNullable(allowedSystemVariables).orElse(Collections.emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
if (key.startsWith("env.")) {
|
||||
return System.getenv().get(key.substring(4));
|
||||
String envKey = key.substring(4);
|
||||
return isAllowed(envKey) ? System.getenv().get(envKey) : null;
|
||||
} else {
|
||||
return System.getProperty(key);
|
||||
return isAllowed(key) ? System.getProperty(key) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,4 +73,7 @@ public class SystemEnvProperties extends Properties {
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
protected boolean isAllowed(String key) {
|
||||
return allowedSystemVariables.contains(key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,35 +33,35 @@ public class StringPropertyReplacerTest {
|
||||
@Test
|
||||
public void testSystemProperties() throws NoSuchAlgorithmException {
|
||||
System.setProperty("prop1", "val1");
|
||||
Assert.assertEquals("foo-val1", StringPropertyReplacer.replaceProperties("foo-${prop1}"));
|
||||
Assert.assertEquals("foo-val1", replaceProperties("foo-${prop1}"));
|
||||
|
||||
Assert.assertEquals("foo-def", StringPropertyReplacer.replaceProperties("foo-${prop2:def}"));
|
||||
Assert.assertEquals("foo-def", replaceProperties("foo-${prop2:def}"));
|
||||
System.setProperty("prop2", "val2");
|
||||
Assert.assertEquals("foo-val2", StringPropertyReplacer.replaceProperties("foo-${prop2:def}"));
|
||||
Assert.assertEquals("foo-val2", replaceProperties("foo-${prop2:def}"));
|
||||
|
||||
// It looks for the property "prop3", then fallback to "prop4", then fallback to "prop5" and finally default value.
|
||||
// This syntax is supported by Quarkus (and underlying Microprofile)
|
||||
Assert.assertEquals("foo-def", StringPropertyReplacer.replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
Assert.assertEquals("foo-def", replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
System.setProperty("prop5", "val5");
|
||||
Assert.assertEquals("foo-val5", StringPropertyReplacer.replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
Assert.assertEquals("foo-val5", replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
System.setProperty("prop4", "val4");
|
||||
Assert.assertEquals("foo-val4", StringPropertyReplacer.replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
Assert.assertEquals("foo-val4", replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
System.setProperty("prop3", "val3");
|
||||
Assert.assertEquals("foo-val3", StringPropertyReplacer.replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
Assert.assertEquals("foo-val3", replaceProperties("foo-${prop3:${prop4:${prop5:def}}}"));
|
||||
|
||||
// It looks for the property "prop6", then fallback to "prop7" then fallback to value "def" .
|
||||
// This syntax is not supported by Quarkus (microprofile), however Wildfly probably supports this
|
||||
Assert.assertEquals("foo-def", StringPropertyReplacer.replaceProperties("foo-${prop6,prop7:def}"));
|
||||
Assert.assertEquals("foo-def", replaceProperties("foo-${prop6,prop7:def}"));
|
||||
System.setProperty("prop7", "val7");
|
||||
Assert.assertEquals("foo-val7", StringPropertyReplacer.replaceProperties("foo-${prop6,prop7:def}"));
|
||||
Assert.assertEquals("foo-val7", replaceProperties("foo-${prop6,prop7:def}"));
|
||||
System.setProperty("prop6", "val6");
|
||||
Assert.assertEquals("foo-val6", StringPropertyReplacer.replaceProperties("foo-${prop6,prop7:def}"));
|
||||
Assert.assertEquals("foo-val6", replaceProperties("foo-${prop6,prop7:def}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStackOverflow() {
|
||||
System.setProperty("prop", "${prop}");
|
||||
IllegalStateException ise = Assert.assertThrows(IllegalStateException.class, () -> StringPropertyReplacer.replaceProperties("${prop}"));
|
||||
IllegalStateException ise = Assert.assertThrows(IllegalStateException.class, () -> replaceProperties("${prop}"));
|
||||
Assert.assertEquals("Infinite recursion happening when replacing properties on '${prop}'", ise.getMessage());
|
||||
}
|
||||
|
||||
@ -72,9 +72,13 @@ public class StringPropertyReplacerTest {
|
||||
for (String key : env.keySet()) {
|
||||
String value = env.get(key);
|
||||
if ( !(value == null || "".equals(value)) ) {
|
||||
Assert.assertEquals("foo-" + value, StringPropertyReplacer.replaceProperties("foo-${env." + key + "}"));
|
||||
Assert.assertEquals("foo-" + value, replaceProperties("foo-${env." + key + "}"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceProperties(String key) {
|
||||
return StringPropertyReplacer.replaceProperties(key, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,8 +17,15 @@
|
||||
|
||||
package org.keycloak;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.StringPropertyReplacer.PropertyResolver;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@ -28,6 +35,14 @@ public class Config {
|
||||
|
||||
public static void init(ConfigProvider configProvider) {
|
||||
Config.configProvider = configProvider;
|
||||
StringPropertyReplacer.setDefaultPropertyResolver(new PropertyResolver() {
|
||||
SystemEnvProperties systemVariables = new SystemEnvProperties(Config.getAllowedSystemVariables());
|
||||
|
||||
@Override
|
||||
public String resolve(String property) {
|
||||
return systemVariables.getProperty(property);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String getAdminRealm() {
|
||||
@ -56,6 +71,22 @@ public class Config {
|
||||
return configProvider.scope(scope);
|
||||
}
|
||||
|
||||
private static Set<String> getAllowedSystemVariables() {
|
||||
Scope adminScope = configProvider.scope("admin");
|
||||
|
||||
if (adminScope == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
String[] allowedSystemVariables = adminScope.getArray("allowed-system-variables");
|
||||
|
||||
if (allowedSystemVariables == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return new HashSet<>(Arrays.asList(allowedSystemVariables));
|
||||
}
|
||||
|
||||
public static interface ConfigProvider {
|
||||
|
||||
String getProvider(String spi);
|
||||
|
||||
@ -40,7 +40,6 @@ import java.io.OutputStream;
|
||||
public class JsonSerialization {
|
||||
public static final ObjectMapper mapper = new ObjectMapper();
|
||||
public static final ObjectMapper prettyMapper = new ObjectMapper();
|
||||
public static final ObjectMapper sysPropertiesAwareMapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
|
||||
|
||||
static {
|
||||
mapper.registerModule(new Jdk8Module());
|
||||
@ -80,7 +79,7 @@ public class JsonSerialization {
|
||||
}
|
||||
|
||||
public static <T> T readValue(InputStream bytes, Class<T> type) throws IOException {
|
||||
return readValue(bytes, type, false);
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
|
||||
public static <T> T readValue(String string, TypeReference<T> type) throws IOException {
|
||||
@ -91,14 +90,6 @@ public class JsonSerialization {
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
|
||||
public static <T> T readValue(InputStream bytes, Class<T> type, boolean replaceSystemProperties) throws IOException {
|
||||
if (replaceSystemProperties) {
|
||||
return sysPropertiesAwareMapper.readValue(bytes, type);
|
||||
} else {
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link ObjectNode} based on the given {@code pojo}, copying all its properties to the resulting {@link ObjectNode}.
|
||||
*
|
||||
|
||||
@ -23,7 +23,6 @@ import org.keycloak.common.util.ObjectUtil;
|
||||
import org.keycloak.representations.ClaimsRepresentation;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.JsonWebToken;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.idm.ClientPoliciesRepresentation;
|
||||
import org.keycloak.representations.idm.ClientPolicyConditionConfigurationRepresentation;
|
||||
import org.keycloak.representations.idm.ClientPolicyConditionRepresentation;
|
||||
@ -97,30 +96,6 @@ public class JsonParserTest {
|
||||
Assert.assertNotNull(nested.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsingSystemProps() throws IOException {
|
||||
System.setProperty("my.host", "foo");
|
||||
System.setProperty("con.pool.size", "200");
|
||||
System.setProperty("allow.any.hostname", "true");
|
||||
System.setProperty("socket.timeout.millis", "6000");
|
||||
System.setProperty("connection.timeout.millis", "7000");
|
||||
System.setProperty("connection.ttl.millis", "500");
|
||||
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream("keycloak.json");
|
||||
|
||||
AdapterConfig config = JsonSerialization.readValue(is, AdapterConfig.class, true);
|
||||
Assert.assertEquals("http://foo:8080/auth", config.getAuthServerUrl());
|
||||
Assert.assertEquals("external", config.getSslRequired());
|
||||
Assert.assertEquals("angular-product${non.existing}", config.getResource());
|
||||
Assert.assertTrue(config.isPublicClient());
|
||||
Assert.assertTrue(config.isAllowAnyHostname());
|
||||
Assert.assertEquals(100, config.getCorsMaxAge());
|
||||
Assert.assertEquals(200, config.getConnectionPoolSize());
|
||||
Assert.assertEquals(6000L, config.getSocketTimeout());
|
||||
Assert.assertEquals(7000L, config.getConnectionTimeout());
|
||||
Assert.assertEquals(500L, config.getConnectionTTL());
|
||||
}
|
||||
|
||||
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
|
||||
|
||||
@Test
|
||||
@ -263,4 +238,4 @@ public class JsonParserTest {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
= Deprecating using system variables in the realm configuration
|
||||
|
||||
To favor a more secure server runtime and avoid to accidentally expose system variables, you are now forced to specify
|
||||
which system variables you want to expose by using the `spi-admin-allowed-system-variables` configuration option when
|
||||
starting the server.
|
||||
|
||||
In future releases, this capability will be removed in favor of preventing any usage of system variables in the realm configuration.
|
||||
@ -266,6 +266,20 @@ https-certificate-file
|
||||
|
||||
You can achieve most optimizations to startup and runtime behavior by using the `build` command. Also, by using the `keycloak.conf` file as a configuration source, you avoid some steps at startup that would otherwise require command line parameters, such as initializing the CLI itself. As a result, the server starts up even faster.
|
||||
|
||||
== Using system variables in the realm configuration
|
||||
|
||||
Some of the realm capabilities allow administrators to reference system variables such as environment variables and system properties when configuring
|
||||
the realm and its components.
|
||||
|
||||
By default, {project_name} disallow using system variables but only those explicitly specified through the `spi-admin-allowed-system-variables` configuration
|
||||
option. This option allows you to specify a comma-separated list of keys that will eventually resolve to values from system variables with the same key.
|
||||
|
||||
. Start the server and expose a set of system variables to the server runtime
|
||||
+
|
||||
<@kc.start parameters="--spi-admin-allowed-system-variables=FOO,BAR"/>
|
||||
|
||||
In future releases, this capability will be removed in favor of preventing any usage of system variables in the realm configuration.
|
||||
|
||||
== Underlying concepts
|
||||
This section gives an overview of the underlying concepts {project_name} uses, especially when it comes to optimizing the startup.
|
||||
|
||||
|
||||
@ -377,7 +377,7 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
||||
url = addH2NonKeywords(url);
|
||||
}
|
||||
Class.forName(driver);
|
||||
return DriverManager.getConnection(StringPropertyReplacer.replaceProperties(url, System.getProperties()), config.get("user"), config.get("password"));
|
||||
return DriverManager.getConnection(StringPropertyReplacer.replaceProperties(url, System.getProperties()::getProperty), config.get("user"), config.get("password"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to connect to database", e);
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
package org.keycloak.saml.common.util;
|
||||
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.saml.common.ErrorCodes;
|
||||
import org.keycloak.saml.common.PicketLinkLogger;
|
||||
import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
||||
@ -210,7 +211,7 @@ public class StaxParserUtil {
|
||||
|
||||
final String value = attribute.getValue();
|
||||
|
||||
return value == null ? null : trim(StringPropertyReplacer.replaceProperties(value));
|
||||
return value == null ? null : trim(StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,7 +251,7 @@ public class StaxParserUtil {
|
||||
*/
|
||||
public static String getAttributeValueRP(StartElement startElement, HasQName attrName) {
|
||||
final String value = getAttributeValue(startElement, attrName.getQName());
|
||||
return value == null ? null : StringPropertyReplacer.replaceProperties(value);
|
||||
return value == null ? null : StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -535,7 +536,7 @@ public class StaxParserUtil {
|
||||
*/
|
||||
public static String getElementTextRP(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
try {
|
||||
return trim(StringPropertyReplacer.replaceProperties(xmlEventReader.getElementText()));
|
||||
return trim(StringPropertyReplacer.replaceProperties(xmlEventReader.getElementText(), SystemEnvProperties.UNFILTERED::getProperty));
|
||||
} catch (XMLStreamException e) {
|
||||
throw logger.parserException(e);
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@ import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.TokenIdGenerator;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.connections.httpclient.HttpClientProvider;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
@ -58,7 +57,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
@ -77,8 +75,7 @@ public class ResourceAdminManager {
|
||||
}
|
||||
|
||||
public static String resolveUri(KeycloakSession session, String rootUrl, String uri) {
|
||||
String absoluteURI = ResolveRelative.resolveRelativeUri(session, rootUrl, uri);
|
||||
return StringPropertyReplacer.replaceProperties(absoluteURI);
|
||||
return ResolveRelative.resolveRelativeUri(session, rootUrl, uri);
|
||||
|
||||
}
|
||||
|
||||
@ -88,10 +85,7 @@ public class ResourceAdminManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
String absoluteURI = ResolveRelative.resolveRelativeUri(session, client.getRootUrl(), mgmtUrl);
|
||||
|
||||
// this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
|
||||
return StringPropertyReplacer.replaceProperties(absoluteURI);
|
||||
return ResolveRelative.resolveRelativeUri(session, client.getRootUrl(), mgmtUrl);
|
||||
}
|
||||
|
||||
// For non-cluster setup, return just single configured managementUrls
|
||||
@ -192,10 +186,7 @@ public class ResourceAdminManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
String absoluteURI = ResolveRelative.resolveRelativeUri(session, client.getRootUrl(), backchannelLogoutUrl);
|
||||
// this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine
|
||||
// and avoid request to LB in cluster environment
|
||||
return StringPropertyReplacer.replaceProperties(absoluteURI);
|
||||
return ResolveRelative.resolveRelativeUri(session, client.getRootUrl(), backchannelLogoutUrl);
|
||||
}
|
||||
|
||||
protected Response sendBackChannelLogoutRequestToClientUri(ClientModel resource,
|
||||
|
||||
@ -264,7 +264,7 @@ public class AccountRestService {
|
||||
|
||||
private ConsentRepresentation modelToRepresentation(UserConsentModel model) {
|
||||
List<ConsentScopeRepresentation> grantedScopes = model.getGrantedClientScopes().stream()
|
||||
.map(m -> new ConsentScopeRepresentation(m.getId(), m.getConsentScreenText()!= null ? m.getConsentScreenText() : m.getName(), StringPropertyReplacer.replaceProperties(m.getConsentScreenText(), getProperties())))
|
||||
.map(m -> new ConsentScopeRepresentation(m.getId(), m.getConsentScreenText()!= null ? m.getConsentScreenText() : m.getName(), StringPropertyReplacer.replaceProperties(m.getConsentScreenText(), getProperties()::getProperty)))
|
||||
.collect(Collectors.toList());
|
||||
return new ConsentRepresentation(grantedScopes, model.getCreatedDate(), model.getLastUpdatedDate());
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
package org.keycloak.services.util;
|
||||
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.urls.UrlType;
|
||||
@ -36,14 +37,19 @@ public class ResolveRelative {
|
||||
}
|
||||
|
||||
public static String resolveRelativeUri(String frontendUrl, String adminUrl, String rootUrl, String url) {
|
||||
String finalUrl;
|
||||
|
||||
if (url == null || !url.startsWith("/")) {
|
||||
return url;
|
||||
finalUrl = url;
|
||||
} else if (rootUrl != null && !rootUrl.isEmpty()) {
|
||||
return resolveRootUrl(frontendUrl, adminUrl, rootUrl) + url;
|
||||
finalUrl = resolveRootUrl(frontendUrl, adminUrl, rootUrl) + url;
|
||||
} else {
|
||||
return UriBuilder.fromUri(frontendUrl).replacePath(url).build().toString();
|
||||
finalUrl = UriBuilder.fromUri(frontendUrl).replacePath(url).build().toString();
|
||||
}
|
||||
|
||||
return StringPropertyReplacer.replaceProperties(finalUrl);
|
||||
}
|
||||
|
||||
public static String resolveRootUrl(KeycloakSession session, String rootUrl) {
|
||||
String frontendUrl = session.getContext().getUri(UrlType.FRONTEND).getBaseUri().toString();
|
||||
String adminUrl = session.getContext().getUri(UrlType.ADMIN).getBaseUri().toString();
|
||||
|
||||
@ -352,7 +352,7 @@ public class DefaultThemeManager implements ThemeManager {
|
||||
*/
|
||||
private void substituteProperties(final Properties properties) {
|
||||
for (final String propertyName : properties.stringPropertyNames()) {
|
||||
properties.setProperty(propertyName, StringPropertyReplacer.replaceProperties(properties.getProperty(propertyName), new SystemEnvProperties()));
|
||||
properties.setProperty(propertyName, StringPropertyReplacer.replaceProperties(properties.getProperty(propertyName), SystemEnvProperties.UNFILTERED::getProperty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,27 +15,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.services.util;
|
||||
package org.keycloak.utils;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class JsonConfigProvider implements Config.ConfigProvider {
|
||||
|
||||
private Properties properties;
|
||||
|
||||
private JsonNode config;
|
||||
|
||||
public JsonConfigProvider(JsonNode config, Properties properties) {
|
||||
public JsonConfigProvider(JsonNode config) {
|
||||
this.config = config;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,7 +67,7 @@ public class JsonConfigProvider implements Config.ConfigProvider {
|
||||
}
|
||||
|
||||
private String replaceProperties(String value) {
|
||||
return StringPropertyReplacer.replaceProperties(value, properties);
|
||||
return StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
|
||||
public class JsonScope implements Config.Scope {
|
||||
@ -18,15 +18,13 @@
|
||||
package org.keycloak.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.keycloak.services.util.JsonConfigProvider;
|
||||
import org.keycloak.services.util.JsonConfigProvider.JsonScope;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.keycloak.utils.JsonConfigProvider.JsonScope;
|
||||
|
||||
public class ScopeUtil {
|
||||
|
||||
@ -34,7 +32,7 @@ public class ScopeUtil {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
JsonNode config = mapper.readTree(json(properties));
|
||||
return new JsonConfigProvider(config, new Properties()).new JsonScope(config);
|
||||
return new JsonConfigProvider(config).new JsonScope(config);
|
||||
} catch (IOException e) {
|
||||
Assert.fail("Could not parse json");
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import org.jboss.logging.Logger;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.common.crypto.FipsMode;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.error.KeycloakErrorHandler;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
@ -436,7 +437,7 @@ public class AuthServerTestEnricher {
|
||||
log.infof("Running SQL script created by liquibase during manual migration flow", sqlScriptPath);
|
||||
String prefix = "keycloak.connectionsJpa.";
|
||||
String jdbcDriver = System.getProperty(prefix + "driver");
|
||||
String dbUrl = StringPropertyReplacer.replaceProperties(System.getProperty(prefix + "url"));
|
||||
String dbUrl = StringPropertyReplacer.replaceProperties(System.getProperty(prefix + "url"), SystemEnvProperties.UNFILTERED::getProperty);
|
||||
String dbUser = System.getProperty(prefix + "user");
|
||||
String dbPassword = System.getProperty(prefix + "password");
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ import org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDepl
|
||||
import org.jboss.arquillian.test.spi.TestClass;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.getAppServerQualifiers;
|
||||
@ -100,7 +101,7 @@ public class DeploymentTargetModifier extends AnnotationDeploymentScenarioGenera
|
||||
String newAppServerQualifier = ContainerConstants.APP_SERVER_PREFIX + AppServerTestEnricher.CURRENT_APP_SERVER + "-" + suffix;
|
||||
updateServerQualifier(deployment, testClass, newAppServerQualifier);
|
||||
} else {
|
||||
String newServerQualifier = StringPropertyReplacer.replaceProperties(containerQualifier);
|
||||
String newServerQualifier = StringPropertyReplacer.replaceProperties(containerQualifier, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
if (!newServerQualifier.equals(containerQualifier)) {
|
||||
updateServerQualifier(deployment, testClass, newServerQualifier);
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -97,8 +98,8 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
InputStream is = KcSamlIdPInitiatedSsoTest.class.getResourceAsStream(fileName);
|
||||
try {
|
||||
String template = StreamUtil.readString(is, Charset.defaultCharset());
|
||||
String realmString = StringPropertyReplacer.replaceProperties(template, properties);
|
||||
return IOUtil.loadRealm(new ByteArrayInputStream(realmString.getBytes("UTF-8")));
|
||||
String realmString = StringPropertyReplacer.replaceProperties(template, properties::getProperty);
|
||||
return IOUtil.loadRealm(new ByteArrayInputStream(realmString.getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
@ -139,7 +140,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
p.put("url.realm.provider", urlRealmProvider);
|
||||
p.put("url.realm.consumer", urlRealmConsumer);
|
||||
p.put("url.realm.consumer-2", urlRealmConsumer2);
|
||||
|
||||
|
||||
testRealms.add(loadFromClasspath("kc3731-provider-realm.json", p));
|
||||
testRealms.add(loadFromClasspath("kc3731-broker-realm.json", p));
|
||||
}
|
||||
@ -399,7 +400,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
assertThat(fed.getUserId(), is(PROVIDER_REALM_USER_NAME));
|
||||
assertThat(fed.getUserName(), is(PROVIDER_REALM_USER_NAME));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testProviderTransientIdpInitiatedLogin() throws Exception {
|
||||
IdentityProviderResource idp = adminClient.realm(REALM_CONS_NAME).identityProviders().get("saml-leaf");
|
||||
@ -426,7 +427,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
nameId.setFormat(URI.create(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()));
|
||||
nameId.setValue("subjectId1" );
|
||||
resp.getAssertions().get(0).getAssertion().getSubject().getSubType().addBaseID(nameId);
|
||||
|
||||
|
||||
Set<StatementAbstractType> statements = resp.getAssertions().get(0).getAssertion().getStatements();
|
||||
|
||||
AttributeStatementType attributeType = (AttributeStatementType) statements.stream()
|
||||
@ -448,7 +449,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
|
||||
// Login in provider realm
|
||||
.login().sso(true).build()
|
||||
|
||||
|
||||
.processSamlResponse(Binding.POST)
|
||||
.transformObject(ob -> {
|
||||
assertThat(ob, Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
|
||||
@ -460,7 +461,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
nameId.setFormat(URI.create(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()));
|
||||
nameId.setValue("subjectId2" );
|
||||
resp.getAssertions().get(0).getAssertion().getSubject().getSubType().addBaseID(nameId);
|
||||
|
||||
|
||||
Set<StatementAbstractType> statements = resp.getAssertions().get(0).getAssertion().getStatements();
|
||||
|
||||
AttributeStatementType attributeType = (AttributeStatementType) statements.stream()
|
||||
@ -487,7 +488,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
ResponseType resp = (ResponseType) samlResponse.getSamlObject();
|
||||
assertThat(resp.getDestination(), is(urlRealmConsumer + "/app/auth2/saml"));
|
||||
assertAudience(resp, urlRealmConsumer + "/app/auth2");
|
||||
|
||||
|
||||
UsersResource users = adminClient.realm(REALM_CONS_NAME).users();
|
||||
List<UserRepresentation> userList= users.search(CONSUMER_CHOSEN_USERNAME);
|
||||
assertEquals(1, userList.size());
|
||||
@ -495,7 +496,7 @@ public class KcSamlIdPInitiatedSsoTest extends AbstractKeycloakTest {
|
||||
FederatedIdentityRepresentation fed = users.get(id).getFederatedIdentity().get(0);
|
||||
assertThat(fed.getUserId(), is(PROVIDER_REALM_USER_NAME));
|
||||
assertThat(fed.getUserName(), is(PROVIDER_REALM_USER_NAME));
|
||||
|
||||
|
||||
//check that no user with sent subject-id was sent
|
||||
userList = users.search("subjectId1");
|
||||
assertTrue(userList.isEmpty());
|
||||
|
||||
@ -21,9 +21,9 @@ import org.keycloak.Config.Scope;
|
||||
import org.keycloak.Config.SystemPropertiesScope;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
@ -34,8 +34,6 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class Config implements ConfigProvider {
|
||||
|
||||
private final Properties systemProperties = new SystemEnvProperties();
|
||||
|
||||
private final Map<String, String> defaultProperties = new ConcurrentHashMap<>();
|
||||
private final ThreadLocal<Map<String, String>> properties = new ThreadLocal<Map<String, String>>() {
|
||||
@Override
|
||||
@ -157,7 +155,7 @@ public class Config implements ConfigProvider {
|
||||
}
|
||||
|
||||
private String replaceProperties(String value) {
|
||||
return StringPropertyReplacer.replaceProperties(value, systemProperties);
|
||||
return StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -23,13 +23,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.util.JsonConfigProvider;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.utils.JsonConfigProvider;
|
||||
|
||||
public class JsonConfigProviderFactory implements ConfigProviderFactory {
|
||||
|
||||
@ -66,11 +64,6 @@ public class JsonConfigProviderFactory implements ConfigProviderFactory {
|
||||
}
|
||||
|
||||
protected Optional<Config.ConfigProvider> createJsonProvider(JsonNode node) {
|
||||
return Optional.ofNullable(node).map(n -> new JsonConfigProvider(n, getProperties()));
|
||||
return Optional.ofNullable(node).map(n -> new JsonConfigProvider(n));
|
||||
}
|
||||
|
||||
protected Properties getProperties() {
|
||||
return new SystemEnvProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user