Replace PhantomJS by HtmlUnit

Closes #9979

Co-authored-by: Jon Koops <jonkoops@gmail.com>
Signed-off-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Martin Bartoš 2024-05-27 17:56:07 +02:00 committed by Marek Posolda
parent b1a90972b6
commit 76a6733f0a
26 changed files with 132 additions and 224 deletions

View file

@ -24,10 +24,6 @@ runs:
with: with:
create-cache-if-it-doesnt-exist: true create-cache-if-it-doesnt-exist: true
- id: phantomjs-cache
name: PhantomJS cache
uses: ./.github/actions/phantomjs-cache
- id: frontend-plugin-cache - id: frontend-plugin-cache
name: Frontend Plugin Cache name: Frontend Plugin Cache
uses: ./.github/actions/frontend-plugin-cache uses: ./.github/actions/frontend-plugin-cache

View file

@ -25,10 +25,6 @@ runs:
name: Maven cache name: Maven cache
uses: ./.github/actions/maven-cache uses: ./.github/actions/maven-cache
- id: phantomjs-cache
name: PhantomJS cache
uses: ./.github/actions/phantomjs-cache
- id: frontend-plugin-cache - id: frontend-plugin-cache
name: Frontend Plugin Cache name: Frontend Plugin Cache
uses: ./.github/actions/frontend-plugin-cache uses: ./.github/actions/frontend-plugin-cache

View file

@ -1,26 +0,0 @@
name: PhantomJS Cache
description: Caches PhantomJS driver
inputs:
version:
description: PhantomJS Driver version
required: false
default: 2.1.1
runs:
using: composite
steps:
- id: cache-phantomjs-driver
name: PhantomJS Driver cache
uses: actions/cache@v4
with:
path: ~/.arquillian/drone
key: phantomjs-${{ inputs.version }}
- id: download-phantomjs-driver
name: Download PhantomJS Driver
if: steps.cache-phantomjs-driver.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p ~/.arquillian/drone/phantomjs/${{ inputs.version }}/
curl -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-${{ inputs.version }}-linux-x86_64.tar.bz2 --output ~/.arquillian/drone/phantomjs/${{ inputs.version }}/phantomjs-${{ inputs.version }}-linux-x86_64.tar.bz2

View file

@ -626,30 +626,6 @@
<dballocator.skip>false</dballocator.skip> <dballocator.skip>false</dballocator.skip>
</properties> </properties>
</profile> </profile>
<!-- Workaround for issues related to PhantomJS in some newer linux environment. See for example here for more details https://github.com/nodejs/node/issues/43132 -->
<profile>
<id>phantomjs-openssl-workaround</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<environmentVariables>
<OPENSSL_CONF>/dev/null</OPENSSL_CONF>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles> </profiles>
</project> </project>

View file

@ -63,7 +63,7 @@
<goal>copy-resources</goal> <goal>copy-resources</goal>
</goals> </goals>
<configuration> <configuration>
<outputDirectory>${auth.server.home}</outputDirectory> <outputDirectory>${auth.server.home}/conf</outputDirectory>
<resources> <resources>
<resource> <resource>
<directory>${common.resources}/keystore</directory> <directory>${common.resources}/keystore</directory>
@ -71,6 +71,7 @@
<include>ca.crt</include> <include>ca.crt</include>
<include>client.crt</include> <include>client.crt</include>
<include>client.key</include> <include>client.key</include>
<include>client.p12</include>
<include>client-ca.crt</include> <include>client-ca.crt</include>
<include>client-ca.key</include> <include>client-ca.key</include>
<include>*.crl</include> <include>*.crl</include>
@ -80,7 +81,9 @@
<directory>${common.resources}/pki/root/ca</directory> <directory>${common.resources}/pki/root/ca</directory>
<includes> <includes>
<include>certs/clients/test-user-san@localhost.cert.pem</include> <include>certs/clients/test-user-san@localhost.cert.pem</include>
<include>certs/clients/test-user-san@localhost.p12</include>
<include>certs/clients/test-user@localhost.key.pem</include> <include>certs/clients/test-user@localhost.key.pem</include>
<include>certs/clients/test-user-san-cert-test-user-key@localhost.p12</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>

View file

