diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java index 4301044c0be9..6eaf4f498224 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -114,6 +114,7 @@ public class RealmRepresentation { @Deprecated protected List defaultRoles; protected RoleRepresentation defaultRole; + protected ClientRepresentation adminPermissionsClient; protected List defaultGroups; @Deprecated protected Set requiredCredentials; @@ -553,6 +554,14 @@ public void setDefaultRole(RoleRepresentation defaultRole) { this.defaultRole = defaultRole; } + public ClientRepresentation getAdminPermissionsClient() { + return adminPermissionsClient; + } + + public void setAdminPermissionsClient(ClientRepresentation adminPermissionsClient) { + this.adminPermissionsClient = adminPermissionsClient; + } + public List getDefaultGroups() { return defaultGroups; } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java index 2541d1f6e2bb..96fee9ba1d53 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java @@ -1094,6 +1094,18 @@ public RoleModel getDefaultRole() { return cached.getDefaultRoleId() == null ? null : cacheSession.getRoleById(this, cached.getDefaultRoleId()); } + @Override + public void setAdminPermissionsClient(ClientModel client) { + getDelegateForUpdate(); + updated.setAdminPermissionsClient(client); + } + + @Override + public ClientModel getAdminPermissionsClient() { + if (isUpdated()) return updated.getAdminPermissionsClient(); + return cached.getAdminPermissionsClientId() == null ? null : cacheSession.getClientById(this, cached.getAdminPermissionsClientId()); + } + @Override public RoleModel getRole(String name) { return cacheSession.getRealmRole(this, name); diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java index c3b9ab087b7d..f32822fb02ba 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java @@ -161,6 +161,7 @@ public class CachedRealm extends AbstractExtendableRevisioned { protected boolean adminEventsEnabled; protected boolean adminEventsDetailsEnabled; protected String defaultRoleId; + protected String adminPermissionsClientId; private boolean allowUserManagedAccess; protected List defaultGroups; @@ -257,6 +258,7 @@ public CachedRealm(Long revision, RealmModel model) { adminEventsEnabled = model.isAdminEventsEnabled(); adminEventsDetailsEnabled = model.isAdminEventsDetailsEnabled(); + adminPermissionsClientId = model.getAdminPermissionsClient() == null ? null : model.getAdminPermissionsClient().getId(); if(Objects.isNull(model.getDefaultRole())) { throw new ModelException("Default Role is null for Realm " + name); @@ -339,6 +341,10 @@ public String getDefaultRoleId() { return defaultRoleId; } + public String getAdminPermissionsClientId() { + return adminPermissionsClientId; + } + public String getName() { return name; } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaClientProviderFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaClientProviderFactory.java index 5276a2204ef7..5d3ac8239238 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaClientProviderFactory.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaClientProviderFactory.java @@ -18,11 +18,15 @@ package org.keycloak.models.jpa; import org.keycloak.Config; +import org.keycloak.common.Profile; import org.keycloak.connections.jpa.JpaConnectionProvider; import org.keycloak.models.ClientProvider; import org.keycloak.models.ClientProviderFactory; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.RealmModel; +import org.keycloak.models.jpa.entities.RealmAttributes; +import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.saml.SamlConfigAttributes; import jakarta.persistence.EntityManager; @@ -30,6 +34,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import static org.keycloak.models.jpa.JpaRealmProviderFactory.PROVIDER_ID; import static org.keycloak.models.jpa.JpaRealmProviderFactory.PROVIDER_PRIORITY; @@ -59,7 +64,20 @@ public void init(Config.Scope config) { @Override public void postInit(KeycloakSessionFactory factory) { + if (Profile.isFeatureEnabled(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ_V2)) { + factory.register(event -> { + if (event instanceof RealmModel.RealmAttributeUpdateEvent attrUpdateEvent) { + if (Objects.equals(attrUpdateEvent.getAttributeName(), RealmAttributes.ADMIN_PERMISSIONS_ENABLED) && Boolean.parseBoolean(attrUpdateEvent.getAttributeValue())) { + KeycloakSession keycloakSession = attrUpdateEvent.getKeycloakSession(); + RealmModel realm = attrUpdateEvent.getRealm(); + if (realm.getAdminPermissionsClient() != null) return; + + KeycloakModelUtils.setupAdminPermissionsClient(keycloakSession, realm); + } + } + }); + } } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 2468f59bcb9c..095bced508c2 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -1206,7 +1206,34 @@ public boolean isAdminPermissionsEnabled() { @Override public void setAdminPermissionsEnabled(boolean adminPermissionsEnabled) { + boolean isAdminPermissionsAlreadyEnabled = getAdminPermissionsClient() != null; setAttribute(RealmAttributes.ADMIN_PERMISSIONS_ENABLED, adminPermissionsEnabled); + + // sending an event if we are enabling the permissions and it was not enabled already + if (adminPermissionsEnabled && !isAdminPermissionsAlreadyEnabled) { + session.getKeycloakSessionFactory().publish(new RealmModel.RealmAttributeUpdateEvent() { + + @Override + public RealmModel getRealm() { + return RealmAdapter.this; + } + + @Override + public String getAttributeName() { + return RealmAttributes.ADMIN_PERMISSIONS_ENABLED; + } + + @Override + public String getAttributeValue() { + return String.valueOf(adminPermissionsEnabled); + } + + @Override + public KeycloakSession getKeycloakSession() { + return session; + } + }); + } } @Override @@ -1251,6 +1278,19 @@ public RoleModel getDefaultRole() { return session.roles().getRoleById(this, realm.getDefaultRoleId()); } + @Override + public void setAdminPermissionsClient(ClientModel client) { + setAttribute(RealmAttributes.ADMIN_PERMISSIONS_CLIENT_ID, client.getId()); + } + + @Override + public ClientModel getAdminPermissionsClient() { + if (getAttribute(RealmAttributes.ADMIN_PERMISSIONS_CLIENT_ID) == null) { + return null; + } + return session.clients().getClientById(this, getAttribute(RealmAttributes.ADMIN_PERMISSIONS_CLIENT_ID)); + } + @Override public Stream getIdentityProvidersStream() { return session.identityProviders().getAllStream(); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributes.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributes.java index dff975eb70b3..751cdef55b07 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributes.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributes.java @@ -60,4 +60,5 @@ public interface RealmAttributes { String ORGANIZATIONS_ENABLED = "organizationsEnabled"; String ADMIN_PERMISSIONS_ENABLED = "adminPermissionsEnabled"; + String ADMIN_PERMISSIONS_CLIENT_ID = "adminPermissionsClientId"; } diff --git a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java index a84689797674..0577e612635b 100644 --- a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java +++ b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java @@ -534,8 +534,13 @@ private static RoleModel getOrAddClientRole(ClientModel client, String name) { } private static Map createClients(KeycloakSession session, RealmRepresentation rep, RealmModel realm, Map mappedFlows) { - Map appMap = new HashMap(); + Map appMap = new HashMap<>(); for (ClientRepresentation resourceRep : rep.getClients()) { + if (Profile.isFeatureEnabled(Feature.ADMIN_FINE_GRAINED_AUTHZ_V2)) { + if (realm.getAdminPermissionsClient() != null && realm.getAdminPermissionsClient().getClientId().equals(resourceRep.getClientId())) { + continue; // admin-permission-client is already imported at this point + } + } ClientModel app = RepresentationToModel.createClient(session, realm, resourceRep, mappedFlows); String postLogoutRedirectUris = app.getAttribute(OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS); if (postLogoutRedirectUris == null) { diff --git a/server-spi-private/src/main/java/org/keycloak/models/Constants.java b/server-spi-private/src/main/java/org/keycloak/models/Constants.java index 8ef31926d624..f108f4e256c3 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/Constants.java +++ b/server-spi-private/src/main/java/org/keycloak/models/Constants.java @@ -188,4 +188,6 @@ public final class Constants { //attribute name used to mark a temporary admin user/service account as temporary public static final String IS_TEMP_ADMIN_ATTR_NAME = "is_temporary_admin"; + + public static final String ADMIN_PERMISSIONS_CLIENT_ID = "admin-permissions"; } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index a75c3d4956ea..9348aeaa74c4 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -1188,4 +1188,11 @@ public static void setDefaultGroups(KeycloakSession session, RealmModel realm, S public static boolean isAdminPermissionsEnabled(RealmModel realm) { return Profile.isFeatureEnabled(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ_V2) && realm.isAdminPermissionsEnabled(); } + + public static void setupAdminPermissionsClient(KeycloakSession session, RealmModel realm) { + ClientModel client = session.clients().addClient(realm, Constants.ADMIN_PERMISSIONS_CLIENT_ID); + realm.setAdminPermissionsClient(client); + RepresentationToModel.createResourceServer(client, session, false); + } + } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index b23a6259ae58..800a2e1dcb60 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -126,6 +126,7 @@ public class ModelToRepresentation { REALM_EXCLUDED_ATTRIBUTES.add("organizationsEnabled"); REALM_EXCLUDED_ATTRIBUTES.add("verifiableCredentialsEnabled"); REALM_EXCLUDED_ATTRIBUTES.add("adminPermissionsEnabled"); + REALM_EXCLUDED_ATTRIBUTES.add("adminPermissionsClientId"); } public static Set CLIENT_EXCLUDED_ATTRIBUTES = new HashSet<>(); @@ -509,6 +510,14 @@ public static RealmRepresentation toRepresentation(KeycloakSession session, Real rep.setDefaultRole(toBriefRepresentation(realm.getDefaultRole())); + if (realm.getAdminPermissionsClient() != null) { + ClientModel adminPermissionsClient = realm.getAdminPermissionsClient(); + ClientRepresentation clientRep = new ClientRepresentation(); + clientRep.setId(adminPermissionsClient.getId()); + clientRep.setClientId(adminPermissionsClient.getClientId()); + rep.setAdminPermissionsClient(clientRep); + } + List defaultGroups = realm.getDefaultGroupsStream() .map(ModelToRepresentation::buildGroupPath).collect(Collectors.toList()); if (!defaultGroups.isEmpty()) { @@ -1037,8 +1046,6 @@ public static ScopeRepresentation toRepresentation(Scope model) { } public static ResourceServerRepresentation toRepresentation(ResourceServer model, ClientModel client) { - RealmModel realm = client.getRealm(); - ResourceServerRepresentation server = new ResourceServerRepresentation(); server.setId(model.getId()); @@ -1047,11 +1054,22 @@ public static ResourceServerRepresentation toRepresentation(ResourceServer model server.setAllowRemoteResourceManagement(model.isAllowRemoteResourceManagement()); server.setPolicyEnforcementMode(model.getPolicyEnforcementMode()); server.setDecisionStrategy(model.getDecisionStrategy()); - server.setAuthorizationSchema(KeycloakModelUtils.isAdminPermissionsEnabled(realm) ? AdminPermissionsAuthorizationSchema.INSTANCE : null); + server.setAuthorizationSchema(getAuthorizationSchema(client)); return server; } + private static AuthorizationSchema getAuthorizationSchema(ClientModel client) { + if (!KeycloakModelUtils.isAdminPermissionsEnabled(client.getRealm())) { + return null; + } + ClientModel adminPermissionsClient = client.getRealm().getAdminPermissionsClient(); + if (adminPermissionsClient == null || ! client.getClientId().equals(adminPermissionsClient.getClientId())) { + return null; + } + return AdminPermissionsAuthorizationSchema.INSTANCE; + } + public static R toRepresentation(Policy policy, AuthorizationProvider authorization) { return toRepresentation(policy, authorization, false, true); } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java index 52da89c29285..d99baded2a60 100644 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java @@ -973,6 +973,16 @@ public void setDefaultRole(RoleModel role) { delegate.setDefaultRole(role); } + @Override + public ClientModel getAdminPermissionsClient() { + return delegate.getAdminPermissionsClient(); + } + + @Override + public void setAdminPermissionsClient(ClientModel client) { + delegate.setAdminPermissionsClient(client); + } + public boolean isIdentityFederationEnabled() { return delegate.isIdentityFederationEnabled(); } diff --git a/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java b/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java index d8d0749c6461..155e9c44b9c0 100644 --- a/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java +++ b/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java @@ -1620,6 +1620,15 @@ public void setDefaultRole(RoleModel role) { } + @Override + public ClientModel getAdminPermissionsClient() { + return null; + } + + @Override + public void setAdminPermissionsClient(ClientModel client) { + } + @Override public boolean isIdentityFederationEnabled() { return false; diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java index 03e8962bdde6..b2bc786a54ba 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java @@ -63,6 +63,13 @@ interface IdentityProviderRemovedEvent extends ProviderEvent { KeycloakSession getKeycloakSession(); } + interface RealmAttributeUpdateEvent extends ProviderEvent { + RealmModel getRealm(); + String getAttributeName(); + String getAttributeValue(); + KeycloakSession getKeycloakSession(); + } + @Override String getId(); @@ -677,6 +684,10 @@ default Stream getStorageProviders(Class sto */ void setDefaultRole(RoleModel role); + ClientModel getAdminPermissionsClient(); + + void setAdminPermissionsClient(ClientModel client); + /** * @deprecated use {@link IdentityProviderStorageProvider#isIdentityFederationEnabled()} instead. */ diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index a2fbdca94295..018bacf1a7d5 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -561,6 +561,16 @@ public RealmModel importRealm(RealmRepresentation rep, boolean skipUserDependent realm.setDefaultRole(RepresentationToModel.createRole(realm, rep.getDefaultRole())); } + if (Profile.isFeatureEnabled(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ_V2)) { + if (rep.getAdminPermissionsClient() != null) { + ClientModel client = RepresentationToModel.createClient(session, realm, rep.getAdminPermissionsClient()); + realm.setAdminPermissionsClient(client); + RepresentationToModel.createResourceServer(client, session, false); + } else if (Boolean.TRUE.equals(rep.isAdminPermissionsEnabled())) { + KeycloakModelUtils.setupAdminPermissionsClient(session, realm); + } + } + boolean postponeMasterClientSetup = postponeMasterClientSetup(rep); if (!postponeMasterClientSetup) { setupMasterAdminManagement(realm); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/AdminPermissionsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/AdminPermissionsTest.java similarity index 87% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/AdminPermissionsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/AdminPermissionsTest.java index a42630d25bd0..19e520e9a11a 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/AdminPermissionsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/AdminPermissionsTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.keycloak.testsuite.authz.admin; +package org.keycloak.testsuite.authz.admin.permissions; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; @@ -73,13 +73,24 @@ public void authorizationSchemaAvailableFeatureV2Enabled() throws Exception { assertThat(clients, hasSize(1)); ResourceServerRepresentation authorizationSettings = testRealm().clients().get(clients.get(0).getId()).authorization().getSettings(); assertThat(authorizationSettings, notNullValue()); + //admin permissions not enabled for the realm assertThat(authorizationSettings.getAuthorizationSchema(), nullValue()); try (RealmAttributeUpdater rau = new RealmAttributeUpdater(testRealm()).setAdminPermissionsEnabled(Boolean.TRUE).update()) { authorizationSettings = testRealm().clients().get(clients.get(0).getId()).authorization().getSettings(); assertThat(authorizationSettings, notNullValue()); + + //schema should be available only for admin-permissions client + assertThat(authorizationSettings.getAuthorizationSchema(), nullValue()); + + //get the admin-permissions client + ClientRepresentation adminPermissionsClient = testRealm().toRepresentation().getAdminPermissionsClient(); + assertThat(adminPermissionsClient, notNullValue()); + + authorizationSettings = testRealm().clients().get(adminPermissionsClient.getId()).authorization().getSettings(); assertThat(authorizationSettings.getAuthorizationSchema(), notNullValue()); } } + } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/ExportImportTestWithFGAPV2Enabled.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/ExportImportTestWithFGAPV2Enabled.java new file mode 100644 index 000000000000..ac6c82aa8adf --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/permissions/ExportImportTestWithFGAPV2Enabled.java @@ -0,0 +1,124 @@ +/* + * Copyright 2024 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.authz.admin.permissions; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import org.junit.After; +import org.junit.Test; +import org.keycloak.common.Profile; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; +import org.keycloak.testsuite.arquillian.annotation.EnableFeature; +import org.keycloak.testsuite.exportimport.ExportImportTest; + +@EnableFeature(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ_V2) +public class ExportImportTestWithFGAPV2Enabled extends ExportImportTest { + + private final String REALM_NAME = "fgap"; + private final String CUSTOM_CLIENT_ID = "imported-permission-client"; + + @After + public void cleanup() { + removeRealm(REALM_NAME); + } + + @Test + public void testCreateRealmWithSwitchOnAndNoAdminPermissionsClient() { + RealmRepresentation rep = new RealmRepresentation(); + rep.setRealm(REALM_NAME); + rep.setAdminPermissionsEnabled(Boolean.TRUE); + + adminClient.realms().create(rep); + + assertTrue(adminClient.realm(REALM_NAME).toRepresentation().isAdminPermissionsEnabled()); + + //admin-permissions client should be created + ClientRepresentation client = adminClient.realm(REALM_NAME).toRepresentation().getAdminPermissionsClient(); + + assertThat(client, notNullValue()); + + ResourceServerRepresentation authorizationSettings = adminClient.realm(REALM_NAME).clients().get(client.getId()).authorization().getSettings(); + assertThat(authorizationSettings, notNullValue()); + assertThat(authorizationSettings.getAuthorizationSchema(), notNullValue()); + } + + @Test + public void testCreateRealmWithSwitchOnAndAdminPermissionsClient() { + RealmRepresentation rep = new RealmRepresentation(); + rep.setRealm(REALM_NAME); + rep.setAdminPermissionsEnabled(Boolean.TRUE); + + ClientRepresentation clientRep = new ClientRepresentation(); + clientRep.setClientId(CUSTOM_CLIENT_ID); + clientRep.setServiceAccountsEnabled(Boolean.TRUE); + + rep.setAdminPermissionsClient(clientRep); + rep.setClients(List.of(clientRep)); + + adminClient.realms().create(rep); + + assertTrue(adminClient.realm(REALM_NAME).toRepresentation().isAdminPermissionsEnabled()); + + //admin-permissions client (imported-permission-client) should be created + ClientRepresentation client = adminClient.realm(REALM_NAME).toRepresentation().getAdminPermissionsClient(); + + assertThat(client, notNullValue()); + assertThat(client.getClientId(), equalTo(CUSTOM_CLIENT_ID)); + + ResourceServerRepresentation authorizationSettings = adminClient.realm(REALM_NAME).clients().get(client.getId()).authorization().getSettings(); + assertThat(authorizationSettings, notNullValue()); + assertThat(authorizationSettings.getAuthorizationSchema(), notNullValue()); + } + + @Test + public void testCreateRealmWithSwitchOffAndAdminPermissionsClient() { + RealmRepresentation rep = new RealmRepresentation(); + rep.setRealm(REALM_NAME); + + ClientRepresentation clientRep = new ClientRepresentation(); + clientRep.setClientId(CUSTOM_CLIENT_ID); + clientRep.setServiceAccountsEnabled(Boolean.TRUE); + + rep.setAdminPermissionsClient(clientRep); + rep.setClients(List.of(clientRep)); + + adminClient.realms().create(rep); + + assertFalse(adminClient.realm(REALM_NAME).toRepresentation().isAdminPermissionsEnabled()); + + //admin-permissions client (imported-permission-client) should be created + ClientRepresentation client = adminClient.realm(REALM_NAME).toRepresentation().getAdminPermissionsClient(); + + assertThat(client, notNullValue()); + assertThat(client.getClientId(), equalTo(CUSTOM_CLIENT_ID)); + + ResourceServerRepresentation authorizationSettings = adminClient.realm(REALM_NAME).clients().get(client.getId()).authorization().getSettings(); + assertThat(authorizationSettings, notNullValue()); + + // schema should not be available as the realm switch is off + assertThat(authorizationSettings.getAuthorizationSchema(), nullValue()); + } + +}