[KEYCLOAK-17872] Add missing HTTPClient properties

Signed-off-by: ruromero <rromerom@redhat.com>
This commit is contained in:
ruromero 2021-04-26 15:09:24 +02:00 committed by Hynek Mlnařík
parent 23e3bc5f8f
commit 464475caa0
35 changed files with 322 additions and 21 deletions

View file

@ -384,6 +384,10 @@ public class HttpClientBuilder {
establishConnectionTimeout(adapterConfig.getConnectionTimeout(), TimeUnit.MILLISECONDS);
}
if (connectionTTL == -1 && adapterConfig.getConnectionTTL() > 0) {
connectionTTL(adapterConfig.getConnectionTTL(), TimeUnit.MILLISECONDS);
}
return build();
}

View file

@ -37,7 +37,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
public class KeycloakExtension implements Extension {
public static final String SUBSYSTEM_NAME = "keycloak";
public static final String NAMESPACE = "urn:jboss:domain:keycloak:1.1";
public static final String NAMESPACE = "urn:jboss:domain:keycloak:1.2";
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";

View file

@ -19,6 +19,7 @@ package org.keycloak.subsystem.as7;
import org.jboss.as.controller.SimpleAttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.operations.validation.IntRangeValidator;
import org.jboss.as.controller.operations.validation.LongRangeValidator;
import org.jboss.as.controller.operations.validation.StringLengthValidator;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
@ -81,6 +82,24 @@ class SharedAttributeDefinitons {
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0, true))
.build();
protected static final SimpleAttributeDefinition SOCKET_TIMEOUT =
new SimpleAttributeDefinitionBuilder("socket-timeout", ModelType.LONG, true)
.setXmlName("socket-timeout")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition CONNECTION_TTL =
new SimpleAttributeDefinitionBuilder("connection-ttl", ModelType.LONG, true)
.setXmlName("connection-ttl")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition CONNECTION_TIMEOUT =
new SimpleAttributeDefinitionBuilder("connection-timeout", ModelType.LONG, true)
.setXmlName("connection-timeout")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition ENABLE_CORS =
new SimpleAttributeDefinitionBuilder("enable-cors", ModelType.BOOLEAN, true)
@ -192,6 +211,9 @@ class SharedAttributeDefinitons {
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
ATTRIBUTES.add(SOCKET_TIMEOUT);
ATTRIBUTES.add(CONNECTION_TTL);
ATTRIBUTES.add(CONNECTION_TIMEOUT);
ATTRIBUTES.add(ENABLE_CORS);
ATTRIBUTES.add(CLIENT_KEYSTORE);
ATTRIBUTES.add(CLIENT_KEYSTORE_PASSWORD);

View file

@ -32,6 +32,9 @@ keycloak.realm.allow-any-hostname=SSL Setting
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
keycloak.realm.truststore-password=Password of the Truststore
keycloak.realm.connection-pool-size=Connection pool size for the client used by the adapter
keycloak.realm.socket-timeout=Timeout for socket waiting for data in milliseconds
keycloak.realm.connection-ttl=Connection time to live in milliseconds
keycloak.realm.connection-timeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak.realm.enable-cors=Enable Keycloak CORS support
keycloak.realm.client-keystore=n/a
keycloak.realm.client-keystore-password=n/a
@ -61,6 +64,9 @@ keycloak.secure-deployment.allow-any-hostname=SSL Setting
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
keycloak.secure-deployment.truststore-password=Password of the Truststore
keycloak.secure-deployment.connection-pool-size=Connection pool size for the client used by the adapter
keycloak.secure-deployment.socket-timeout=Timeout for socket waiting for data in milliseconds
keycloak.secure-deployment.connection-ttl=Connection time to live in milliseconds
keycloak.secure-deployment.connection-timeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak.secure-deployment.resource=Application name
keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
keycloak.secure-deployment.credentials=Adapter credentials

View file

@ -38,7 +38,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
public class KeycloakExtension implements Extension {
public static final String SUBSYSTEM_NAME = "keycloak";
public static final String NAMESPACE = "urn:jboss:domain:keycloak:1.1";
public static final String NAMESPACE = "urn:jboss:domain:keycloak:1.2";
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";

View file

@ -19,6 +19,7 @@ package org.keycloak.subsystem.adapter.extension;
import org.jboss.as.controller.SimpleAttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.operations.validation.IntRangeValidator;
import org.jboss.as.controller.operations.validation.LongRangeValidator;
import org.jboss.as.controller.operations.validation.StringLengthValidator;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
@ -81,6 +82,24 @@ public class SharedAttributeDefinitons {
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0, true))
.build();
protected static final SimpleAttributeDefinition SOCKET_TIMEOUT =
new SimpleAttributeDefinitionBuilder("socket-timeout", ModelType.LONG, true)
.setXmlName("socket-timeout")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition CONNECTION_TTL =
new SimpleAttributeDefinitionBuilder("connection-ttl", ModelType.LONG, true)
.setXmlName("connection-ttl")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition CONNECTION_TIMEOUT =
new SimpleAttributeDefinitionBuilder("connection-timeout", ModelType.LONG, true)
.setXmlName("connection-timeout")
.setAllowExpression(true)
.setValidator(new LongRangeValidator(-1L, true))
.build();
protected static final SimpleAttributeDefinition ENABLE_CORS =
new SimpleAttributeDefinitionBuilder("enable-cors", ModelType.BOOLEAN, true)
@ -219,6 +238,9 @@ public class SharedAttributeDefinitons {
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
ATTRIBUTES.add(SOCKET_TIMEOUT);
ATTRIBUTES.add(CONNECTION_TTL);
ATTRIBUTES.add(CONNECTION_TIMEOUT);
ATTRIBUTES.add(ENABLE_CORS);
ATTRIBUTES.add(CLIENT_KEYSTORE);
ATTRIBUTES.add(CLIENT_KEYSTORE_PASSWORD);

View file

@ -35,6 +35,9 @@ keycloak.realm.allow-any-hostname=SSL Setting
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
keycloak.realm.truststore-password=Password of the Truststore
keycloak.realm.connection-pool-size=Connection pool size for the client used by the adapter
keycloak.realm.socket-timeout=Timeout for socket waiting for data in milliseconds
keycloak.realm.connection-ttl=Connection time to live in milliseconds
keycloak.realm.connection-timeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak.realm.enable-cors=Enable Keycloak CORS support
keycloak.realm.client-keystore=n/a
keycloak.realm.client-keystore-password=n/a
@ -68,6 +71,9 @@ keycloak.secure-deployment.allow-any-hostname=SSL Setting
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
keycloak.secure-deployment.truststore-password=Password of the Truststore
keycloak.secure-deployment.connection-pool-size=Connection pool size for the client used by the adapter
keycloak.secure-deployment.socket-timeout=Timeout for socket waiting for data in milliseconds
keycloak.secure-deployment.connection-ttl=Connection time to live in milliseconds
keycloak.secure-deployment.connection-timeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak.secure-deployment.resource=Application name
keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
keycloak.secure-deployment.credentials=Adapter credentials
@ -113,6 +119,9 @@ keycloak.secure-server.allow-any-hostname=SSL Setting
keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
keycloak.secure-server.truststore-password=Password of the Truststore
keycloak.secure-server.connection-pool-size=Connection pool size for the client used by the adapter
keycloak.secure-server.socket-timeout=Timeout for socket waiting for data in milliseconds
keycloak.secure-server.connection-ttl=Connection time to live in milliseconds
keycloak.secure-server.connection-timeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak.secure-server.resource=Application name
keycloak.secure-server.use-resource-role-mappings=Use resource level permissions from token
keycloak.secure-server.credentials=Adapter credentials

View file

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2021 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.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:jboss:domain:keycloak:1.2"
xmlns="urn:jboss:domain:keycloak:1.2"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">
<!-- The subsystem root element -->
<xs:element name="subsystem" type="subsystem-type"/>
<xs:complexType name="subsystem-type">
<xs:annotation>
<xs:documentation>
<![CDATA[
The Keycloak adapter subsystem, used to register deployments managed by Keycloak
]]>
</xs:documentation>
</xs:annotation>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="realm" maxOccurs="unbounded" minOccurs="0" type="realm-type"/>
<xs:element name="secure-deployment" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
<xs:element name="secure-server" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="realm-type">
<xs:all>
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="socket-timeout" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-ttl" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-timeout" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="auth-server-url" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
</xs:all>
<xs:attribute name="name" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>The name of the realm.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="secure-deployment-type">
<xs:all>
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="use-resource-role-mappings" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="auth-server-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="realm" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="resource" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="public-client" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="socket-timeout" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-ttl" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="connection-timeout" type="xs:long" minOccurs="0" maxOccurs="1"/>
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="enable-basic-auth" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="turn-off-change-session-id-on-login" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="token-minimum-time-to-live" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="min-time-between-jwks-requests" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="public-key-cache-ttl" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<xs:element name="adapter-state-cookie-path" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:all>
<xs:attribute name="name" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>The name of the realm.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="credential-type" mixed="true">
<xs:sequence maxOccurs="unbounded" minOccurs="0">
<xs:any processContents="lax"></xs:any>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="redirect-rewrite-rule-type" mixed="true">
<xs:sequence maxOccurs="unbounded" minOccurs="0">
<xs:any processContents="lax"></xs:any>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
</xs:schema>

View file

@ -19,6 +19,6 @@
<!-- Template used by WildFly build when directed to include Keycloak subsystem in a configuration. -->
<config>
<extension-module>org.keycloak.keycloak-adapter-subsystem</extension-module>
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<subsystem xmlns="urn:jboss:domain:keycloak:1.2">
</subsystem>
</config>

View file

@ -97,12 +97,12 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
@Override
protected String getSubsystemXml() throws IOException {
return readResource("keycloak-1.1.xml");
return readResource("keycloak-1.2.xml");
}
@Override
protected String getSubsystemXsdPath() throws Exception {
return "schema/wildfly-keycloak_1_1.xsd";
return "schema/wildfly-keycloak_1_2.xsd";
}
@Override

View file

@ -15,7 +15,7 @@
~ limitations under the License.
-->
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<subsystem xmlns="urn:jboss:domain:keycloak:1.2">
<realm name="master">
<realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB</realm-public-key>
<auth-server-url>http://localhost:8080/auth</auth-server-url>
@ -26,6 +26,9 @@
<allow-any-hostname>false</allow-any-hostname>
<disable-trust-manager>true</disable-trust-manager>
<connection-pool-size>20</connection-pool-size>
<socket-timeout>2000</socket-timeout>
<connection-ttl>5000</connection-ttl>
<connection-timeout>3000</connection-timeout>
<enable-cors>true</enable-cors>
<client-keystore>keys.jks</client-keystore>
<client-keystore-password>secret</client-keystore-password>
@ -85,6 +88,9 @@
<resource>wildfly-management</resource>
<bearer-only>true</bearer-only>
<ssl-required>EXTERNAL</ssl-required>
<socket-timeout>10000</socket-timeout>
<connection-ttl>40000</connection-ttl>
<connection-timeout>50000</connection-timeout>
<principal-attribute>preferred_username</principal-attribute>
</secure-deployment>
<secure-server name="wildfly-console">

View file

@ -93,6 +93,7 @@ public class Constants {
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
static final String SOCKET_TIMEOUT = "socketTimeout";
static final String CONNECTION_TIMEOUT = "connectionTimeout";
static final String CONNECTION_TTL = "connectionTTL";
}
static class XML {
@ -174,5 +175,6 @@ public class Constants {
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
static final String SOCKET_TIMEOUT = "socketTimeout";
static final String CONNECTION_TIMEOUT = "connectionTimeout";
static final String CONNECTION_TTL = "connectionTTL";
}
}

View file

@ -90,8 +90,14 @@ abstract class HttpClientDefinition {
.setAllowExpression(true)
.build();
private static final SimpleAttributeDefinition CONNECTION_TTL =
new SimpleAttributeDefinitionBuilder(Constants.Model.CONNECTION_TTL, ModelType.LONG, true)
.setXmlName(Constants.XML.CONNECTION_TTL)
.setAllowExpression(true)
.build();
static final SimpleAttributeDefinition[] ATTRIBUTES = {ALLOW_ANY_HOSTNAME, CLIENT_KEYSTORE, CLIENT_KEYSTORE_PASSWORD,
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD, SOCKET_TIMEOUT, CONNECTION_TIMEOUT};
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD, SOCKET_TIMEOUT, CONNECTION_TIMEOUT, CONNECTION_TTL};
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();

View file

@ -102,3 +102,4 @@ keycloak-saml.IDP.HttpClient.truststore=Path to the truststore used to validate
keycloak-saml.IDP.HttpClient.truststorePassword=The truststore password
keycloak-saml.IDP.HttpClient.socketTimeout=Timeout for socket waiting for data
keycloak-saml.IDP.HttpClient.connectionTimeout=Timeout for establishing the connection with the remote host
keycloak-saml.IDP.HttpClient.connectionTTL=The connection time to live

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2020 Red Hat, Inc. and/or its affiliates
~ Copyright 2021 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");
@ -552,6 +552,11 @@
<xs:documentation>Defines timeout for establishing the connection with the remote host in milliseconds.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="connectionTTL" type="xs:long" default="-1">
<xs:annotation>
<xs:documentation>Defines the connection time to live.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="allowed-clock-skew-type">

View file

@ -84,6 +84,8 @@
truststore="/tmp/truststore.jks"
truststorePassword="trustpwd#*"
socketTimeout="6000"
connectionTTL="500"
connectionTimeout="1000"
/>
</IDP>
</SP>

View file

@ -83,4 +83,8 @@ public interface AdapterHttpClientConfig {
*/
long getConnectionTimeout();
/**
* Returns the connection time-to-live
*/
long getConnectionTTL();
}

View file

@ -381,6 +381,10 @@ public class HttpClientBuilder {
establishConnectionTimeout(adapterConfig.getConnectionTimeout(), TimeUnit.MILLISECONDS);
}
if (connectionTTL == -1 && adapterConfig.getConnectionTTL() > 0) {
connectionTTL(adapterConfig.getConnectionTTL(), TimeUnit.MILLISECONDS);
}
configureProxyForAuthServerIfProvided(adapterConfig);
return build();

View file

@ -191,6 +191,7 @@ public class IDP implements Serializable {
private String proxyUrl;
private long socketTimeout;
private long connectionTimeout;
private long connectionTTL;
@Override
public String getTruststore() {
@ -278,6 +279,15 @@ public class IDP implements Serializable {
this.connectionTimeout = connectionTimeout;
}
@Override
public long getConnectionTTL() {
return connectionTTL;
}
public void setConnectionTTL(long connectionTTL) {
this.connectionTTL = connectionTTL;
}
public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl;
}

View file

@ -55,10 +55,13 @@ public class HttpClientParser extends AbstractKeycloakSamlAdapterV1Parser<HttpCl
config.setProxyUrl(StaxParserUtil.getAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_PROXY_URL));
config.setTruststore(StaxParserUtil.getAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_TRUSTSTORE));
config.setTruststorePassword(StaxParserUtil.getAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_TRUSTSTORE_PASSWORD));
final Long socketTimeout = StaxParserUtil.getLongAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_SOCKET_TIMEOUT);
config.setSocketTimeout(socketTimeout == null ? -1 : socketTimeout);
final Long connectionTimeout = StaxParserUtil.getLongAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_CONNECTION_TIMEOUT);
config.setConnectionTimeout(connectionTimeout == null ? -1 : connectionTimeout);
final Long connectionTTL = StaxParserUtil.getLongAttributeValueRP(element, KeycloakSamlAdapterV1QNames.ATTR_CONNECTION_TTL);
config.setConnectionTTL(connectionTTL == null ? -1 : connectionTTL);
return config;
}

