From 5fd3eb29902ac774c2cdc2b6ff8bf5c7e6748bb0 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Thu, 26 Jan 2017 15:37:52 +0100 Subject: [PATCH] KEYCLOAK-3729 Ability to run tests within Keycloak server --- .../org/keycloak/util/JsonSerialization.java | 4 + .../services/testsuite-providers/pom.xml | 4 + .../rest/TestingResourceProvider.java | 48 +++++---- .../testsuite/runonserver/FetchOnServer.java | 32 ++++++ .../runonserver/FetchOnServerWrapper.java | 12 +++ .../testsuite/runonserver/ModuleUtil.java | 35 +++++++ .../testsuite/runonserver/RunHelpers.java | 44 +++++++++ .../testsuite/runonserver/RunOnServer.java | 31 ++++++ .../runonserver/RunOnServerException.java | 12 +++ .../runonserver/SerializationUtil.java | 70 +++++++++++++ .../main/module.xml | 1 + .../DeploymentArchiveProcessor.java | 5 + .../client/KeycloakTestingClient.java | 64 ++++++++++++ .../client/resources/TestingResource.java | 17 ++-- .../testsuite/admin/IdentityProviderTest.java | 2 - .../testsuite/admin/realm/RealmTest.java | 22 +++-- .../keys/GeneratedHmacKeyProviderTest.java | 25 +++-- .../testsuite/migration/MigrationTest.java | 20 +++- .../InternalComponentRepresentation.java | 27 ++++++ .../runonserver/RunOnServerDeployment.java | 23 +++++ .../runonserver/RunOnServerTest.java | 97 +++++++++++++++++++ ...n-on-server-jboss-deployment-structure.xml | 15 +++ 22 files changed, 561 insertions(+), 49 deletions(-) create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServer.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServerWrapper.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/ModuleUtil.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunHelpers.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServer.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServerException.java create mode 100644 testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java create mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/InternalComponentRepresentation.java create mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerDeployment.java create mode 100755 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/run-on-server-jboss-deployment-structure.xml diff --git a/core/src/main/java/org/keycloak/util/JsonSerialization.java b/core/src/main/java/org/keycloak/util/JsonSerialization.java index c94ee96dac..ed43e69228 100755 --- a/core/src/main/java/org/keycloak/util/JsonSerialization.java +++ b/core/src/main/java/org/keycloak/util/JsonSerialization.java @@ -77,6 +77,10 @@ public class JsonSerialization { return readValue(bytes, type, false); } + public static T readValue(String string, TypeReference type) throws IOException { + return mapper.readValue(string, type); + } + public static T readValue(InputStream bytes, TypeReference type) throws IOException { return mapper.readValue(bytes, type); } diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml index b0e1fccf70..a1951f35c5 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml @@ -56,6 +56,10 @@ io.undertow undertow-servlet + + org.wildfly.core + wildfly-controller + diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java index cfcef5a111..a4ae8c2121 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java @@ -17,13 +17,10 @@ package org.keycloak.testsuite.rest; -import org.infinispan.Cache; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.BadRequestException; -import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.Time; import org.keycloak.component.ComponentModel; -import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.events.Event; import org.keycloak.events.EventQuery; import org.keycloak.events.EventStoreProvider; @@ -62,6 +59,11 @@ import org.keycloak.testsuite.forms.PassThroughClientAuthenticator; import org.keycloak.testsuite.rest.representation.AuthenticatorState; import org.keycloak.testsuite.rest.resource.TestCacheResource; import org.keycloak.testsuite.rest.resource.TestingExportImportResource; +import org.keycloak.testsuite.runonserver.ModuleUtil; +import org.keycloak.testsuite.runonserver.FetchOnServer; +import org.keycloak.testsuite.runonserver.RunOnServer; +import org.keycloak.testsuite.runonserver.SerializationUtil; +import org.keycloak.util.JsonSerialization; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -82,8 +84,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.keycloak.exportimport.ExportImportConfig.PROVIDER; - /** * @author Stian Thorgersen */ @@ -636,21 +636,6 @@ public class TestingResourceProvider implements RealmResourceProvider { return reps; } - @GET - @Path("/component") - @Produces(MediaType.APPLICATION_JSON) - public MultivaluedHashMap getComponentConfig(@QueryParam("componentId") String componentId) { - RealmModel realm = session.getContext().getRealm(); - return realm.getComponent(componentId).getConfig(); - } - - @GET - @Path("/smtp-config") - @Produces(MediaType.APPLICATION_JSON) - public Map getSmtpConfig() { - return session.getContext().getRealm().getSmtpConfig(); - } - @GET @Path("/identity-config") @Produces(MediaType.APPLICATION_JSON) @@ -665,6 +650,29 @@ public class TestingResourceProvider implements RealmResourceProvider { System.setProperty("java.security.krb5.conf", krb5ConfFile); } + @POST + @Path("/run-on-server") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String runOnServer(String runOnServer) throws Exception { + try { + ClassLoader cl = ModuleUtil.isModules() ? ModuleUtil.getClassLoader() : getClass().getClassLoader(); + Object r = SerializationUtil.decode(runOnServer, cl); + + if (r instanceof FetchOnServer) { + Object result = ((FetchOnServer) r).run(session); + return result != null ? JsonSerialization.writeValueAsString(result) : null; + } else if (r instanceof RunOnServer) { + ((RunOnServer) r).run(session); + return null; + } else { + throw new IllegalArgumentException(); + } + } catch (Throwable t) { + return SerializationUtil.encodeException(t); + } + } + private RealmModel getRealmByName(String realmName) { RealmProvider realmProvider = session.getProvider(RealmProvider.class); return realmProvider.getRealmByName(realmName); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServer.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServer.java new file mode 100644 index 0000000000..c167ae760e --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServer.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.runonserver; + +import org.keycloak.models.KeycloakSession; + +import java.io.Serializable; +import java.util.function.Function; + +/** + * @author Stian Thorgersen + */ +public interface FetchOnServer extends Serializable { + + Object run(KeycloakSession session); + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServerWrapper.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServerWrapper.java new file mode 100644 index 0000000000..d83a760b92 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/FetchOnServerWrapper.java @@ -0,0 +1,12 @@ +package org.keycloak.testsuite.runonserver; + +/** + * Created by st on 26.01.17. + */ +public interface FetchOnServerWrapper { + + FetchOnServer getRunOnServer(); + + Class getResultClass(); + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/ModuleUtil.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/ModuleUtil.java new file mode 100644 index 0000000000..dfe33586cd --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/ModuleUtil.java @@ -0,0 +1,35 @@ +package org.keycloak.testsuite.runonserver; + +import org.jboss.modules.Module; +import org.jboss.modules.ModuleIdentifier; + +/** + * Created by st on 26.01.17. + */ +public class ModuleUtil { + + private static boolean modules; + + static { + try { + Module.getContextModuleLoader().loadModule(ModuleIdentifier.fromString("org.wildfly.common")); + modules = true; + } catch (Throwable t) { + modules = false; + } + } + + public static boolean isModules() { + return modules; + } + + public static ClassLoader getClassLoader() { + try { + Module m = Module.getContextModuleLoader().loadModule(ModuleIdentifier.fromString("deployment.run-on-server-classes.war")); + return m.getClassLoader(); + } catch (Exception e) { + throw new RuntimeException("Failed to load 'deployment.run-on-server-classes.war', did you include RunOnServerDeployment?", e); + } + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunHelpers.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunHelpers.java new file mode 100644 index 0000000000..59f20a8041 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunHelpers.java @@ -0,0 +1,44 @@ +package org.keycloak.testsuite.runonserver; + +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.idm.ComponentRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +/** + * Created by st on 26.01.17. + */ +public class RunHelpers { + + public static FetchOnServerWrapper internalRealm() { + return new FetchOnServerWrapper() { + + @Override + public FetchOnServer getRunOnServer() { + return (FetchOnServer) session -> ModelToRepresentation.toRepresentation(session.getContext().getRealm(), true); + } + + @Override + public Class getResultClass() { + return RealmRepresentation.class; + } + + }; + } + + public static FetchOnServerWrapper internalComponent(String componentId) { + return new FetchOnServerWrapper() { + + @Override + public FetchOnServer getRunOnServer() { + return (FetchOnServer) session -> ModelToRepresentation.toRepresentation(session, session.getContext().getRealm().getComponent(componentId), true); + } + + @Override + public Class getResultClass() { + return ComponentRepresentation.class; + } + + }; + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServer.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServer.java new file mode 100644 index 0000000000..bd9524b9c3 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.runonserver; + +import org.keycloak.models.KeycloakSession; + +import java.io.Serializable; + +/** + * @author Stian Thorgersen + */ +public interface RunOnServer extends Serializable { + + void run(KeycloakSession session); + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServerException.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServerException.java new file mode 100644 index 0000000000..cfe8ed0666 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/RunOnServerException.java @@ -0,0 +1,12 @@ +package org.keycloak.testsuite.runonserver; + +/** + * Created by st on 26.01.17. + */ +public class RunOnServerException extends RuntimeException { + + public RunOnServerException(Throwable throwable) { + super(throwable); + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java new file mode 100644 index 0000000000..cd1b21665d --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java @@ -0,0 +1,70 @@ +package org.keycloak.testsuite.runonserver; + +import org.keycloak.common.util.Base64; + +import java.io.*; + +/** + * Created by st on 26.01.17. + */ +public class SerializationUtil { + + public static String encode(Object function) { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(os); + oos.writeObject(function); + oos.close(); + + return Base64.encodeBytes(os.toByteArray()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static Object decode(String encoded, ClassLoader classLoader) { + try { + byte[] bytes = Base64.decode(encoded); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(is) { + @Override + protected Class resolveClass(ObjectStreamClass c) throws IOException, ClassNotFoundException { + try { + return Class.forName(c.getName(), false, classLoader); + } catch (ClassNotFoundException e) { + throw e; + } + } + }; + + return ois.readObject(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String encodeException(Throwable t) { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(os); + oos.writeObject(t); + oos.close(); + + return Base64.encodeBytes(os.toByteArray()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static Throwable decodeException(String result) { + try { + byte[] bytes = Base64.decode(result); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(is); + return (Throwable) ois.readObject(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/org/keycloak/testsuite/integration-arquillian-testsuite-providers/main/module.xml b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/org/keycloak/testsuite/integration-arquillian-testsuite-providers/main/module.xml index 6f208386fd..1e4b3f762c 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/org/keycloak/testsuite/integration-arquillian-testsuite-providers/main/module.xml +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/org/keycloak/testsuite/integration-arquillian-testsuite-providers/main/module.xml @@ -38,5 +38,6 @@ + diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java index 65cebd6f8c..0e06ee1f33 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java @@ -71,6 +71,11 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor { @Override public void process(Archive archive, TestClass testClass) { + // Ignore run on server classes + if (archive.getName().equals("run-on-server-classes.war")) { + return; + } + log.info("Processing archive " + archive.getName()); // if (isAdapterTest(testClass)) { modifyAdapterConfigs(archive, testClass); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java index ae3a873ec0..1e20944f49 100755 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java @@ -23,11 +23,14 @@ import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import org.keycloak.testsuite.client.resources.TestApplicationResource; import org.keycloak.testsuite.client.resources.TestExampleCompanyResource; import org.keycloak.testsuite.client.resources.TestingResource; +import org.keycloak.testsuite.runonserver.*; +import org.keycloak.util.JsonSerialization; /** * @author Marko Strukelj */ public class KeycloakTestingClient { + private final ResteasyWebTarget target; private final ResteasyClient client; @@ -52,6 +55,67 @@ public class KeycloakTestingClient { public TestExampleCompanyResource testExampleCompany() { return target.proxy(TestExampleCompanyResource.class); } + public Server server() { + return new Server("master"); + } + + public Server server(String realm) { + return new Server(realm); + } + + public class Server { + + private String realm; + + public Server(String realm) { + this.realm = realm; + } + + public T fetch(FetchOnServerWrapper wrapper) throws RunOnServerException { + return fetch(wrapper.getRunOnServer(), wrapper.getResultClass()); + } + + public T fetch(FetchOnServer function, Class clazz) throws RunOnServerException { + try { + String s = fetch(function); + return JsonSerialization.readValue(s, clazz); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String fetch(FetchOnServer function) throws RunOnServerException { + String encoded = SerializationUtil.encode(function); + + String result = testing(realm != null ? realm : "master").runOnServer(encoded); + if (result != null && !result.isEmpty() && !result.trim().startsWith("{")) { + Throwable t = SerializationUtil.decodeException(result); + if (t instanceof AssertionError) { + throw (AssertionError) t; + } else { + throw new RunOnServerException(t); + } + } else { + return result; + } + } + + public void run(RunOnServer function) throws RunOnServerException { + String encoded = SerializationUtil.encode(function); + + String result = testing(realm != null ? realm : "master").runOnServer(encoded); + if (result != null && !result.isEmpty() && !result.trim().startsWith("{")) { + Throwable t = SerializationUtil.decodeException(result); + if (t instanceof AssertionError) { + throw (AssertionError) t; + } else { + throw new RunOnServerException(t); + } + } + } + + } + public void close() { client.close(); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java index 9bb73d34a5..02d889ffc7 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java @@ -242,23 +242,20 @@ public interface TestingResource { @Produces(MediaType.APPLICATION_JSON) Map getTestComponentDetails(); - @GET - @Path("/smtp-config") - @Produces(MediaType.APPLICATION_JSON) - Map getSmtpConfig(); - @GET @Path("/identity-config") @Produces(MediaType.APPLICATION_JSON) Map getIdentityProviderConfig(@QueryParam("alias") String alias); - @GET - @Path("/component") - @Produces(MediaType.APPLICATION_JSON) - MultivaluedHashMap getComponentConfig(@QueryParam("componentId") String componentId); - @PUT @Path("/set-krb5-conf-file") @Consumes(MediaType.APPLICATION_JSON) void setKrb5ConfFile(@QueryParam("krb5-conf-file") String krb5ConfFile); + + @POST + @Path("/run-on-server") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + String runOnServer(String runOnServer); + } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java index f550c17e43..2fbb5a30d6 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java @@ -129,8 +129,6 @@ public class IdentityProviderTest extends AbstractAdminTest { assertFalse(representation.isStoreToken()); assertFalse(representation.isTrustEmail()); - testingClient.testing("admin-client-test").getSmtpConfig(); - assertEquals("some secret value", testingClient.testing("admin-client-test").getIdentityProviderConfig("new-identity-provider").get("clientSecret")); IdentityProviderRepresentation rep = realm.identityProviders().findAll().stream().filter(i -> i.getAlias().equals("new-identity-provider")).findFirst().get(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java index d0a8bde8f6..db10d02a9a 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java @@ -19,12 +19,13 @@ package org.keycloak.testsuite.admin.realm; import org.apache.commons.io.IOUtils; import org.hamcrest.Matchers; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.resource.ServerInfoResource; -import org.keycloak.common.util.StreamUtil; import org.keycloak.common.util.Time; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; @@ -34,7 +35,6 @@ import org.keycloak.representations.adapters.action.PushNotBeforeAction; import org.keycloak.representations.idm.AdminEventRepresentation; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ComponentRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; @@ -45,6 +45,9 @@ import org.keycloak.testsuite.admin.AbstractAdminTest; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; import org.keycloak.testsuite.auth.page.AuthRealm; +import org.keycloak.testsuite.client.KeycloakTestingClient; +import org.keycloak.testsuite.runonserver.RunOnServerDeployment; +import org.keycloak.testsuite.runonserver.RunHelpers; import org.keycloak.testsuite.util.AdminEventPaths; import org.keycloak.testsuite.util.CredentialBuilder; import org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse; @@ -52,7 +55,6 @@ import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.util.JsonSerialization; -import javax.ws.rs.BadRequestException; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; import java.io.IOException; @@ -66,7 +68,6 @@ import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -77,6 +78,11 @@ import static org.junit.Assert.fail; */ public class RealmTest extends AbstractAdminTest { + @Deployment + public static WebArchive deploy() { + return RunOnServerDeployment.create(); + } + @Rule public AssertEvents events = new AssertEvents(this); @@ -140,7 +146,10 @@ public class RealmTest extends AbstractAdminTest { RealmRepresentation returned = adminClient.realm("realm-with-smtp").toRepresentation(); assertEquals(ComponentRepresentation.SECRET_VALUE, returned.getSmtpServer().get("password")); - assertEquals("secret", testingClient.testing("realm-with-smtp").getSmtpConfig().get("password")); + KeycloakTestingClient.Server serverClient = testingClient.server("realm-with-smtp"); + + RealmRepresentation internalRep = serverClient.fetch(RunHelpers.internalRealm()); + assertEquals("secret", internalRep.getSmtpServer().get("password")); adminClient.realm("realm-with-smtp").update(rep); @@ -148,7 +157,8 @@ public class RealmTest extends AbstractAdminTest { assertFalse(event.getRepresentation().contains("some secret value!!")); assertTrue(event.getRepresentation().contains(ComponentRepresentation.SECRET_VALUE)); - assertEquals("secret", testingClient.testing("realm-with-smtp").getSmtpConfig().get("password")); + internalRep = serverClient.fetch(RunHelpers.internalRealm()); + assertEquals("secret", internalRep.getSmtpServer().get("password")); RealmRepresentation realm = adminClient.realms().findAll().stream().filter(r -> r.getRealm().equals("realm-with-smtp")).findFirst().get(); assertEquals(ComponentRepresentation.SECRET_VALUE, realm.getSmtpServer().get("password")); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/keys/GeneratedHmacKeyProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/keys/GeneratedHmacKeyProviderTest.java index fb3a4f74ca..e5d2bc2d97 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/keys/GeneratedHmacKeyProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/keys/GeneratedHmacKeyProviderTest.java @@ -17,16 +17,15 @@ package org.keycloak.testsuite.keys; +import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.graphene.page.Page; +import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Rule; import org.junit.Test; import org.keycloak.common.util.Base64Url; import org.keycloak.common.util.MultivaluedHashMap; -import org.keycloak.common.util.PemUtils; import org.keycloak.jose.jws.AlgorithmType; -import org.keycloak.jose.jws.crypto.HMACProvider; import org.keycloak.keys.GeneratedHmacKeyProviderFactory; -import org.keycloak.keys.GeneratedRsaKeyProviderFactory; import org.keycloak.keys.KeyProvider; import org.keycloak.representations.idm.ComponentRepresentation; import org.keycloak.representations.idm.ErrorRepresentation; @@ -37,9 +36,10 @@ import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.runonserver.RunHelpers; +import org.keycloak.testsuite.runonserver.RunOnServerDeployment; import javax.ws.rs.core.Response; -import java.security.interfaces.RSAPublicKey; import java.util.List; import static org.junit.Assert.*; @@ -50,6 +50,11 @@ import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; */ public class GeneratedHmacKeyProviderTest extends AbstractKeycloakTest { + @Deployment + public static WebArchive deploy() { + return RunOnServerDeployment.create(); + } + @Rule public AssertEvents events = new AssertEvents(this); @@ -94,7 +99,8 @@ public class GeneratedHmacKeyProviderTest extends AbstractKeycloakTest { assertEquals(AlgorithmType.HMAC.name(), key.getType()); assertEquals(priority, key.getProviderPriority()); - assertEquals(32, Base64Url.decode(testingClient.testing("test").getComponentConfig(id).getFirst("secret")).length); + ComponentRepresentation component = testingClient.server("test").fetch(RunHelpers.internalComponent(id)); + assertEquals(32, Base64Url.decode(component.getConfig().getFirst("secret")).length); } @Test @@ -127,7 +133,8 @@ public class GeneratedHmacKeyProviderTest extends AbstractKeycloakTest { assertEquals(AlgorithmType.HMAC.name(), key.getType()); assertEquals(priority, key.getProviderPriority()); - assertEquals(512, Base64Url.decode(testingClient.testing("test").getComponentConfig(id).getFirst("secret")).length); + ComponentRepresentation component = testingClient.server("test").fetch(RunHelpers.internalComponent(id)); + assertEquals(512, Base64Url.decode(component.getConfig().getFirst("secret")).length); } @Test @@ -141,13 +148,15 @@ public class GeneratedHmacKeyProviderTest extends AbstractKeycloakTest { Response response = adminClient.realm("test").components().add(rep); String id = ApiUtil.getCreatedId(response); - assertEquals(32, Base64Url.decode(testingClient.testing("test").getComponentConfig(id).getFirst("secret")).length); + ComponentRepresentation component = testingClient.server("test").fetch(RunHelpers.internalComponent(id)); + assertEquals(32, Base64Url.decode(component.getConfig().getFirst("secret")).length); ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation(); createdRep.getConfig().putSingle("secretSize", "512"); adminClient.realm("test").components().component(id).update(createdRep); - assertEquals(512, Base64Url.decode(testingClient.testing("test").getComponentConfig(id).getFirst("secret")).length); + component = testingClient.server("test").fetch(RunHelpers.internalComponent(id)); + assertEquals(512, Base64Url.decode(component.getConfig().getFirst("secret")).length); } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java index dd68c1d779..4f6d6886ab 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java @@ -21,6 +21,9 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.ws.rs.NotFoundException; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Before; import org.junit.Test; import org.keycloak.admin.client.resource.ClientResource; @@ -50,6 +53,8 @@ import org.keycloak.storage.UserStorageProvider; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.arquillian.migration.Migration; +import org.keycloak.testsuite.runonserver.RunHelpers; +import org.keycloak.testsuite.runonserver.RunOnServerDeployment; import org.keycloak.testsuite.util.OAuthClient; import static org.keycloak.testsuite.Assert.assertEquals; @@ -71,7 +76,12 @@ public class MigrationTest extends AbstractKeycloakTest { private RealmResource migrationRealm2; private RealmResource migrationRealm3; private RealmResource masterRealm; - + + @Deployment + public static WebArchive deploy() { + return RunOnServerDeployment.create(); + } + @Override public void addTestRealms(List testRealms) { log.info("Adding no test realms for migration test. Test realm should be migrated from previous vesrion."); @@ -187,7 +197,9 @@ public class MigrationTest extends AbstractKeycloakTest { components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "rsa"); assertEquals(1, components.size()); - assertEquals(expectedMasterRealmKey, testingClient.testing(MASTER).getComponentConfig(components.get(0).getId()).getFirst("privateKey")); + + ComponentRepresentation component = testingClient.server(MASTER).fetch(RunHelpers.internalComponent(components.get(0).getId())); + assertEquals(expectedMasterRealmKey, component.getConfig().getFirst("privateKey")); components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "hmac-generated"); assertEquals(1, components.size()); @@ -197,7 +209,9 @@ public class MigrationTest extends AbstractKeycloakTest { components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "rsa"); assertEquals(1, components.size()); - assertEquals(expectedMigrationRealmKey, testingClient.testing(MIGRATION).getComponentConfig(components.get(0).getId()).getFirst("privateKey")); + + component = testingClient.server(MIGRATION).fetch(RunHelpers.internalComponent(components.get(0).getId())); + assertEquals(expectedMigrationRealmKey, component.getConfig().getFirst("privateKey")); components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "hmac-generated"); assertEquals(1, components.size()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/InternalComponentRepresentation.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/InternalComponentRepresentation.java new file mode 100644 index 0000000000..346ccc6ecd --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/InternalComponentRepresentation.java @@ -0,0 +1,27 @@ +package org.keycloak.testsuite.runonserver; + +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.idm.ComponentRepresentation; + +/** + * Created by st on 26.01.17. + */ +public class InternalComponentRepresentation implements FetchOnServerWrapper { + + private final String componentId; + + public InternalComponentRepresentation(String componentId) { + this.componentId = componentId; + } + + @Override + public FetchOnServer getRunOnServer() { + return (FetchOnServer) session -> ModelToRepresentation.toRepresentation(session.getContext().getRealm(), true); + } + + @Override + public Class getResultClass() { + return ComponentRepresentation.class; + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerDeployment.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerDeployment.java new file mode 100644 index 0000000000..bdc6eeef55 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerDeployment.java @@ -0,0 +1,23 @@ +package org.keycloak.testsuite.runonserver; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.keycloak.testsuite.AbstractKeycloakTest; +import org.keycloak.testsuite.runonserver.RunOnServerException; + +/** + * Created by st on 26.01.17. + */ +public class RunOnServerDeployment { + + @Deployment + public static WebArchive create(Class ... classes) { + return ShrinkWrap.create(WebArchive.class, "run-on-server-classes.war") + .addAsManifestResource("run-on-server-jboss-deployment-structure.xml","jboss-deployment-structure.xml") + .addClasses(classes) + .addClass(AbstractKeycloakTest.class) + .addClass(RunOnServerException.class); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java new file mode 100755 index 0000000000..4101ffc150 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.runonserver; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.ComparisonFailure; +import org.junit.Test; +import org.keycloak.models.ModelException; +import org.keycloak.models.RealmModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.AbstractKeycloakTest; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.*; + +/** + * This checks running code on the server for tests works and is not a test of the actual server + * + * @author Stian Thorgersen + */ +public class RunOnServerTest extends AbstractKeycloakTest { + + @Deployment + public static WebArchive deploy() { + return RunOnServerDeployment.create(RunOnServerTest.class); + } + + @Test + public void runOnServerRep() throws IOException { + final String realmName = "master"; + + RealmRepresentation realmRep = testingClient.server().fetch(session -> { + RealmModel master = session.realms().getRealm(realmName); + return ModelToRepresentation.toRepresentation(master, true); + }, RealmRepresentation.class); + + assertEquals(realmName, realmRep.getRealm()); + } + + @Test + public void runOnServerHelpers() throws IOException { + RealmRepresentation realmRep = testingClient.server().fetch(RunHelpers.internalRealm()); + assertEquals("master", realmRep.getRealm()); + } + + @Test + public void runOnServerNoResponse() throws IOException { + testingClient.server().run(session -> System.out.println("Hello world!")); + } + + @Test + public void runOnServerAssertOnServer() throws IOException { + try { + testingClient.server().run(session -> assertEquals("foo", "bar")); + fail("Expected exception"); + } catch (ComparisonFailure e) { + assertEquals("expected:<[foo]> but was:<[bar]>", e.getMessage()); + } + } + + @Test + public void runOnServerExceptionOnServer() throws IOException { + try { + testingClient.server().run(session -> { + throw new ModelException("Something went wrong"); + }); + fail("Expected exception"); + } catch (RunOnServerException e) { + assertTrue(e.getCause() instanceof ModelException); + assertEquals("Something went wrong", e.getCause().getMessage()); + } + } + + @Override + public void addTestRealms(List testRealms) { + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/run-on-server-jboss-deployment-structure.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/run-on-server-jboss-deployment-structure.xml new file mode 100644 index 0000000000..5ffd9a148d --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/run-on-server-jboss-deployment-structure.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file