@ -46,9 +46,9 @@
<systemrules.version>1.19.0</systemrules.version> <systemrules.version>1.19.0</systemrules.version>
<common.resources>${basedir}/../../servers/auth-server/common</common.resources> <common.resources>${basedir}/../../servers/auth-server/common</common.resources>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven.compiler.release>11</maven.compiler.release> <maven.compiler.release>17</maven.compiler.release>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
</properties> </properties>
<dependencies> <dependencies>

View file

@ -39,10 +39,16 @@ import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.RemoteWebDriver;
import java.io.File;
import java.net.MalformedURLException;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
public class KeycloakDronePostSetup { public class KeycloakDronePostSetup {
public static final String HTML_UNIT_SSL_KEYSTORE_PROP = "htmlunit-ssl-keystore";
public static final String HTML_UNIT_SSL_KEYSTORE_PASSWORD_PROP = "htmlunit-ssl-keystore-password";
public static final String HTML_UNIT_SSL_KEYSTORE_TYPE_PROP = "htmlunit-ssl-keystore-type";
@Inject @Inject
@ClassScoped // needed in BrowserDriverIgnoreDecider @ClassScoped // needed in BrowserDriverIgnoreDecider
@ -54,22 +60,19 @@ public class KeycloakDronePostSetup {
DronePoint<?> dronePoint = event.getDronePoint(); DronePoint<?> dronePoint = event.getDronePoint();
Object drone = droneContext.get(dronePoint).getInstance(); Object drone = droneContext.get(dronePoint).getInstance();
if (drone instanceof RemoteWebDriver) { if (drone instanceof RemoteWebDriver remoteWebDriver) {
RemoteWebDriver remoteWebDriver = (RemoteWebDriver) drone;
log.infof("Detected browser: %s %s", remoteWebDriver.getCapabilities().getBrowserName(), remoteWebDriver.getCapabilities().getBrowserVersion()); log.infof("Detected browser: %s %s", remoteWebDriver.getCapabilities().getBrowserName(), remoteWebDriver.getCapabilities().getBrowserVersion());
webDriverProducer.set(remoteWebDriver); webDriverProducer.set(remoteWebDriver);
} }
if (drone instanceof WebDriver && !(drone instanceof AppiumDriver)) { if (drone instanceof WebDriver webDriver && !(drone instanceof AppiumDriver)) {
WebDriver webDriver = (WebDriver) drone;
configureDriverSettings(webDriver); configureDriverSettings(webDriver);
webDriverProducer.set(webDriver); webDriverProducer.set(webDriver);
} else { } else {
log.warn("Drone is not instanceof WebDriver for a desktop browser! Drone is " + drone); log.warn("Drone is not instanceof WebDriver for a desktop browser! Drone is " + drone);
} }
if (drone instanceof GrapheneProxyInstance) { if (drone instanceof GrapheneProxyInstance droneProxy) {
GrapheneProxyInstance droneProxy = (GrapheneProxyInstance) drone;
if (drone instanceof HtmlUnitDriver) { if (drone instanceof HtmlUnitDriver) {
droneProxy.registerInterceptor(new HtmlUnitInterceptor()); droneProxy.registerInterceptor(new HtmlUnitInterceptor());
} }
@ -89,11 +92,11 @@ public class KeycloakDronePostSetup {
driver.manage().window().maximize(); driver.manage().window().maximize();
configureFirefoxDriver(driver); configureFirefoxDriver(driver);
configureHtmlUnitDriver(driver);
} }
private void configureFirefoxDriver(WebDriver driver) { private void configureFirefoxDriver(WebDriver driver) {
if (driver instanceof FirefoxDriver) { if (driver instanceof FirefoxDriver firefoxDriver) {
FirefoxDriver firefoxDriver = (FirefoxDriver) driver;
Capabilities capabilities = firefoxDriver.getCapabilities(); Capabilities capabilities = firefoxDriver.getCapabilities();
FirefoxOptions options = new FirefoxOptions(capabilities); FirefoxOptions options = new FirefoxOptions(capabilities);
// disables extension automatic updates as we don't need it when running the test suite // disables extension automatic updates as we don't need it when running the test suite
@ -102,6 +105,28 @@ public class KeycloakDronePostSetup {
} }
} }
private void configureHtmlUnitDriver(WebDriver driver) {
if (driver instanceof HtmlUnitDriver htmlUnitDriver) {
final var keystore = System.getProperty(HTML_UNIT_SSL_KEYSTORE_PROP);
final var keystorePassword = System.getProperty(HTML_UNIT_SSL_KEYSTORE_PASSWORD_PROP);
final var keystoreType = System.getProperty(HTML_UNIT_SSL_KEYSTORE_TYPE_PROP);
log.info("Check HtmlUnit driver TLS settings");
if (keystore != null && keystorePassword != null && keystoreType != null) {
log.infof("Keystore '%s', password '%s', type '%s'", keystore, keystorePassword, keystoreType);
var options = htmlUnitDriver.getWebClient().getOptions();
options.setUseInsecureSSL(true);
try {
options.setSSLClientCertificateKeyStore(new File(keystore).toURI().toURL(), keystorePassword, keystoreType);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
}
public static class HtmlUnitInterceptor implements Interceptor { public static class HtmlUnitInterceptor implements Interceptor {
@Override @Override

View file

@ -27,7 +27,6 @@ import org.jboss.arquillian.drone.webdriver.spi.BrowserCapabilities;
import org.jboss.arquillian.drone.webdriver.spi.BrowserCapabilitiesRegistry; import org.jboss.arquillian.drone.webdriver.spi.BrowserCapabilitiesRegistry;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.openqa.selenium.Capabilities; import org.openqa.selenium.Capabilities;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.DesiredCapabilities;
@ -53,7 +52,6 @@ public class KeycloakWebDriverConfigurator {
DesiredCapabilities capabilitiesToAdd = new DesiredCapabilities(); DesiredCapabilities capabilitiesToAdd = new DesiredCapabilities();
updateCapabilityKeys("htmlUnit", webDriverCfg, capabilitiesToAdd); updateCapabilityKeys("htmlUnit", webDriverCfg, capabilitiesToAdd);
updateCapabilityKeys("appium", webDriverCfg, capabilitiesToAdd); updateCapabilityKeys("appium", webDriverCfg, capabilitiesToAdd);
configurePhantomJSDriver(webDriverCfg, capabilitiesToAdd);
acceptAllSSLCerts(webDriverCfg, capabilitiesToAdd); acceptAllSSLCerts(webDriverCfg, capabilitiesToAdd);
BrowserCapabilities browserCap = registryInstance.get().getEntryFor(webDriverCfg.getBrowser()); BrowserCapabilities browserCap = registryInstance.get().getEntryFor(webDriverCfg.getBrowser());
@ -64,21 +62,6 @@ public class KeycloakWebDriverConfigurator {
capabilitiesToAdd.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true); capabilitiesToAdd.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true);
} }
private void configurePhantomJSDriver(WebDriverConfiguration webDriverCfg, DesiredCapabilities capabilitiesToAdd) {
if (!webDriverCfg.getBrowser().equals("phantomjs")) {
return;
}
String cliArgs = System.getProperty("keycloak.phantomjs.cli.args");
if (cliArgs == null) {
cliArgs = "--ignore-ssl-errors=true --web-security=false";
}
capabilitiesToAdd.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, cliArgs);
}
// This is to ensure that default value of capabilities like "version" will be used just for the HtmlUnitDriver, but not for other drivers. // This is to ensure that default value of capabilities like "version" will be used just for the HtmlUnitDriver, but not for other drivers.
// Hence in configs we have "htmlUnit.version" instead of "version" // Hence in configs we have "htmlUnit.version" instead of "version"
private void updateCapabilityKeys(String browser, WebDriverConfiguration webDriverCfg, DesiredCapabilities capabilitiesToAdd, String... exclude) { private void updateCapabilityKeys(String browser, WebDriverConfiguration webDriverCfg, DesiredCapabilities capabilitiesToAdd, String... exclude) {

View file

@ -26,5 +26,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER}) @Target({ElementType.FIELD, ElementType.PARAMETER})
@Qualifier @Qualifier
public @interface PhantomJSBrowser { public @interface HtmlUnitBrowser {
} }

View file

@ -77,8 +77,6 @@ public class ConsoleProtectionTest extends AbstractAdapterTest {
@Before @Before
public void beforeConsoleProtectionTest() throws IOException, OperationException { public void beforeConsoleProtectionTest() throws IOException, OperationException {
Assume.assumeTrue("This testClass doesn't work with phantomjs", !"phantomjs".equals(System.getProperty("js.browser")));
try (OnlineManagementClient clientWorkerNodeClient = AppServerTestEnricher.getManagementClient()) { try (OnlineManagementClient clientWorkerNodeClient = AppServerTestEnricher.getManagementClient()) {
Operations operations = new Operations(clientWorkerNodeClient); Operations operations = new Operations(clientWorkerNodeClient);

View file

@ -1,7 +1,6 @@
package org.keycloak.testsuite.javascript; package org.keycloak.testsuite.javascript;
import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.graphene.page.Page;
import org.junit.Assume;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -318,8 +317,6 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
@Test @Test
public void grantBrowserBasedApp() { public void grantBrowserBasedApp() {
Assume.assumeTrue("This test doesn't work with phantomjs", !"phantomjs".equals(System.getProperty("js.browser")));
ClientResource clientResource = ApiUtil.findClientResourceByClientId(adminClient.realm(REALM_NAME), CLIENT_ID); ClientResource clientResource = ApiUtil.findClientResourceByClientId(adminClient.realm(REALM_NAME), CLIENT_ID);
ClientRepresentation client = clientResource.toRepresentation(); ClientRepresentation client = clientResource.toRepresentation();
try { try {
@ -455,13 +452,10 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
// Possibility of 0 and 401 is caused by this issue: https://issues.redhat.com/browse/KEYCLOAK-12686 // Possibility of 0 and 401 is caused by this issue: https://issues.redhat.com/browse/KEYCLOAK-12686
.sendXMLHttpRequest(request, response -> assertThat(response, hasEntry(is("status"), anyOf(is(0L), is(401L))))) .sendXMLHttpRequest(request, response -> assertThat(response, hasEntry(is("status"), anyOf(is(0L), is(401L)))))
.refresh(); .refresh();
if (!"phantomjs".equals(System.getProperty("js.browser"))) { testExecutor.logInAndInit(defaultArguments(), unauthorizedUser, this::assertInitAuth)
// I have no idea why, but this request doesn't work with phantomjs, it works in chrome .sendXMLHttpRequest(request, output -> assertThat(output, hasEntry("status", 403L)))
testExecutor.logInAndInit(defaultArguments(), unauthorizedUser, this::assertInitAuth) .logout(this::assertOnTestAppUrl)
.sendXMLHttpRequest(request, output -> assertThat(output, hasEntry("status", 403L))) .refresh();
.logout(this::assertOnTestAppUrl)
.refresh();
}
testExecutor.logInAndInit(defaultArguments(), testUser, this::assertInitAuth) testExecutor.logInAndInit(defaultArguments(), testUser, this::assertInitAuth)
.sendXMLHttpRequest(request, assertResponseStatus(200)); .sendXMLHttpRequest(request, assertResponseStatus(200));
} }
@ -711,10 +705,6 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
@Test @Test
public void spaceInRealmNameTest() { public void spaceInRealmNameTest() {
// Unfortunately this test doesn't work on phantomjs
// it looks like phantomjs double encode %20 => %25%20
Assume.assumeTrue("This test doesn't work with phantomjs", !"phantomjs".equals(System.getProperty("js.browser")));
try { try {
adminClient.realm(REALM_NAME).update(RealmBuilder.edit(adminClient.realm(REALM_NAME).toRepresentation()).name(SPACE_REALM_NAME).build()); adminClient.realm(REALM_NAME).update(RealmBuilder.edit(adminClient.realm(REALM_NAME).toRepresentation()).name(SPACE_REALM_NAME).build());

View file

@ -33,7 +33,7 @@ import org.keycloak.testsuite.arquillian.annotation.RestartContainer;
import org.keycloak.testsuite.auth.page.WelcomePage; import org.keycloak.testsuite.auth.page.WelcomePage;
import org.keycloak.testsuite.auth.page.login.OIDCLogin; import org.keycloak.testsuite.auth.page.login.OIDCLogin;
import org.keycloak.testsuite.util.DroneUtils; import org.keycloak.testsuite.util.DroneUtils;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import java.net.InetAddress; import java.net.InetAddress;
@ -54,15 +54,15 @@ import static org.keycloak.testsuite.util.URLUtils.navigateToUri;
public class WelcomePageTest extends AbstractKeycloakTest { public class WelcomePageTest extends AbstractKeycloakTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Page @Page
@PhantomJSBrowser @HtmlUnitBrowser
protected OIDCLogin loginPage; protected OIDCLogin loginPage;
@Page @Page
@PhantomJSBrowser @HtmlUnitBrowser
protected WelcomePage welcomePage; protected WelcomePage welcomePage;
@Override @Override
@ -80,7 +80,7 @@ public class WelcomePageTest extends AbstractKeycloakTest {
Assume.assumeThat("Test skipped", Assume.assumeThat("Test skipped",
suiteContext.getAuthServerInfo().isJBossBased(), suiteContext.getAuthServerInfo().isJBossBased(),
Matchers.is(true)); Matchers.is(true));
DroneUtils.replaceDefaultWebDriver(this, phantomJS); DroneUtils.replaceDefaultWebDriver(this, htmlUnit);
setDefaultPageUriParameters(); setDefaultPageUriParameters();
} }
@ -150,8 +150,7 @@ public class WelcomePageTest extends AbstractKeycloakTest {
public void test_5_AccessCreatedAdminAccount() throws Exception { public void test_5_AccessCreatedAdminAccount() throws Exception {
welcomePage.navigateTo(); welcomePage.navigateTo();
welcomePage.navigateToAdminConsole(); welcomePage.navigateToAdminConsole();
// TODO PhantomJS is not loading the new admin console for some reason, so is not redirecting to the login page. It works with Chrome though. Assert.assertEquals("Keycloak Administration Console", htmlUnit.getTitle());
Assert.assertEquals("Keycloak Administration Console", phantomJS.getTitle());
} }
@Test @Test

View file

@ -18,6 +18,7 @@
package org.keycloak.testsuite.x509; package org.keycloak.testsuite.x509;
import jakarta.ws.rs.core.Response;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.graphene.page.Page;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -62,14 +63,14 @@ import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents; import org.keycloak.testsuite.util.AssertAdminEvents;
import org.keycloak.testsuite.util.ClientBuilder; import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.DroneUtils; import org.keycloak.testsuite.util.DroneUtils;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.testsuite.util.WaitUtils; import org.keycloak.testsuite.util.WaitUtils;
import org.keycloak.userprofile.UserProfileConstants; import org.keycloak.userprofile.UserProfileConstants;
import org.keycloak.utils.StringUtil;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import jakarta.ws.rs.core.Response;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
@ -90,7 +91,11 @@ import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorC
import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN; import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN;
import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN_CN; import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN_CN;
import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN_EMAIL; import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType.SUBJECTDN_EMAIL;
import static org.keycloak.testsuite.drone.KeycloakDronePostSetup.HTML_UNIT_SSL_KEYSTORE_PASSWORD_PROP;
import static org.keycloak.testsuite.drone.KeycloakDronePostSetup.HTML_UNIT_SSL_KEYSTORE_PROP;
import static org.keycloak.testsuite.drone.KeycloakDronePostSetup.HTML_UNIT_SSL_KEYSTORE_TYPE_PROP;
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED; import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED;
import static org.keycloak.utils.StringUtil.isBlank;
/** /**
* @author <a href="mailto:brat000012001@gmail.com">Peter Nalyvayko</a> * @author <a href="mailto:brat000012001@gmail.com">Peter Nalyvayko</a>
@ -126,7 +131,7 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
protected AuthenticationExecutionInfoRepresentation directGrantExecution; protected AuthenticationExecutionInfoRepresentation directGrantExecution;
private static SetSystemProperty phantomjsCliArgs; private static final List<SetSystemProperty> systemProperties = new ArrayList<>(10);
@Rule @Rule
public AssertEvents events = new AssertEvents(this); public AssertEvents events = new AssertEvents(this);
@ -135,15 +140,15 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this); public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this);
@Page @Page
@PhantomJSBrowser @HtmlUnitBrowser
protected AppPage appPage; protected AppPage appPage;
@Page @Page
@PhantomJSBrowser @HtmlUnitBrowser
protected X509IdentityConfirmationPage loginConfirmationPage; protected X509IdentityConfirmationPage loginConfirmationPage;
@Page @Page
@PhantomJSBrowser @HtmlUnitBrowser
protected LoginPage loginPage; protected LoginPage loginPage;
@ -160,48 +165,31 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
@BeforeClass @BeforeClass
public static void onBeforeTestClass() { public static void onBeforeTestClass() {
configurePhantomJS("/ca.crt", "/client.crt", "/client.key", "password"); configureHtmlUnit("/client.p12");
} }
@AfterClass @AfterClass
public static void onAfterTestClass() { public static void onAfterTestClass() {
phantomjsCliArgs.revert(); systemProperties.forEach(SetSystemProperty::revert);
} }
/** protected static void configureHtmlUnit(String keystore) {
* Setup phantom JS to be used for mutual TLS testing. All file paths are relative to "authServerHome" configureHtmlUnit(keystore, "password", "pkcs12");
* }
* @param certificatesPath
* @param clientCertificateFile protected static void configureHtmlUnit(String keystore, String keystorePassword, String keystoreType) {
* @param clientKeyFile
* @param clientKeyPassword
*/
protected static void configurePhantomJS(String certificatesPath, String clientCertificateFile, String clientKeyFile, String clientKeyPassword) {
String authServerHome = getAuthServerHome(); String authServerHome = getAuthServerHome();
if (authServerHome != null && System.getProperty("auth.server.ssl.required") != null) { if (authServerHome != null && System.getProperty("auth.server.ssl.required") != null) {
StringBuilder cliArgs = new StringBuilder(); if (isBlank(keystore) || isBlank(keystorePassword) || isBlank(keystoreType)) {
throw new IllegalArgumentException("You need to specify keystore name, password, and type.");
cliArgs.append("--ignore-ssl-errors=true ");
cliArgs.append("--web-security=false ");
if (certificatesPath != null) {
cliArgs.append("--ssl-certificates-path=").append(authServerHome).append(certificatesPath).append(" ");
} }
if (clientCertificateFile != null) { systemProperties.add(new SetSystemProperty(HTML_UNIT_SSL_KEYSTORE_PROP, authServerHome + keystore));
cliArgs.append("--ssl-client-certificate-file=").append(authServerHome).append(clientCertificateFile).append(" "); systemProperties.add(new SetSystemProperty(HTML_UNIT_SSL_KEYSTORE_PASSWORD_PROP, keystorePassword));
} systemProperties.add(new SetSystemProperty(HTML_UNIT_SSL_KEYSTORE_TYPE_PROP, keystoreType));
if (clientKeyFile != null) {
cliArgs.append("--ssl-client-key-file=").append(authServerHome).append(clientKeyFile).append(" ");
}
if (clientKeyPassword != null) {
cliArgs.append("--ssl-client-key-passphrase=").append(clientKeyPassword).append(" ");
}
phantomjsCliArgs = new SetSystemProperty("keycloak.phantomjs.cli.args", cliArgs.toString());
} }
} }
private static boolean isAuthServerJBoss() { private static boolean isAuthServerJBoss() {
return Boolean.parseBoolean(System.getProperty("auth.server.jboss")); return Boolean.parseBoolean(System.getProperty("auth.server.jboss"));
} }
@ -219,6 +207,10 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
authServerHome = authServerHome + "/standalone/configuration"; authServerHome = authServerHome + "/standalone/configuration";
} }
if (AuthServerTestEnricher.isAuthServerQuarkus()) {
authServerHome = authServerHome + "/conf";
}
return authServerHome; return authServerHome;
} }

View file

@ -29,7 +29,7 @@ import org.keycloak.models.Constants;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.util.ContainerAssume; import org.keycloak.testsuite.util.ContainerAssume;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -46,13 +46,13 @@ public class X509BrowserCRLTest extends AbstractX509AuthenticationTest {
public static CRLRule crlRule = new CRLRule(); public static CRLRule crlRule = new CRLRule();
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@ -176,6 +176,9 @@ public class X509BrowserCRLTest extends AbstractX509AuthenticationTest {
@Test @Test
public void loginWithMultipleRevocationListsUsingInvalidCert() { public void loginWithMultipleRevocationListsUsingInvalidCert() {
// not sure why it is failing on Undertow - works with Quarkus
ContainerAssume.assumeNotAuthServerUndertow();
X509AuthenticatorConfigModel config = X509AuthenticatorConfigModel config =
new X509AuthenticatorConfigModel() new X509AuthenticatorConfigModel()
.setCRLEnabled(true) .setCRLEnabled(true)

View file

@ -27,10 +27,9 @@ import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
* @author Sebastian Loesch * @author Sebastian Loesch
* @date 02/14/2019 * @date 02/14/2019
@ -39,12 +38,12 @@ import org.openqa.selenium.WebDriver;
public class X509BrowserLoginIssuerDnTest extends AbstractX509AuthenticationTest { public class X509BrowserLoginIssuerDnTest extends AbstractX509AuthenticationTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@BeforeClass @BeforeClass
@ -59,8 +58,7 @@ public class X509BrowserLoginIssuerDnTest extends AbstractX509AuthenticationTest
@BeforeClass @BeforeClass
public static void onBeforeTestClass() { public static void onBeforeTestClass() {
configurePhantomJS("/ca.crt", "/certs/clients/test-user-san@localhost.cert.pem", configureHtmlUnit("/certs/clients/test-user-san-cert-test-user-key@localhost.p12");
"/certs/clients/test-user@localhost.key.pem", "password");
} }
private String setup(boolean canonicalDnEnabled) throws Exception { private String setup(boolean canonicalDnEnabled) throws Exception {

View file

@ -20,8 +20,9 @@ package org.keycloak.testsuite.x509;
import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.api.annotation.Drone;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
@ -33,18 +34,17 @@ import org.openqa.selenium.WebDriver;
public class X509BrowserLoginSubjectAltNameTest extends AbstractX509AuthenticationTest { public class X509BrowserLoginSubjectAltNameTest extends AbstractX509AuthenticationTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@BeforeClass @BeforeClass
public static void onBeforeTestClass() { public static void onBeforeTestClass() {
configurePhantomJS("/ca.crt", "/certs/clients/test-user-san@localhost.cert.pem", configureHtmlUnit("/certs/clients/test-user-san-cert-test-user-key@localhost.p12");
"/certs/clients/test-user@localhost.key.pem", "password");
} }
@Test @Test

View file

@ -17,17 +17,12 @@
package org.keycloak.testsuite.x509; package org.keycloak.testsuite.x509;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.api.annotation.Drone;
import org.junit.Assume;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
@ -38,28 +33,17 @@ import org.openqa.selenium.WebDriver;
public class X509BrowserLoginSubjectDnTest extends AbstractX509AuthenticationTest { public class X509BrowserLoginSubjectDnTest extends AbstractX509AuthenticationTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
}
@BeforeClass
public static void checkAssumption() {
try {
CertificateFactory.getInstance("X.509", "SUN");
}
catch (CertificateException | NoSuchProviderException e) {
Assume.assumeNoException("Test assumes the SUN security provider", e);
}
} }
@BeforeClass @BeforeClass
public static void onBeforeTestClass() { public static void onBeforeTestClass() {
configurePhantomJS("/ca.crt", "/certs/clients/test-user-san@localhost.cert.pem", configureHtmlUnit("/certs/clients/test-user-san-cert-test-user-key@localhost.p12");
"/certs/clients/test-user@localhost.key.pem", "password");
} }
private String setup(boolean canonicalDnEnabled) throws Exception { private String setup(boolean canonicalDnEnabled) throws Exception {

View file

@ -20,7 +20,7 @@ package org.keycloak.testsuite.x509;
import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.api.annotation.Drone;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -58,18 +58,15 @@ import org.openqa.selenium.WebDriver;
public class X509BrowserLoginTest extends AbstractX509AuthenticationTest { public class X509BrowserLoginTest extends AbstractX509AuthenticationTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@Test @Test
public void loginAsUserFromCertSubjectEmail() throws Exception { public void loginAsUserFromCertSubjectEmail() throws Exception {
// Login using an e-mail extracted from certificate's subject DN // Login using an e-mail extracted from certificate's subject DN

View file

@ -20,7 +20,6 @@ package org.keycloak.testsuite.x509;
import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.api.annotation.Drone;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -32,11 +31,10 @@ import org.keycloak.representations.AccessToken;
import org.keycloak.representations.RefreshToken; import org.keycloak.representations.RefreshToken;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.sessions.AuthenticationSessionProvider;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.util.ContainerAssume; import org.keycloak.testsuite.util.ContainerAssume;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@ -58,12 +56,12 @@ import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorC
public class X509DirectGrantTest extends AbstractX509AuthenticationTest { public class X509DirectGrantTest extends AbstractX509AuthenticationTest {
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@Test @Test

View file

@ -14,7 +14,7 @@ import org.jboss.arquillian.drone.api.annotation.Drone;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel; import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
@ -35,12 +35,12 @@ public class X509OCSPResponderFailOpenTest extends AbstractX509AuthenticationTes
private Undertow ocspResponder; private Undertow ocspResponder;
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@Test @Test

View file

@ -37,7 +37,7 @@ import static org.keycloak.authentication.authenticators.x509.X509AuthenticatorC
import io.undertow.Undertow; import io.undertow.Undertow;
import io.undertow.server.handlers.BlockingHandler; import io.undertow.server.handlers.BlockingHandler;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
@ -58,12 +58,12 @@ public class X509OCSPResponderSpecificCertTest extends AbstractX509Authenticatio
private Undertow ocspResponder; private Undertow ocspResponder;
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@Test @Test

View file

@ -44,7 +44,7 @@ import java.nio.file.Paths;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
@ -65,12 +65,12 @@ public class X509OCSPResponderTest extends AbstractX509AuthenticationTest {
private Undertow ocspResponder; private Undertow ocspResponder;
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlUnit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlUnit);
} }
@Test @Test

View file

@ -24,7 +24,7 @@ import org.junit.Test;
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel; import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel;
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.IdentityMapperType; import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.IdentityMapperType;
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType; import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType;
import org.keycloak.testsuite.util.PhantomJSBrowser; import org.keycloak.testsuite.util.HtmlUnitBrowser;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
/** /**
@ -37,18 +37,18 @@ public class X509SingleCertificateBrowserCRLTest extends AbstractX509Authenticat
public static CRLRule crlRule = new CRLRule(); public static CRLRule crlRule = new CRLRule();
@Drone @Drone
@PhantomJSBrowser @HtmlUnitBrowser
private WebDriver phantomJS; private WebDriver htmlunit;
@Before @Before
public void replaceTheDefaultDriver() { public void replaceTheDefaultDriver() {
replaceDefaultWebDriver(phantomJS); replaceDefaultWebDriver(htmlunit);
} }
@BeforeClass @BeforeClass
public static void onBeforeTestClass() { public static void onBeforeTestClass() {
// configure single certificate without CA cert // configure single certificate without CA cert
configurePhantomJS(null, "/client-ca.crt", "/client-ca.key", "password"); configureHtmlUnit("/client-ca.jks", "secret", "jks");
} }
@Test @Test

View file

@ -91,9 +91,10 @@
<property name="chromeDriverVersion">${chromeDriverVersion}</property> <property name="chromeDriverVersion">${chromeDriverVersion}</property>
</extension> </extension>
<extension qualifier="webdriver-phantomjsbrowser"> <extension qualifier="webdriver-htmlunitbrowser">
<property name="browser">phantomjs</property> <property name="browser">htmlunit</property>
<property name="downloadBinaries">${webdriverDownloadBinaries}</property> <property name="htmlUnit.version">${htmlUnitBrowserVersion}</property>
<property name="htmlUnitWebClientOptions">cssEnabled=false;historyPageCacheLimit=1</property>
</extension> </extension>
<extension qualifier="graphene-secondbrowser"> <extension qualifier="graphene-secondbrowser">

View file

@ -290,7 +290,7 @@
<outputDirectory>${containers.home}/auth-server-undertow</outputDirectory> <outputDirectory>${containers.home}/auth-server-undertow</outputDirectory>
</artifactItem> </artifactItem>
</artifactItems> </artifactItems>
<includes>*.jks,*.crt,*.truststore,*.crl,*.key,certs/clients/*</includes> <includes>*.jks,*.p12,*.crt,*.truststore,*.crl,*.key,certs/clients/*</includes>
<skip>${auth.server.undertow.skip.unpack}</skip> <skip>${auth.server.undertow.skip.unpack}</skip>
</configuration> </configuration>
</execution> </execution>
@ -1626,11 +1626,6 @@
<groupId>org.jboss.arquillian.protocol</groupId> <groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId> <artifactId>arquillian-protocol-servlet</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-phantom-driver</artifactId>
<version>1.2.1.Final</version>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.arquillian.graphene</groupId> <groupId>org.jboss.arquillian.graphene</groupId>
<artifactId>arquillian-browser-screenshooter</artifactId> <artifactId>arquillian-browser-screenshooter</artifactId>