keycloak-developers

Merge pull request #4516 from mposolda/jwe KEYCLOAK-5570

9/29/2017 3:54:27 PM

Details

diff --git a/core/src/test/java/org/keycloak/jose/JWETest.java b/core/src/test/java/org/keycloak/jose/JWETest.java
index f97f3c5..31d8a8a 100644
--- a/core/src/test/java/org/keycloak/jose/JWETest.java
+++ b/core/src/test/java/org/keycloak/jose/JWETest.java
@@ -94,7 +94,7 @@ public class JWETest {
     }
 
 
-    // @Test
+    //@Test
     public void testPerfDirect() throws Exception {
         int iterations = 50000;
 
diff --git a/core/src/test/java/org/keycloak/RSAVerifierTest.java b/core/src/test/java/org/keycloak/RSAVerifierTest.java
index e606e35..8418f14 100755
--- a/core/src/test/java/org/keycloak/RSAVerifierTest.java
+++ b/core/src/test/java/org/keycloak/RSAVerifierTest.java
@@ -28,6 +28,7 @@ import org.keycloak.common.VerificationException;
 import org.keycloak.common.util.Time;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.util.JsonSerialization;
 import org.keycloak.util.TokenUtil;
 
 import javax.security.auth.x500.X500Principal;
@@ -126,28 +127,28 @@ public class RSAVerifierTest {
         return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm");
     }
 
-   /*
-   @Test
+
+   // @Test
    public void testSpeed() throws Exception
    {
-
-      byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
-
-      String encoded = new JWSBuilder()
-              .content(tokenBytes)
-              .rsa256(idpPair.getPrivate());
+       // Took 44 seconds with 50000 iterations
+      byte[] tokenBytes = JsonSerialization.writeValueAsBytes(token);
 
       long start = System.currentTimeMillis();
-      int count = 10000;
+      int count = 50000;
       for (int i = 0; i < count; i++)
       {
-         SkeletonKeyTokenVerification v = RSATokenVerifier.verify(null, encoded, metadata);
+          String encoded = new JWSBuilder()
+                  .content(tokenBytes)
+                  .rsa256(idpPair.getPrivate());
+
+          verifySkeletonKeyToken(encoded);
 
       }
       long end = System.currentTimeMillis() - start;
-      System.out.println("rate: " + ((double)end/(double)count));
+      System.out.println("took: " + end);
    }
-   */
+
 
 
     @Test
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
index ec572e9..0573dbb 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
@@ -93,7 +93,7 @@ public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
 
     @Test
     public void testBruteForceWithUserOperations() throws Exception {
-        // Enable 1st DC only
+        // Enable 1st node on each DC only
         enableDcOnLoadBalancer(DC.FIRST);
         enableDcOnLoadBalancer(DC.SECOND);
 
@@ -125,7 +125,7 @@ public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
 
     @Test
     public void testBruteForceWithRealmOperations() throws Exception {
-        // Enable 1st DC only
+        // Enable 1st node on each DC only
         enableDcOnLoadBalancer(DC.FIRST);
         enableDcOnLoadBalancer(DC.SECOND);
 
@@ -162,7 +162,7 @@ public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
 
     @Test
     public void testDuplicatedPutIfAbsentOperation() throws Exception {
-        // Enable 1st DC only
+        // Enable 1st node on each DC only
         enableDcOnLoadBalancer(DC.FIRST);
         enableDcOnLoadBalancer(DC.SECOND);
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/InvalidationCrossDCTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/InvalidationCrossDCTest.java
new file mode 100644
index 0000000..c3819f7
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/InvalidationCrossDCTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2017 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.crossdc;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ResourcesResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.Retry;
+import org.keycloak.testsuite.admin.ApiUtil;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class InvalidationCrossDCTest extends AbstractAdminCrossDCTest {
+
+    private static final String REALM_NAME = "test";
+
+    @Test
+    public void realmInvalidationTest() throws Exception {
+        enableDcOnLoadBalancer(DC.FIRST);
+        enableDcOnLoadBalancer(DC.SECOND);
+
+        RealmRepresentation realmDc0 = getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).toRepresentation();
+        RealmRepresentation realmDc1 = getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME).toRepresentation();
+
+        // Test same realm on both DCs
+        Assert.assertNull(realmDc0.getDisplayName());
+        Assert.assertTrue(realmDc0.isRegistrationAllowed());
+        Assert.assertNull(realmDc1.getDisplayName());
+        Assert.assertTrue(realmDc1.isRegistrationAllowed());
+
+        // Update realm on DC0
+        realmDc0.setRegistrationAllowed(false);
+        realmDc0.setDisplayName("Cool Realm!");
+        getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).update(realmDc0);
+
+        // Assert updated on both DC0 and DC1 (here retry is needed. We need to wait until invalidation message arrives)
+        realmDc0 = getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).toRepresentation();
+        Assert.assertEquals("Cool Realm!", realmDc0.getDisplayName());
+        Assert.assertFalse(realmDc0.isRegistrationAllowed());
+
+        AtomicInteger i = new AtomicInteger(0);
+        Retry.execute(() -> {
+            i.incrementAndGet();
+            RealmRepresentation realmDcc1 = getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME).toRepresentation();
+            Assert.assertEquals("Cool Realm!", realmDcc1.getDisplayName());
+            Assert.assertFalse(realmDcc1.isRegistrationAllowed());
+        }, 50, 50);
+
+        log.infof("realmInvalidationTest: Passed after '%d' iterations", i.get());
+    }
+
+
+    @Test
+    public void clientInvalidationTest() throws Exception {
+        enableDcOnLoadBalancer(DC.FIRST);
+        enableDcOnLoadBalancer(DC.SECOND);
+
+        ClientResource clientResourceDc0 = ApiUtil.findClientByClientId(getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME), "named-test-app");
+        ClientResource clientResourceDc1 = ApiUtil.findClientByClientId(getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME), "named-test-app");
+        ClientRepresentation clientDc0 = clientResourceDc0.toRepresentation();
+        ClientRepresentation clientDc1 = clientResourceDc1.toRepresentation();
+
+        // Test same client on both DCs
+        Assert.assertEquals("My Named Test App", clientDc0.getName());
+        Assert.assertEquals("My Named Test App", clientDc1.getName());
+
+        // Update client on DC0
+        clientDc0.setName("Changed Test App");
+        clientResourceDc0.update(clientDc0);
+
+        // Assert updated on both DC0 and DC1 (here retry is needed. We need to wait until invalidation message arrives)
+        clientDc0 = clientResourceDc0.toRepresentation();
+        Assert.assertEquals("Changed Test App", clientDc0.getName());
+
+        AtomicInteger i = new AtomicInteger(0);
+        Retry.execute(() -> {
+            i.incrementAndGet();
+            ClientRepresentation clientDcc1 = clientResourceDc1.toRepresentation();
+            Assert.assertEquals("Changed Test App", clientDcc1.getName());
+        }, 50, 50);
+
+        log.infof("clientInvalidationTest: Passed after '%d' iterations", i.get());
+    }
+
+
+    @Test
+    public void clientListInvalidationTest() throws Exception {
+        enableDcOnLoadBalancer(DC.FIRST);
+        enableDcOnLoadBalancer(DC.SECOND);
+
+        List<ClientRepresentation> dc0List = getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).clients().findAll();
+        List<ClientRepresentation> dc1List = getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME).clients().findAll();
+
+
+        // Test same clients on both DCs
+        Assert.assertEquals(dc0List.size(), dc1List.size());
+        int initialSize = dc0List.size();
+
+        // Create client on DC0
+        ClientRepresentation rep = new ClientRepresentation();
+        rep.setClientId("some-new-client");
+        rep.setEnabled(true);
+        Response response = getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).clients().create(rep);
+        Assert.assertEquals(201, response.getStatus());
+        response.close();
+
+        // Assert updated on both DC0 and DC1 (here retry is needed. We need to wait until invalidation message arrives)
+        dc0List = getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME).clients().findAll();
+        Assert.assertEquals(initialSize + 1, dc0List.size());
+
+        AtomicInteger i = new AtomicInteger(0);
+        Retry.execute(() -> {
+            i.incrementAndGet();
+            List<ClientRepresentation> dc1Listt = getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME).clients().findAll();
+            Assert.assertEquals(initialSize + 1, dc1Listt.size());
+        }, 50, 50);
+
+        log.infof("clientListInvalidationTest: Passed after '%d' iterations", i.get());
+    }
+
+
+    @Test
+    public void userInvalidationTest() throws Exception {
+        enableDcOnLoadBalancer(DC.FIRST);
+        enableDcOnLoadBalancer(DC.SECOND);
+
+        UserResource userResourceDc0 = ApiUtil.findUserByUsernameId(getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME), "test-user@localhost");
+        UserResource userResourceDc1 = ApiUtil.findUserByUsernameId(getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME), "test-user@localhost");
+        UserRepresentation userDc0 = userResourceDc0.toRepresentation();
+        UserRepresentation userDc1 = userResourceDc1.toRepresentation();
+
+        // Test same user on both DCs
+        Assert.assertEquals("Tom", userDc0.getFirstName());
+        Assert.assertEquals("Tom", userDc1.getFirstName());
+
+        // Update user on DC0
+        userDc0.setFirstName("Brad");
+        userResourceDc0.update(userDc0);
+
+        // Assert updated on both DC0 and DC1 (here retry is needed. We need to wait until invalidation message arrives)
+        userDc0 = userResourceDc0.toRepresentation();
+        Assert.assertEquals("Brad", userDc0.getFirstName());
+
+        AtomicInteger i = new AtomicInteger(0);
+        Retry.execute(() -> {
+            i.incrementAndGet();
+            UserRepresentation userDcc1 = userResourceDc1.toRepresentation();
+            Assert.assertEquals("Brad", userDcc1.getFirstName());
+        }, 50, 50);
+
+        log.infof("userInvalidationTest: Passed after '%d' iterations", i.get());
+    }
+
+
+    @Test
+    public void authzResourceInvalidationTest() throws Exception {
+        enableDcOnLoadBalancer(DC.FIRST);
+        enableDcOnLoadBalancer(DC.SECOND);
+
+
+        ResourcesResource resourcesDc0Resource = ApiUtil.findClientByClientId(getAdminClientForStartedNodeInDc(0).realms().realm(REALM_NAME), "test-app-authz").authorization().resources();
+        ResourcesResource resourcesDc1Resource = ApiUtil.findClientByClientId(getAdminClientForStartedNodeInDc(1).realms().realm(REALM_NAME), "test-app-authz").authorization().resources();
+        ResourceRepresentation resDc0 = resourcesDc0Resource.findByName("Premium Resource").get(0);
+        ResourceRepresentation resDc1 = resourcesDc1Resource.findByName("Premium Resource").get(0);
+
+        // Test same resource on both DCs
+        Assert.assertEquals("/protected/premium/*", resDc0.getUri());
+        Assert.assertEquals("/protected/premium/*", resDc1.getUri());
+
+        // Update resource on DC0
+        resDc0.setUri("/protected/ultra/premium/*");
+        resourcesDc0Resource.resource(resDc0.getId()).update(resDc0);
+
+        // Assert updated on both DC0 and DC1 (here retry is needed. We need to wait until invalidation message arrives)
+        resDc0 = resourcesDc0Resource.findByName("Premium Resource").get(0);
+        Assert.assertEquals("/protected/ultra/premium/*", resDc0.getUri());
+
+        AtomicInteger i = new AtomicInteger(0);
+        Retry.execute(() -> {
+            i.incrementAndGet();
+            ResourceRepresentation ressDc1 = resourcesDc1Resource.findByName("Premium Resource").get(0);
+            Assert.assertEquals("/protected/ultra/premium/*", ressDc1.getUri());
+        }, 50, 50);
+
+        log.infof("authzResourceInvalidationTest: Passed after '%d' iterations", i.get());
+    }
+
+
+}