From 99e2f1df94d7464bcfb3f67e0750455afe4c05ef Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Tue, 21 Jan 2025 14:05:14 +0100 Subject: [PATCH] Replace createRealm/createClient and invalid use of ref with attachTo (#36640) Closes #35995 Signed-off-by: stianst --- .../annotations/InjectClient.java | 9 ++- .../annotations/InjectRealm.java | 8 ++- .../testframework/realm/ClientSupplier.java | 28 +++++---- .../testframework/realm/RealmSupplier.java | 44 +++++++------- .../keycloak/test/examples/AttachToTest.java | 59 +++++++++++++++++++ .../admin/AdminSignatureAlgorithmTest.java | 2 +- .../authz/fgap/AbstractPermissionTest.java | 2 +- .../admin/authz/fgap/FeatureDisabledTest.java | 2 +- .../authz/fgap/FeatureV1EnabledTest.java | 2 +- .../authz/fgap/FeatureV2EnabledTest.java | 2 +- 10 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 test-framework/examples/tests/src/test/java/org/keycloak/test/examples/AttachToTest.java diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectClient.java b/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectClient.java index cc3013e5301..32596e735be 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectClient.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectClient.java @@ -21,5 +21,12 @@ public @interface InjectClient { String realmRef() default ""; - boolean createClient() default true; + /** + * Attach to an existing client instead of creating one; when attaching to an existing client the config will be ignored + * and the client will not be deleted automatically. + * + * @return the client-id of the existing client to attach to + */ + String attachTo() default ""; + } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectRealm.java b/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectRealm.java index 1f5c8daef9f..c9c645b6ced 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectRealm.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/annotations/InjectRealm.java @@ -19,6 +19,12 @@ public @interface InjectRealm { String ref() default ""; - boolean createRealm() default true; + /** + * Attach to an existing realm instead of creating one; when attaching to an existing realm the config will be ignored + * and the realm will not be deleted automatically. + * + * @return the name of the existing realm to attach to + */ + String attachTo() default ""; } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java index a9b694c4f3c..1fac8b9ff3d 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java @@ -29,28 +29,34 @@ public class ClientSupplier implements Supplier { public ManagedClient getValue(InstanceContext instanceContext) { ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class, instanceContext.getAnnotation().realmRef()); - ClientConfig config = SupplierHelpers.getInstance(instanceContext.getAnnotation().config()); - ClientRepresentation clientRepresentation = config.configure(ClientConfigBuilder.create()).build(); + String attachTo = instanceContext.getAnnotation().attachTo(); + boolean managed = attachTo.isEmpty(); - if (clientRepresentation.getClientId() == null) { - String clientId = SupplierHelpers.createName(instanceContext); - clientRepresentation.setClientId(clientId); - } + ClientRepresentation clientRepresentation; + + if (managed) { + ClientConfig config = SupplierHelpers.getInstance(instanceContext.getAnnotation().config()); + clientRepresentation = config.configure(ClientConfigBuilder.create()).build(); + + if (clientRepresentation.getClientId() == null) { + clientRepresentation.setClientId(SupplierHelpers.createName(instanceContext)); + } - if (instanceContext.getAnnotation().createClient()) { Response response = realm.admin().clients().create(clientRepresentation); if (Status.CONFLICT.equals(Status.fromStatusCode(response.getStatus()))) { throw new IllegalStateException("Client already exist with client id: " + clientRepresentation.getClientId()); } clientRepresentation.setId(ApiUtil.handleCreatedResponse(response)); } else { - List clients = realm.admin().clients().findByClientId(clientRepresentation.getClientId()); + List clients = realm.admin().clients().findByClientId(attachTo); if (clients.isEmpty()) { - throw new IllegalStateException("No client found with client id: " + clientRepresentation.getClientId()); + throw new IllegalStateException("No client found with client id: " + attachTo); } clientRepresentation = clients.get(0); } + instanceContext.addNote("managed", managed); + ClientResource clientResource = realm.admin().clients().get(clientRepresentation.getId()); return new ManagedClient(clientRepresentation, clientResource); } @@ -62,7 +68,9 @@ public class ClientSupplier implements Supplier { @Override public void close(InstanceContext instanceContext) { - instanceContext.getValue().admin().remove(); + if (instanceContext.getNote("managed", Boolean.class)) { + instanceContext.getValue().admin().remove(); + } } } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java index 4e54194766c..47c7e0841fa 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java @@ -15,8 +15,6 @@ import org.keycloak.testframework.server.KeycloakServer; public class RealmSupplier implements Supplier { - private static final String REALM_NAME_KEY = "realmName"; - @Override public Class getAnnotationClass() { return InjectRealm.class; @@ -32,36 +30,40 @@ public class RealmSupplier implements Supplier { KeycloakServer server = instanceContext.getDependency(KeycloakServer.class); Keycloak adminClient = instanceContext.getDependency(Keycloak.class, "bootstrap-client"); - RealmConfig config = SupplierHelpers.getInstance(instanceContext.getAnnotation().config()); + String attachTo = instanceContext.getAnnotation().attachTo(); + boolean managed = attachTo.isEmpty(); - RealmConfigBuilder realmConfigBuilder = config.configure(RealmConfigBuilder.create()); + RealmRepresentation realmRepresentation; - RealmConfigInterceptorHelper interceptor = new RealmConfigInterceptorHelper(instanceContext.getRegistry()); - realmConfigBuilder = interceptor.intercept(realmConfigBuilder, instanceContext); + if (managed) { + RealmConfig config = SupplierHelpers.getInstance(instanceContext.getAnnotation().config()); + RealmConfigBuilder realmConfigBuilder = config.configure(RealmConfigBuilder.create()); - RealmRepresentation realmRepresentation = realmConfigBuilder.build(); + RealmConfigInterceptorHelper interceptor = new RealmConfigInterceptorHelper(instanceContext.getRegistry()); + realmConfigBuilder = interceptor.intercept(realmConfigBuilder, instanceContext); - if (realmRepresentation.getRealm() == null) { - String realmName = SupplierHelpers.createName(instanceContext); - realmRepresentation.setRealm(realmName); - } + realmRepresentation = realmConfigBuilder.build(); - if (realmRepresentation.getId() == null) { - realmRepresentation.setId(realmRepresentation.getRealm()); - } + if (realmRepresentation.getRealm() == null) { + realmRepresentation.setRealm(SupplierHelpers.createName(instanceContext)); + } - String realmName = realmRepresentation.getRealm(); - instanceContext.addNote(REALM_NAME_KEY, realmName); + if (realmRepresentation.getId() == null) { + realmRepresentation.setId(realmRepresentation.getRealm()); + } - if (instanceContext.getAnnotation().createRealm()) { adminClient.realms().create(realmRepresentation); + + // TODO Token needs to be invalidated after creating realm to have roles for new realm in the token. Maybe lightweight access tokens could help. + adminClient.tokenManager().invalidate(adminClient.tokenManager().getAccessTokenString()); + } else { + realmRepresentation = adminClient.realm(attachTo).toRepresentation(); } - // TODO Token needs to be invalidated after creating realm to have roles for new realm in the token. Maybe lightweight access tokens could help. - adminClient.tokenManager().invalidate(adminClient.tokenManager().getAccessTokenString()); + instanceContext.addNote("managed", managed); RealmResource realmResource = adminClient.realm(realmRepresentation.getRealm()); - return new ManagedRealm(server.getBaseUrl() + "/realms/" + realmName, realmRepresentation, realmResource); + return new ManagedRealm(server.getBaseUrl() + "/realms/" + realmRepresentation.getRealm(), realmRepresentation, realmResource); } @Override @@ -76,7 +78,7 @@ public class RealmSupplier implements Supplier { @Override public void close(InstanceContext instanceContext) { - if (instanceContext.getAnnotation().createRealm()) { + if (instanceContext.getNote("managed", Boolean.class)) { instanceContext.getValue().admin().remove(); } } diff --git a/test-framework/examples/tests/src/test/java/org/keycloak/test/examples/AttachToTest.java b/test-framework/examples/tests/src/test/java/org/keycloak/test/examples/AttachToTest.java new file mode 100644 index 00000000000..bc6a77a6e16 --- /dev/null +++ b/test-framework/examples/tests/src/test/java/org/keycloak/test/examples/AttachToTest.java @@ -0,0 +1,59 @@ +package org.keycloak.test.examples; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.testframework.annotations.InjectAdminClient; +import org.keycloak.testframework.annotations.InjectClient; +import org.keycloak.testframework.annotations.InjectRealm; +import org.keycloak.testframework.annotations.KeycloakIntegrationTest; +import org.keycloak.testframework.realm.ManagedClient; +import org.keycloak.testframework.realm.ManagedRealm; + +@KeycloakIntegrationTest +@TestMethodOrder(MethodOrderer.MethodName.class) +public class AttachToTest { + + @InjectAdminClient + Keycloak adminClient; + + @InjectRealm(attachTo = "master") + ManagedRealm attachedRealm; + + @InjectClient + ManagedClient managedClient; + + @InjectClient(ref = "admin-cli", attachTo = "admin-cli") + ManagedClient attachedClient; + + @Test + public void aAttachedRealm() { + Assertions.assertEquals("master", attachedRealm.getName()); + Assertions.assertEquals("master", attachedRealm.admin().toRepresentation().getRealm()); + attachedRealm.updateWithCleanup(r -> r.editUsernameAllowed(true)); + } + + @Test + public void bRealmCleanup() { + Assertions.assertFalse(attachedRealm.admin().toRepresentation().isEditUsernameAllowed()); + } + + @Test + public void cManagedClient() { + Assertions.assertEquals("default", adminClient.realm("master").clients().get(managedClient.getId()).toRepresentation().getClientId()); + } + + @Test + public void dAttachedClient() { + Assertions.assertEquals("admin-cli", attachedClient.getClientId()); + Assertions.assertEquals("admin-cli", attachedClient.admin().toRepresentation().getClientId()); + } + + @Test + public void eManagedClient() { + Assertions.assertEquals("default", managedClient.getClientId()); + Assertions.assertEquals("default", managedClient.admin().toRepresentation().getClientId()); + } +} diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/AdminSignatureAlgorithmTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/AdminSignatureAlgorithmTest.java index 9134ebabb76..b728246c39a 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/AdminSignatureAlgorithmTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/AdminSignatureAlgorithmTest.java @@ -19,7 +19,7 @@ public class AdminSignatureAlgorithmTest { @InjectAdminClient Keycloak admin; - @InjectRealm(ref = "master", createRealm = false) + @InjectRealm(attachTo = "master") ManagedRealm masterRealm; @Test diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/AbstractPermissionTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/AbstractPermissionTest.java index 4e1728f7fb1..9db90089e00 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/AbstractPermissionTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/AbstractPermissionTest.java @@ -39,7 +39,7 @@ public abstract class AbstractPermissionTest { @InjectRealm(config = RealmAdminPermissionsConfig.class) ManagedRealm realm; - @InjectClient(ref = Constants.ADMIN_PERMISSIONS_CLIENT_ID, createClient = false) + @InjectClient(attachTo = Constants.ADMIN_PERMISSIONS_CLIENT_ID) ManagedClient client; protected PermissionsResource getPermissionsResource() { diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureDisabledTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureDisabledTest.java index 5891468fd55..e06bf37cd5c 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureDisabledTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureDisabledTest.java @@ -28,7 +28,7 @@ import org.keycloak.testframework.realm.ManagedClient; @KeycloakIntegrationTest public class FeatureDisabledTest { - @InjectClient(ref = "test-client", config = AuthzClientConfig.class, createClient = true) + @InjectClient(config = AuthzClientConfig.class) private ManagedClient testClient; @Test diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV1EnabledTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV1EnabledTest.java index b101d632018..f4fe4c847b8 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV1EnabledTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV1EnabledTest.java @@ -28,7 +28,7 @@ import org.keycloak.testframework.realm.ManagedClient; @KeycloakIntegrationTest(config = KeycloakAdminPermissionsV1ServerConfig.class) public class FeatureV1EnabledTest { - @InjectClient(ref = "test-client", config = AuthzClientConfig.class, createClient = true) + @InjectClient(config = AuthzClientConfig.class) private ManagedClient testClient; @Test diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV2EnabledTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV2EnabledTest.java index b1e1eccab84..a2f3b50713d 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV2EnabledTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/FeatureV2EnabledTest.java @@ -40,7 +40,7 @@ public class FeatureV2EnabledTest { @InjectRealm private ManagedRealm realm; - @InjectClient(ref = "test-client", config = AuthzClientConfig.class, createClient = true) + @InjectClient(config = AuthzClientConfig.class) private ManagedClient testClient; @Test