Merge pull request #2308 from tkyjovsk/auth-server-eap7-cluster
KEYCLOAK-1679 Auth server eap7 cluster
This commit is contained in:
commit
45b940ad2d
10 changed files with 530 additions and 116 deletions
|
@ -1,20 +1,20 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!--
|
<!--
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
~ and other contributors as indicated by the @author tags.
|
~ and other contributors as indicated by the @author tags.
|
||||||
~
|
~
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
~ you may not use this file except in compliance with the License.
|
~ you may not use this file except in compliance with the License.
|
||||||
~ You may obtain a copy of the License at
|
~ You may obtain a copy of the License at
|
||||||
~
|
~
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
~
|
~
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
~ See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
@ -117,6 +117,68 @@
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>ssl</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>auth.server.ssl.required</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>xml-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>configure-adapter-subsystem-security</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>transform</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformationSets>
|
||||||
|
<transformationSet>
|
||||||
|
<dir>${keycloak.server.home}/standalone/configuration</dir>
|
||||||
|
<includes>
|
||||||
|
<include>standalone.xml</include>
|
||||||
|
</includes>
|
||||||
|
<stylesheet>src/main/xslt/security.xsl</stylesheet>
|
||||||
|
<outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
|
||||||
|
</transformationSet>
|
||||||
|
</transformationSets>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>2.7</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-keystore</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${keycloak.server.home}/standalone/configuration</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/keystore</directory>
|
||||||
|
<includes>
|
||||||
|
<include>keycloak.jks</include>
|
||||||
|
<include>keycloak.truststore</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
<profile>
|
<profile>
|
||||||
<id>jpa</id>
|
<id>jpa</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -255,13 +317,14 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>ssl</id>
|
<id>auth-server-eap7-cluster</id>
|
||||||
<activation>
|
<properties>
|
||||||
<property>
|
<session.cache.owners>1</session.cache.owners>
|
||||||
<name>auth.server.ssl.required</name>
|
<offline.session.cache.owners>1</offline.session.cache.owners>
|
||||||
</property>
|
<login.failure.cache.owners>1</login.failure.cache.owners>
|
||||||
</activation>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -269,53 +332,62 @@
|
||||||
<artifactId>xml-maven-plugin</artifactId>
|
<artifactId>xml-maven-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>configure-adapter-subsystem-security</id>
|
<id>configure-wildfly-datasource</id>
|
||||||
<phase>process-resources</phase>
|
<phase>process-resources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>transform</goal>
|
<goal>transform</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<transformationSets>
|
<transformationSets>
|
||||||
|
<!-- point KeycloakDS datasource to H2 running on TCP port -->
|
||||||
<transformationSet>
|
<transformationSet>
|
||||||
<dir>${keycloak.server.home}/standalone/configuration</dir>
|
<dir>${keycloak.server.home}/standalone/configuration</dir>
|
||||||
<includes>
|
<includes>
|
||||||
<include>standalone.xml</include>
|
<include>standalone-ha.xml</include>
|
||||||
</includes>
|
</includes>
|
||||||
<stylesheet>src/main/xslt/security.xsl</stylesheet>
|
<stylesheet>src/main/xslt/datasource-jdbc-url.xsl</stylesheet>
|
||||||
<outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
|
<outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
|
||||||
|
<parameters>
|
||||||
|
<parameter>
|
||||||
|
<name>pool.name</name>
|
||||||
|
<value>KeycloakDS</value>
|
||||||
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<name>jdbc.url</name>
|
||||||
|
<value>jdbc:h2:tcp://${jboss.bind.address:localhost}:9092/mem:keycloak;DB_CLOSE_DELAY=-1</value>
|
||||||
|
</parameter>
|
||||||
|
</parameters>
|
||||||
|
</transformationSet>
|
||||||
|
<transformationSet>
|
||||||
|
<dir>${keycloak.server.home}/standalone/configuration</dir>
|
||||||
|
<includes>
|
||||||
|
<include>standalone-ha.xml</include>
|
||||||
|
</includes>
|
||||||
|
<stylesheet>src/main/xslt/ispn-cache-owners.xsl</stylesheet>
|
||||||
|
<outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
|
||||||
|
<parameters>
|
||||||
|
<parameter>
|
||||||
|
<name>sessionCacheOwners</name>
|
||||||
|
<value>${session.cache.owners}</value>
|
||||||
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<name>offlineSessionCacheOwners</name>
|
||||||
|
<value>${offline.session.cache.owners}</value>
|
||||||
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<name>loginFailureCacheOwners</name>
|
||||||
|
<value>${login.failure.cache.owners}</value>
|
||||||
|
</parameter>
|
||||||
|
</parameters>
|
||||||
</transformationSet>
|
</transformationSet>
|
||||||
</transformationSets>
|
</transformationSets>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<version>2.7</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-keystore</id>
|
|
||||||
<phase>process-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-resources</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${keycloak.server.home}/standalone/configuration</outputDirectory>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/keystore</directory>
|
|
||||||
<includes>
|
|
||||||
<include>keycloak.jks</include>
|
|
||||||
<include>keycloak.truststore</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:xalan="http://xml.apache.org/xalan"
|
||||||
|
xmlns:j="urn:jboss:domain:4.0"
|
||||||
|
xmlns:ds="urn:jboss:domain:datasources:4.0"
|
||||||
|
xmlns:k="urn:jboss:domain:keycloak:1.1"
|
||||||
|
xmlns:sec="urn:jboss:domain:security:1.2"
|
||||||
|
version="2.0"
|
||||||
|
exclude-result-prefixes="xalan j ds k sec">
|
||||||
|
|
||||||
|
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
|
||||||
|
<xsl:strip-space elements="*"/>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:variable name="nsDS" select="'urn:jboss:domain:datasources:'"/>
|
||||||
|
|
||||||
|
<xsl:param name="pool.name" select="'KeycloakDS'"/>
|
||||||
|
<xsl:param name="jdbc.url" />
|
||||||
|
|
||||||
|
<!-- replace JDBC URL -->
|
||||||
|
<xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $nsDS)]
|
||||||
|
/*[local-name()='datasources' and starts-with(namespace-uri(), $nsDS)]
|
||||||
|
/*[local-name()='datasource' and starts-with(namespace-uri(), $nsDS) and @pool-name=$pool.name]
|
||||||
|
/*[local-name()='connection-url' and starts-with(namespace-uri(), $nsDS)]">
|
||||||
|
<connection-url>
|
||||||
|
<xsl:value-of select="$jdbc.url"/>
|
||||||
|
</connection-url>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Copy everything else. -->
|
||||||
|
<xsl:template match="@*|node()">
|
||||||
|
<xsl:copy>
|
||||||
|
<xsl:apply-templates select="@*|node()" />
|
||||||
|
</xsl:copy>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
</xsl:stylesheet>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:xalan="http://xml.apache.org/xalan"
|
||||||
|
xmlns:j="urn:jboss:domain:4.0"
|
||||||
|
xmlns:i="urn:jboss:domain:infinispan:4.0"
|
||||||
|
version="2.0"
|
||||||
|
exclude-result-prefixes="xalan i">
|
||||||
|
|
||||||
|
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
|
||||||
|
<xsl:strip-space elements="*"/>
|
||||||
|
|
||||||
|
<xsl:variable name="nsDS" select="'urn:jboss:domain:datasources:'"/>
|
||||||
|
|
||||||
|
<xsl:param name="sessionCacheOwners" select="'1'"/>
|
||||||
|
<xsl:param name="offlineSessionCacheOwners" select="'1'"/>
|
||||||
|
<xsl:param name="loginFailureCacheOwners" select="'1'"/>
|
||||||
|
|
||||||
|
<xsl:template match="//i:cache-container/i:distributed-cache[@name='sessions']/@owners">
|
||||||
|
<xsl:attribute name="owners">
|
||||||
|
<xsl:value-of select="$sessionCacheOwners"/>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="//i:cache-container/i:distributed-cache[@name='offlineSessions']/@owners">
|
||||||
|
<xsl:attribute name="owners">
|
||||||
|
<xsl:value-of select="$offlineSessionCacheOwners"/>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="//i:cache-container/i:distributed-cache[@name='loginFailures']/@owners">
|
||||||
|
<xsl:attribute name="owners">
|
||||||
|
<xsl:value-of select="$loginFailureCacheOwners"/>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Copy everything else. -->
|
||||||
|
<xsl:template match="@*|node()">
|
||||||
|
<xsl:copy>
|
||||||
|
<xsl:apply-templates select="@*|node()" />
|
||||||
|
</xsl:copy>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
</xsl:stylesheet>
|
|
@ -54,6 +54,13 @@
|
||||||
<module>eap7</module>
|
<module>eap7</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>auth-server-eap7-cluster</id>
|
||||||
|
<modules>
|
||||||
|
<module>eap7</module>
|
||||||
|
<module>wildfly-balancer</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -18,8 +18,8 @@ package org.keycloak.testsuite.auth.page.account;
|
||||||
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
|
||||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||||
|
import org.keycloak.testsuite.page.PageWithLogOutAction;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -29,7 +29,7 @@ import org.openqa.selenium.support.FindBy;
|
||||||
* @author <a href="mailto:pmensik@redhat.com">Petr Mensik</a>
|
* @author <a href="mailto:pmensik@redhat.com">Petr Mensik</a>
|
||||||
* @author tkyjovsk
|
* @author tkyjovsk
|
||||||
*/
|
*/
|
||||||
public class AccountManagement extends AuthRealm {
|
public class AccountManagement extends AuthRealm implements PageWithLogOutAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UriBuilder createUriBuilder() {
|
public UriBuilder createUriBuilder() {
|
||||||
|
@ -76,7 +76,12 @@ public class AccountManagement extends AuthRealm {
|
||||||
public void signOut() {
|
public void signOut() {
|
||||||
signOutLink.click();
|
signOutLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logOut() {
|
||||||
|
signOut();
|
||||||
|
}
|
||||||
|
|
||||||
public void account() {
|
public void account() {
|
||||||
accountLink.click();
|
accountLink.click();
|
||||||
}
|
}
|
||||||
|
@ -108,4 +113,5 @@ public class AccountManagement extends AuthRealm {
|
||||||
public void waitForAccountLinkPresent() {
|
public void waitForAccountLinkPresent() {
|
||||||
waitUntilElement(accountLink, "account link should be present").is().present();
|
waitUntilElement(accountLink, "account link should be present").is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
|
||||||
import org.keycloak.testsuite.auth.page.login.PageWithLoginUrl;
|
import org.keycloak.testsuite.auth.page.login.PageWithLoginUrl;
|
||||||
import org.keycloak.testsuite.console.page.fragment.Menu;
|
import org.keycloak.testsuite.console.page.fragment.Menu;
|
||||||
import org.keycloak.testsuite.console.page.fragment.ModalDialog;
|
import org.keycloak.testsuite.console.page.fragment.ModalDialog;
|
||||||
|
import org.keycloak.testsuite.page.PageWithLogOutAction;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -32,8 +33,8 @@ import org.openqa.selenium.support.FindBy;
|
||||||
*
|
*
|
||||||
* @author Petr Mensik
|
* @author Petr Mensik
|
||||||
*/
|
*/
|
||||||
public class AdminConsole extends AuthServer implements PageWithLoginUrl {
|
public class AdminConsole extends AuthServer implements PageWithLoginUrl, PageWithLogOutAction {
|
||||||
|
|
||||||
public static final String ADMIN_REALM = "adminRealm";
|
public static final String ADMIN_REALM = "adminRealm";
|
||||||
|
|
||||||
public AdminConsole() {
|
public AdminConsole() {
|
||||||
|
@ -56,7 +57,7 @@ public class AdminConsole extends AuthServer implements PageWithLoginUrl {
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
private Menu menu;
|
private Menu menu;
|
||||||
|
|
||||||
@FindBy(xpath = "//div[@class='modal-dialog']")
|
@FindBy(xpath = "//div[@class='modal-dialog']")
|
||||||
protected ModalDialog modalDialog;
|
protected ModalDialog modalDialog;
|
||||||
|
|
||||||
|
@ -79,7 +80,8 @@ public class AdminConsole extends AuthServer implements PageWithLoginUrl {
|
||||||
|
|
||||||
@FindBy(css = "navbar-brand")
|
@FindBy(css = "navbar-brand")
|
||||||
protected WebElement brandLink;
|
protected WebElement brandLink;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void logOut() {
|
public void logOut() {
|
||||||
menu.logOut();
|
menu.logOut();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.keycloak.testsuite.page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author tkyjovsk
|
||||||
|
*/
|
||||||
|
public interface PageWithLogOutAction {
|
||||||
|
|
||||||
|
public void logOut();
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,19 @@
|
||||||
package org.keycloak.testsuite.cluster;
|
package org.keycloak.testsuite.cluster;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||||
import org.openqa.selenium.Cookie;
|
import org.openqa.selenium.Cookie;
|
||||||
|
import org.keycloak.testsuite.page.AbstractPage;
|
||||||
|
import org.keycloak.testsuite.page.PageWithLogOutAction;
|
||||||
|
import org.junit.Before;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -20,77 +22,131 @@ import org.openqa.selenium.Cookie;
|
||||||
public class SessionFailoverClusterTest extends AbstractClusterTest {
|
public class SessionFailoverClusterTest extends AbstractClusterTest {
|
||||||
|
|
||||||
public static final String KEYCLOAK_SESSION_COOKIE = "KEYCLOAK_SESSION";
|
public static final String KEYCLOAK_SESSION_COOKIE = "KEYCLOAK_SESSION";
|
||||||
public static final String KEYCLOAK_IDENTITY_COOKIE = "KEYCLOAK_IDENTITY";
|
|
||||||
|
public static final Integer SESSION_CACHE_OWNERS = Integer.parseInt(System.getProperty("session.cache.owners", "1"));
|
||||||
|
public static final Integer OFFLINE_SESSION_CACHE_OWNERS = Integer.parseInt(System.getProperty("offline.session.cache.owners", "1"));
|
||||||
|
public static final Integer LOGIN_FAILURES_CACHE_OWNERS = Integer.parseInt(System.getProperty("login.failure.cache.owners", "1"));
|
||||||
|
|
||||||
|
public static final Integer REBALANCE_WAIT = Integer.parseInt(System.getProperty("rebalance.wait", "5000"));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Before
|
||||||
@Ignore("work in progress") // only works with owners="2" at the moment
|
public void beforeSessionFailover() {
|
||||||
public void sessionFailover() {
|
log.info("Initial node failure");
|
||||||
|
|
||||||
// LOGIN
|
|
||||||
accountPage.navigateTo();
|
|
||||||
driver.navigate().refresh();
|
|
||||||
pause(3000);
|
|
||||||
loginPage.form().login(ADMIN, ADMIN);
|
|
||||||
assertCurrentUrlStartsWith(accountPage);
|
|
||||||
|
|
||||||
Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
|
||||||
assertNotNull(sessionCookie);
|
|
||||||
|
|
||||||
failure();
|
failure();
|
||||||
|
pause(REBALANCE_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
// check if session survived backend failure
|
@Test
|
||||||
|
public void sessionFailover() {
|
||||||
|
|
||||||
|
boolean expectSuccessfulFailover = SESSION_CACHE_OWNERS >= getClusterSize();
|
||||||
|
|
||||||
|
log.info("SESSION FAILOVER TEST: cluster size = " + getClusterSize() + ", session-cache owners = " + SESSION_CACHE_OWNERS
|
||||||
|
+ " --> Testsing for " + (expectSuccessfulFailover ? "" : "UN") + "SUCCESSFUL session failover.");
|
||||||
|
|
||||||
|
assertEquals(2, getClusterSize());
|
||||||
|
|
||||||
driver.navigate().refresh();
|
sessionFailover(expectSuccessfulFailover);
|
||||||
pause(3000);
|
}
|
||||||
|
|
||||||
assertCurrentUrlStartsWith(accountPage);
|
|
||||||
Cookie sessionCookieAfterFailover = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
|
||||||
assertNotNull(sessionCookieAfterFailover);
|
|
||||||
assertEquals(sessionCookieAfterFailover.getValue(), sessionCookie.getValue());
|
|
||||||
|
|
||||||
failback();
|
protected void sessionFailover(boolean expectSuccessfulFailover) {
|
||||||
iterateCurrentFailNode();
|
|
||||||
|
|
||||||
// check if session survived backend failback
|
// LOGIN
|
||||||
driver.navigate().refresh();
|
Cookie sessionCookie = login(accountPage);
|
||||||
pause(3000);
|
|
||||||
assertCurrentUrlStartsWith(accountPage);
|
switchFailedNode();
|
||||||
Cookie sessionCookieAfterFailback = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
|
||||||
assertNotNull(sessionCookieAfterFailback);
|
// VERIFY
|
||||||
assertEquals(sessionCookieAfterFailover.getValue(), sessionCookie.getValue());
|
if (expectSuccessfulFailover) {
|
||||||
|
verifyLoggedIn(accountPage, sessionCookie);
|
||||||
|
} else {
|
||||||
|
verifyLoggedOut(accountPage);
|
||||||
|
// FIXME test fails if I put re-login here
|
||||||
|
}
|
||||||
|
|
||||||
|
switchFailedNode();
|
||||||
|
|
||||||
|
// VERIFY again
|
||||||
|
if (expectSuccessfulFailover) {
|
||||||
|
verifyLoggedIn(accountPage, sessionCookie);
|
||||||
|
} else {
|
||||||
|
verifyLoggedOut(accountPage);
|
||||||
|
login(accountPage);
|
||||||
|
}
|
||||||
|
|
||||||
// LOGOUT
|
// LOGOUT
|
||||||
accountPage.navigateTo();
|
logout(accountPage);
|
||||||
accountPage.signOut();
|
verifyLoggedOut(accountPage);
|
||||||
|
|
||||||
assertCurrentUrlDoesntStartWith(accountPage);
|
switchFailedNode();
|
||||||
masterRealmPage.navigateTo();
|
|
||||||
sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
|
||||||
assertNull(sessionCookie);
|
|
||||||
|
|
||||||
failure();
|
// VERIFY
|
||||||
|
verifyLoggedOut(accountPage);
|
||||||
// check if session survived backend failure
|
|
||||||
driver.navigate().refresh();
|
}
|
||||||
pause(3000);
|
|
||||||
assertCurrentUrlDoesntStartWith(accountPage);
|
/**
|
||||||
masterRealmPage.navigateTo();
|
* failure --> failback --> failure of next node
|
||||||
sessionCookieAfterFailover = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
*/
|
||||||
assertNull(sessionCookieAfterFailover);
|
protected void switchFailedNode() {
|
||||||
|
assertFalse(controller.isStarted(getCurrentFailNode().getQualifier()));
|
||||||
|
|
||||||
failback();
|
failback();
|
||||||
|
pause(REBALANCE_WAIT);
|
||||||
// check if session survived backend failback
|
|
||||||
driver.navigate().refresh();
|
iterateCurrentFailNode();
|
||||||
pause(3000);
|
|
||||||
assertCurrentUrlDoesntStartWith(accountPage);
|
failure();
|
||||||
|
pause(REBALANCE_WAIT);
|
||||||
|
|
||||||
|
assertFalse(controller.isStarted(getCurrentFailNode().getQualifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Cookie login(AbstractPage targetPage) {
|
||||||
|
targetPage.navigateTo();
|
||||||
|
assertCurrentUrlStartsWith(loginPage);
|
||||||
|
loginPage.form().login(ADMIN, ADMIN);
|
||||||
|
assertCurrentUrlStartsWith(targetPage);
|
||||||
|
Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
||||||
|
assertNotNull(sessionCookie);
|
||||||
|
return sessionCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logout(AbstractPage targetPage) {
|
||||||
|
if (!(targetPage instanceof PageWithLogOutAction)) {
|
||||||
|
throw new IllegalArgumentException(targetPage.getClass().getSimpleName() + " must implement PageWithLogOutAction interface");
|
||||||
|
}
|
||||||
|
targetPage.navigateTo();
|
||||||
|
assertCurrentUrlStartsWith(targetPage);
|
||||||
|
((PageWithLogOutAction) targetPage).logOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Cookie verifyLoggedIn(AbstractPage targetPage, Cookie sessionCookieForVerification) {
|
||||||
|
// verify on realm path
|
||||||
masterRealmPage.navigateTo();
|
masterRealmPage.navigateTo();
|
||||||
sessionCookieAfterFailback = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
Cookie sessionCookieOnRealmPath = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
||||||
assertNull(sessionCookieAfterFailback);
|
assertNotNull(sessionCookieOnRealmPath);
|
||||||
|
assertEquals(sessionCookieOnRealmPath.getValue(), sessionCookieForVerification.getValue());
|
||||||
|
// verify on target page
|
||||||
|
targetPage.navigateTo();
|
||||||
|
assertCurrentUrlStartsWith(targetPage);
|
||||||
|
Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
||||||
|
assertNotNull(sessionCookie);
|
||||||
|
assertEquals(sessionCookie.getValue(), sessionCookieForVerification.getValue());
|
||||||
|
return sessionCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void verifyLoggedOut(AbstractPage targetPage) {
|
||||||
|
// verify on target page
|
||||||
|
targetPage.navigateTo();
|
||||||
|
driver.navigate().refresh();
|
||||||
|
assertCurrentUrlStartsWith(loginPage);
|
||||||
|
Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE);
|
||||||
|
assertNull(sessionCookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,66 @@
|
||||||
</configuration>
|
</configuration>
|
||||||
</container>
|
</container>
|
||||||
|
|
||||||
|
<group qualifier="auth-server-eap7-cluster">
|
||||||
|
<container qualifier="auth-server-eap7-balancer" mode="suite" >
|
||||||
|
<configuration>
|
||||||
|
<property name="enabled">${auth.server.eap7.cluster}</property>
|
||||||
|
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||||
|
<property name="jbossHome">${keycloak.balancer.home}</property>
|
||||||
|
<property name="jbossArguments">
|
||||||
|
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||||
|
</property>
|
||||||
|
<property name="javaVmArguments">
|
||||||
|
-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m
|
||||||
|
-Djava.net.preferIPv4Stack=true
|
||||||
|
</property>
|
||||||
|
<property name="outputToConsole">${frontend.console.output}</property>
|
||||||
|
<property name="managementPort">${auth.server.management.port}</property>
|
||||||
|
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||||
|
</configuration>
|
||||||
|
</container>
|
||||||
|
<container qualifier="auth-server-eap7-backend1" mode="manual" >
|
||||||
|
<configuration>
|
||||||
|
<property name="enabled">${auth.server.eap7.cluster}</property>
|
||||||
|
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||||
|
<property name="jbossHome">${keycloak.backend1.home}</property>
|
||||||
|
<property name="serverConfig">standalone-ha.xml</property>
|
||||||
|
<property name="jbossArguments">
|
||||||
|
-Djboss.socket.binding.port-offset=${auth.server.backend1.port.offset}
|
||||||
|
-Djboss.node.name=node1
|
||||||
|
${adapter.test.props}
|
||||||
|
</property>
|
||||||
|
<property name="javaVmArguments">
|
||||||
|
-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m
|
||||||
|
-Djava.net.preferIPv4Stack=true
|
||||||
|
</property>
|
||||||
|
<property name="outputToConsole">${backends.console.output}</property>
|
||||||
|
<property name="managementPort">${auth.server.backend1.management.port}</property>
|
||||||
|
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||||
|
</configuration>
|
||||||
|
</container>
|
||||||
|
<container qualifier="auth-server-eap7-backend2" mode="manual" >
|
||||||
|
<configuration>
|
||||||
|
<property name="enabled">${auth.server.eap7.cluster}</property>
|
||||||
|
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||||
|
<property name="jbossHome">${keycloak.backend2.home}</property>
|
||||||
|
<property name="serverConfig">standalone-ha.xml</property>
|
||||||
|
<property name="jbossArguments">
|
||||||
|
-Djboss.socket.binding.port-offset=${auth.server.backend2.port.offset}
|
||||||
|
-Djboss.node.name=node2
|
||||||
|
${adapter.test.props}
|
||||||
|
</property>
|
||||||
|
<property name="javaVmArguments">
|
||||||
|
-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m
|
||||||
|
-Djava.net.preferIPv4Stack=true
|
||||||
|
</property>
|
||||||
|
<property name="outputToConsole">${backends.console.output}</property>
|
||||||
|
<property name="managementPort">${auth.server.backend2.management.port}</property>
|
||||||
|
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||||
|
</configuration>
|
||||||
|
</container>
|
||||||
|
</group>
|
||||||
|
|
||||||
<!-- PREVIOUS VERSIONS OF KEYCLOAK FOR MIGRATION TESTS -->
|
<!-- PREVIOUS VERSIONS OF KEYCLOAK FOR MIGRATION TESTS -->
|
||||||
|
|
||||||
<container qualifier="auth-server-wildfly-kc16" mode="manual" >
|
<container qualifier="auth-server-wildfly-kc16" mode="manual" >
|
||||||
|
|
|
@ -664,6 +664,7 @@
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>auth-server-eap7</id>
|
<id>auth-server-eap7</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -743,6 +744,129 @@
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>auth-server-eap7-cluster</id>
|
||||||
|
<properties>
|
||||||
|
<!--disable exclusion pattern for cluster test which is enabled by default in base/pom.xml-->
|
||||||
|
<exclude.cluster>-</exclude.cluster>
|
||||||
|
|
||||||
|
<auth.server.container>auth-server-eap7-cluster</auth.server.container>
|
||||||
|
<startup.timeout.sec>300</startup.timeout.sec>
|
||||||
|
<adapter.test.props/>
|
||||||
|
<h2.version>1.3.173</h2.version>
|
||||||
|
|
||||||
|
<keycloak.balancer.home>${containers.home}/balancer/wildfly-balancer-${project.version}</keycloak.balancer.home>
|
||||||
|
<keycloak.backend1.home>${containers.home}/node1/keycloak-${version.server.dist}</keycloak.backend1.home>
|
||||||
|
<keycloak.backend2.home>${containers.home}/node2/keycloak-${version.server.dist}</keycloak.backend2.home>
|
||||||
|
|
||||||
|
<keycloak.home>${keycloak.backend1.home}</keycloak.home>
|
||||||
|
<jboss.server.config.dir>${keycloak.home}/standalone/configuration</jboss.server.config.dir>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wildfly</groupId>
|
||||||
|
<artifactId>wildfly-arquillian-container-managed</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-enforcer-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>enforce-properties</id>
|
||||||
|
<goals>
|
||||||
|
<goal>enforce</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<rules>
|
||||||
|
<requireProperty>
|
||||||
|
<property>version.server.dist</property>
|
||||||
|
</requireProperty>
|
||||||
|
</rules>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<run.h2>true</run.h2>
|
||||||
|
|
||||||
|
<auth.server.eap7.cluster>true</auth.server.eap7.cluster>
|
||||||
|
<auth.server.undertow>false</auth.server.undertow>
|
||||||
|
<adapter.test.props>${adapter.test.props}</adapter.test.props>
|
||||||
|
|
||||||
|
<keycloak.balancer.home>${keycloak.balancer.home}</keycloak.balancer.home>
|
||||||
|
<keycloak.backend1.home>${keycloak.backend1.home}</keycloak.backend1.home>
|
||||||
|
<keycloak.backend2.home>${keycloak.backend2.home}</keycloak.backend2.home>
|
||||||
|
|
||||||
|
<!--100-->
|
||||||
|
<auth.server.backend1.port.offset>101</auth.server.backend1.port.offset>
|
||||||
|
<auth.server.backend2.port.offset>102</auth.server.backend2.port.offset>
|
||||||
|
<!--8180-->
|
||||||
|
<auth.server.backend1.http.port>8181</auth.server.backend1.http.port>
|
||||||
|
<auth.server.backend2.http.port>8182</auth.server.backend2.http.port>
|
||||||
|
<!--8543-->
|
||||||
|
<auth.server.backend1.https.port>8544</auth.server.backend1.https.port>
|
||||||
|
<auth.server.backend2.https.port>8545</auth.server.backend2.https.port>
|
||||||
|
<!--10090-->
|
||||||
|
<auth.server.backend1.management.port>10091</auth.server.backend1.management.port>
|
||||||
|
<auth.server.backend2.management.port>10092</auth.server.backend2.management.port>
|
||||||
|
<!--10099-->
|
||||||
|
<auth.server.backend1.management.port.jmx>10100</auth.server.backend1.management.port.jmx>
|
||||||
|
<auth.server.backend2.management.port.jmx>10101</auth.server.backend2.management.port.jmx>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>unpack-auth-server-wildfly</id>
|
||||||
|
<phase>generate-test-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.keycloak.testsuite</groupId>
|
||||||
|
<artifactId>integration-arquillian-server-wildfly-balancer</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<outputDirectory>${containers.home}/balancer</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.keycloak.testsuite</groupId>
|
||||||
|
<artifactId>integration-arquillian-server-eap7</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<outputDirectory>${containers.home}/node1</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.keycloak.testsuite</groupId>
|
||||||
|
<artifactId>integration-arquillian-server-eap7</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<outputDirectory>${containers.home}/node2</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
<overWriteIfNewer>true</overWriteIfNewer>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
<!-- Profiles for migration tests-->
|
<!-- Profiles for migration tests-->
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
|
|
Loading…
Reference in a new issue