View file

@ -93,6 +93,7 @@ public enum KeycloakSamlAdapterV1QNames implements HasQName {
ATTR_KEEP_DOM_ASSERTION(null, "keepDOMAssertion"),
ATTR_SOCKET_TIMEOUT(null, "socketTimeout"),
ATTR_CONNECTION_TIMEOUT(null, "connectionTimeout"),
ATTR_CONNECTION_TTL(null, "connectionTTL"),
UNKNOWN_ELEMENT("");

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019 Red Hat, Inc. and/or its affiliates
~ Copyright 2021 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");
@ -524,6 +524,11 @@
<xs:documentation>Defines timeout for establishing the connection with the remote host in milliseconds.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="connectionTTL" type="xs:long" default="-1">
<xs:annotation>
<xs:documentation>Defines the connection time to live.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="allowed-clock-skew-type">
<xs:annotation>

View file

@ -216,6 +216,7 @@ public class KeycloakSamlAdapterXMLParserTest {
assertThat(idp.getHttpClientConfig().isDisableTrustManager(), is(true));
assertThat(idp.getHttpClientConfig().getSocketTimeout(), is(6000L));
assertThat(idp.getHttpClientConfig().getConnectionTimeout(), is(7000L));
assertThat(idp.getHttpClientConfig().getConnectionTTL(), is(200L));
}
@Test

View file

@ -79,6 +79,7 @@
truststore="ts" truststorePassword="tsp"
socketTimeout="6000"
connectionTimeout="7000"
connectionTTL="200"
/>
</IDP>
</SP>

View file

@ -95,6 +95,7 @@ public class Constants {
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
static final String SOCKET_TIMEOUT = "socketTimeout";
static final String CONNECTION_TIMEOUT = "connectionTimeout";
static final String CONNECTION_TTL = "connectionTTL";
}
static class XML {
@ -176,6 +177,7 @@ public class Constants {
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
static final String SOCKET_TIMEOUT = "socketTimeout";
static final String CONNECTION_TIMEOUT = "connectionTimeout";
static final String CONNECTION_TTL = "connectionTTL";
}
}

View file

@ -90,8 +90,14 @@ abstract class HttpClientDefinition {
.setAllowExpression(true)
.build();
private static final SimpleAttributeDefinition CONNECTION_TTL =
new SimpleAttributeDefinitionBuilder(Constants.Model.CONNECTION_TTL, ModelType.LONG, true)
.setXmlName(Constants.XML.CONNECTION_TTL)
.setAllowExpression(true)
.build();
static final SimpleAttributeDefinition[] ATTRIBUTES = {ALLOW_ANY_HOSTNAME, CLIENT_KEYSTORE, CLIENT_KEYSTORE_PASSWORD,
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD, SOCKET_TIMEOUT, CONNECTION_TIMEOUT};
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD, SOCKET_TIMEOUT, CONNECTION_TIMEOUT, CONNECTION_TTL};
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();

View file

@ -101,3 +101,4 @@ keycloak-saml.IDP.HttpClient.truststore=Path to the truststore used to validate
keycloak-saml.IDP.HttpClient.truststorePassword=The truststore password
keycloak-saml.IDP.HttpClient.socketTimeout=Timeout for socket waiting for data in milliseconds
keycloak-saml.IDP.HttpClient.connectionTimeout=Timeout for establishing the connection with the remote host in milliseconds
keycloak-saml.IDP.HttpClient.connectionTTL=The connection time to live

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2020 Red Hat, Inc. and/or its affiliates
~ Copyright 2021 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");
@ -552,6 +552,11 @@
<xs:documentation>Defines timeout for establishing the connection with the remote host in milliseconds.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="connectionTTL" type="xs:long" default="-1">
<xs:annotation>
<xs:documentation>Defines the connection time to live.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="allowed-clock-skew-type">

View file

@ -1,5 +1,5 @@
<!--
~ Copyright 2020 Red Hat, Inc. and/or its affiliates
~ Copyright 2021 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");
@ -84,6 +84,8 @@
truststore="/tmp/truststore.jks"
truststorePassword="trustpwd#*"
socketTimeout="6000"
connectionTTL="130"
connectionTimeout="7000"
/>
</IDP>
</SP>

View file

@ -33,7 +33,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
"use-resource-role-mappings",
"enable-cors", "cors-max-age", "cors-allowed-methods", "cors-exposed-headers",
"expose-token", "bearer-only", "autodetect-bearer-only",
"connection-pool-size",
"connection-pool-size", "socket-timeout", "connection-ttl", "connection-timeout",
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
"client-keystore", "client-keystore-password", "client-key-password",
"always-refresh-token",
@ -91,9 +91,11 @@ public class AdapterConfig extends BaseAdapterConfig implements AdapterHttpClien
protected boolean verifyTokenAudience = false;
@JsonProperty("socket-timeout")
protected long socketTimeout = -1;
protected long socketTimeout = -1L;
@JsonProperty("connection-timeout")
protected long connectionTimeout = -1;
protected long connectionTimeout = -1L;
@JsonProperty("connection-ttl")
protected long connectionTTL = -1L;
/**
* The Proxy url to use for requests to the auth-server, configurable via the adapter config property {@code proxy-url}.
@ -309,4 +311,13 @@ public class AdapterConfig extends BaseAdapterConfig implements AdapterHttpClien
public void setConnectionTimeout(long connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
@Override
public long getConnectionTTL() {
return connectionTTL;
}
public void setConnectionTTL(long connectionTTL) {
this.connectionTTL = connectionTTL;
}
}

View file

@ -81,4 +81,9 @@ public interface AdapterHttpClientConfig {
* Returns timeout for establishing the connection with the remote host in milliseconds.
*/
long getConnectionTimeout();
/**
* Returns the connection time-to-live
*/
long getConnectionTTL();
}

