From de14e1c310406420f00f9abdef3106c46751b2ec Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Mon, 18 Nov 2024 16:36:26 +0100 Subject: [PATCH] Migrate AdminPreflightTest (#35042) Part of #34494 Signed-off-by: stianst --- .../framework/CoreTestFrameworkExtension.java | 6 +- .../annotations/InjectHttpClient.java | 12 ++++ .../annotations/InjectKeycloakUrls.java | 12 ++++ .../framework/http/HttpClientSupplier.java | 43 +++++++++++++++ .../test/framework/server/KeycloakUrls.java | 48 ++++++++++++++++ .../server/KeycloakUrlsSupplier.java | 30 ++++++++++ .../test/admin/AdminPreflightTest.java | 42 ++++++++++++++ .../testsuite/admin/AdminPreflightTest.java | 55 ------------------- 8 files changed, 192 insertions(+), 56 deletions(-) create mode 100644 test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectHttpClient.java create mode 100644 test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectKeycloakUrls.java create mode 100644 test-framework/core/src/main/java/org/keycloak/test/framework/http/HttpClientSupplier.java create mode 100644 test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrls.java create mode 100644 test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrlsSupplier.java create mode 100644 tests/base/src/test/java/org/keycloak/test/admin/AdminPreflightTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/CoreTestFrameworkExtension.java b/test-framework/core/src/main/java/org/keycloak/test/framework/CoreTestFrameworkExtension.java index eb1a227f0e..80f49f25c2 100644 --- a/test-framework/core/src/main/java/org/keycloak/test/framework/CoreTestFrameworkExtension.java +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/CoreTestFrameworkExtension.java @@ -7,6 +7,7 @@ import org.keycloak.test.framework.database.TestDatabase; import org.keycloak.test.framework.events.AdminEventsSupplier; import org.keycloak.test.framework.events.EventsSupplier; import org.keycloak.test.framework.events.SysLogServerSupplier; +import org.keycloak.test.framework.http.HttpClientSupplier; import org.keycloak.test.framework.injection.Supplier; import org.keycloak.test.framework.oauth.OAuthClientSupplier; import org.keycloak.test.framework.realm.ClientSupplier; @@ -16,6 +17,7 @@ import org.keycloak.test.framework.server.DistributionKeycloakTestServerSupplier import org.keycloak.test.framework.server.EmbeddedKeycloakTestServerSupplier; import org.keycloak.test.framework.server.KeycloakTestServer; import org.keycloak.test.framework.server.RemoteKeycloakTestServerSupplier; +import org.keycloak.test.framework.server.KeycloakUrlsSupplier; import java.util.List; import java.util.Map; @@ -32,12 +34,14 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension { new DistributionKeycloakTestServerSupplier(), new EmbeddedKeycloakTestServerSupplier(), new RemoteKeycloakTestServerSupplier(), + new KeycloakUrlsSupplier(), new DevMemDatabaseSupplier(), new DevFileDatabaseSupplier(), new OAuthClientSupplier(), new SysLogServerSupplier(), new EventsSupplier(), - new AdminEventsSupplier() + new AdminEventsSupplier(), + new HttpClientSupplier() ); } diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectHttpClient.java b/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectHttpClient.java new file mode 100644 index 0000000000..4473368a4a --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectHttpClient.java @@ -0,0 +1,12 @@ +package org.keycloak.test.framework.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface InjectHttpClient { + +} diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectKeycloakUrls.java b/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectKeycloakUrls.java new file mode 100644 index 0000000000..428b4e416d --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/annotations/InjectKeycloakUrls.java @@ -0,0 +1,12 @@ +package org.keycloak.test.framework.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface InjectKeycloakUrls { + +} diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/http/HttpClientSupplier.java b/test-framework/core/src/main/java/org/keycloak/test/framework/http/HttpClientSupplier.java new file mode 100644 index 0000000000..cae43e7e7d --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/http/HttpClientSupplier.java @@ -0,0 +1,43 @@ +package org.keycloak.test.framework.http; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.keycloak.test.framework.annotations.InjectHttpClient; +import org.keycloak.test.framework.injection.InstanceContext; +import org.keycloak.test.framework.injection.RequestedInstance; +import org.keycloak.test.framework.injection.Supplier; + +import java.io.IOException; + +public class HttpClientSupplier implements Supplier { + + @Override + public Class getAnnotationClass() { + return InjectHttpClient.class; + } + + @Override + public Class getValueType() { + return HttpClient.class; + } + + @Override + public HttpClient getValue(InstanceContext instanceContext) { + return HttpClientBuilder.create().build(); + } + + @Override + public void close(InstanceContext instanceContext) { + try { + ((CloseableHttpClient) instanceContext.getValue()).close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean compatible(InstanceContext a, RequestedInstance b) { + return false; + } +} diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrls.java b/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrls.java new file mode 100644 index 0000000000..d85a9f3614 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrls.java @@ -0,0 +1,48 @@ +package org.keycloak.test.framework.server; + +import org.keycloak.common.util.KeycloakUriBuilder; + +import java.net.MalformedURLException; +import java.net.URL; + +public class KeycloakUrls { + + private final String baseUrl; + + public KeycloakUrls(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getBase() { + return baseUrl; + } + + public URL getBaseUrl() { + return toUrl(getBase()); + } + + public String getAdmin() { + return baseUrl + "/admin"; + } + + public URL getAdminUrl() { + return toUrl(getAdmin()); + } + + public KeycloakUriBuilder getAdminBuilder() { + return toBuilder(getAdmin()); + } + + private URL toUrl(String url) { + try { + return new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + private KeycloakUriBuilder toBuilder(String url) { + return KeycloakUriBuilder.fromUri(url); + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrlsSupplier.java b/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrlsSupplier.java new file mode 100644 index 0000000000..884cfe01bd --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/test/framework/server/KeycloakUrlsSupplier.java @@ -0,0 +1,30 @@ +package org.keycloak.test.framework.server; + +import org.keycloak.test.framework.annotations.InjectKeycloakUrls; +import org.keycloak.test.framework.injection.InstanceContext; +import org.keycloak.test.framework.injection.RequestedInstance; +import org.keycloak.test.framework.injection.Supplier; + +public class KeycloakUrlsSupplier implements Supplier { + + @Override + public Class getAnnotationClass() { + return InjectKeycloakUrls.class; + } + + @Override + public Class getValueType() { + return KeycloakUrls.class; + } + + @Override + public KeycloakUrls getValue(InstanceContext instanceContext) { + KeycloakTestServer testServer = instanceContext.getDependency(KeycloakTestServer.class); + return new KeycloakUrls(testServer.getBaseUrl()); + } + + @Override + public boolean compatible(InstanceContext a, RequestedInstance b) { + return true; + } +} diff --git a/tests/base/src/test/java/org/keycloak/test/admin/AdminPreflightTest.java b/tests/base/src/test/java/org/keycloak/test/admin/AdminPreflightTest.java new file mode 100644 index 0000000000..1906f14fe5 --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/test/admin/AdminPreflightTest.java @@ -0,0 +1,42 @@ +package org.keycloak.test.admin; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpOptions; +import org.junit.jupiter.api.Test; +import org.keycloak.services.cors.Cors; +import org.keycloak.test.framework.annotations.InjectHttpClient; +import org.keycloak.test.framework.annotations.InjectKeycloakUrls; +import org.keycloak.test.framework.annotations.KeycloakIntegrationTest; +import org.keycloak.test.framework.server.KeycloakUrls; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@KeycloakIntegrationTest +public class AdminPreflightTest { + + @InjectHttpClient + HttpClient client; + + @InjectKeycloakUrls + KeycloakUrls keycloakUrls; + + @Test + public void testPreflight() throws IOException { + HttpOptions options = new HttpOptions(keycloakUrls.getAdminBuilder().path("/realms/master/users").build()); + options.setHeader("Origin", "http://test"); + + HttpResponse response = client.execute(options); + assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals("true", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_CREDENTIALS).getValue()); + assertEquals("DELETE, POST, GET, PUT", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_METHODS).getValue()); + assertEquals("http://test", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_ORIGIN).getValue()); + assertEquals("3600", response.getFirstHeader(Cors.ACCESS_CONTROL_MAX_AGE).getValue()); + assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Authorization")); + assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Content-Type")); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java deleted file mode 100644 index 19c74663fc..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.keycloak.testsuite.admin; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpOptions; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.keycloak.services.cors.Cors; - -import java.io.IOException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class AdminPreflightTest extends AbstractAdminTest { - - - private CloseableHttpClient client; - - @Before - public void before() { - client = HttpClientBuilder.create().build(); - } - - @After - public void after() { - try { - client.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Test - public void testPreflight() throws IOException { - HttpOptions options = new HttpOptions(getAdminUrl("realms/master/users")); - options.setHeader("Origin", "http://test"); - - CloseableHttpResponse response = client.execute(options); - assertEquals(200, response.getStatusLine().getStatusCode()); - assertEquals("true", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_CREDENTIALS).getValue()); - assertEquals("DELETE, POST, GET, PUT", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_METHODS).getValue()); - assertEquals("http://test", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_ORIGIN).getValue()); - assertEquals("3600", response.getFirstHeader(Cors.ACCESS_CONTROL_MAX_AGE).getValue()); - assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Authorization")); - assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Content-Type")); - } - - private String getAdminUrl(String resource) { - return suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/admin/" + resource; - } - -}