View file

@ -102,6 +102,7 @@ public class JsonParserTest {
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");
@ -115,6 +116,7 @@ public class JsonParserTest {
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("\\$\\{([^}]+)\\}");

View file

@ -7,5 +7,6 @@
"cors-max-age": 100,
"connection-pool-size": "${con.pool.size}",
"socket-timeout": "${socket.timeout.millis}",
"connection-timeout": "${connection.timeout.millis}"
"connection-timeout": "${connection.timeout.millis}",
"connection-ttl": "${connection.ttl.millis}"
}

View file

@ -44,7 +44,7 @@ You also need to add realm config to the same file. Add a new child-element to `
<profile>
....
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<subsystem xmlns="urn:jboss:domain:keycloak:1.2">
<realm name="demo">
<auth-server-url>KEYCLOAK URL</auth-server-url>
<ssl-required>external</ssl-required>
@ -68,7 +68,7 @@ Run the following to deploy it:
# mvn install
# cp target/database.war <WILDFLY HOME>/standalone/deployments
Next add the configuration for it to the Keycloak subsystem. Edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` to `<subsystem xmlns="urn:jboss:domain:keycloak:1.1">` add:
Next add the configuration for it to the Keycloak subsystem. Edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` to `<subsystem xmlns="urn:jboss:domain:keycloak:1.2">` add:
<secure-deployment name="database.war">
<realm>demo</realm>

View file

@ -33,7 +33,7 @@
<xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $keycloakNamespace)]">
<xsl:copy>
<secure-deployment name="hawtio.war" xmlns="urn:jboss:domain:keycloak:1.1"/>
<secure-deployment name="hawtio.war" xmlns="urn:jboss:domain:keycloak:1.2"/>
</xsl:copy>
</xsl:template>