keycloak-aplcache

restricting admin role mapping

6/22/2017 5:51:46 PM

Details

diff --git a/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java b/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
index cf605d1..c2304e8 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.models;
 
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -55,4 +56,14 @@ public class AdminRoles {
 
     public static String[] ALL_REALM_ROLES = {CREATE_CLIENT, VIEW_REALM, VIEW_USERS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, VIEW_AUTHORIZATION, MANAGE_REALM, MANAGE_USERS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS, MANAGE_AUTHORIZATION, QUERY_USERS, QUERY_CLIENTS, QUERY_REALMS, QUERY_GROUPS};
 
+    public static Set<String> ALL_ROLES = new HashSet<>();
+    static {
+        for (String name : ALL_REALM_ROLES) {
+            ALL_ROLES.add(name);
+        }
+        ALL_ROLES.add(ImpersonationConstants.IMPERSONATION_ROLE);
+        ALL_ROLES.add(ADMIN);
+        ALL_ROLES.add(CREATE_REALM);
+        ALL_ROLES.add(CREATE_CLIENT);
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
index e01f4eb..d220a39 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
@@ -17,6 +17,7 @@
 package org.keycloak.services.resources.admin.permissions;
 
 import org.jboss.logging.Logger;
+import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
@@ -25,6 +26,7 @@ import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.models.AdminRoles;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ImpersonationConstants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
@@ -129,6 +131,131 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         return root.resourceServer(client);
     }
 
+    private boolean checkAdminRoles(RoleModel role) {
+        if (AdminRoles.ALL_ROLES.contains(role.getName())) {
+            if (root.admin().hasRole(role)) return true;
+
+            ClientModel adminClient = root.getRealmManagementClient();
+            if (adminClient.equals(role.getContainer())) {
+                // if this is realm admin role, then check to see if admin has similar permissions
+                // we do this so that the authz service is invoked
+                if (role.getName().equals(AdminRoles.MANAGE_CLIENTS)) {
+                    if (!root.clients().canManage()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_CLIENTS)) {
+                    if (!root.clients().canView()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.QUERY_CLIENTS)) {
+                    return true;
+                } else if (role.getName().equals(AdminRoles.QUERY_USERS)) {
+                    return true;
+                } else if (role.getName().equals(AdminRoles.QUERY_GROUPS)) {
+                    return true;
+                } else if (role.getName().equals(AdminRoles.MANAGE_AUTHORIZATION)) {
+                    if (!root.realm().canManageAuthorization()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_AUTHORIZATION)) {
+                    if (!root.realm().canViewAuthorization()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.MANAGE_EVENTS)) {
+                    if (!root.realm().canManageEvents()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_EVENTS)) {
+                    if (!root.realm().canViewEvents()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.MANAGE_USERS)) {
+                    if (!root.users().canManage()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_USERS)) {
+                    if (!root.users().canView()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.MANAGE_IDENTITY_PROVIDERS)) {
+                    if (!root.realm().canManageIdentityProviders()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_IDENTITY_PROVIDERS)) {
+                    if (!root.realm().canViewIdentityProviders()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.MANAGE_REALM)) {
+                    if (!root.realm().canManageRealm()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(AdminRoles.VIEW_REALM)) {
+                    if (!root.realm().canViewRealm()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else if (role.getName().equals(ImpersonationConstants.IMPERSONATION_ROLE)) {
+                    if (!root.users().canImpersonate()) {
+                        return adminConflictMessage(role);
+                    } else {
+                        return true;
+                    }
+                } else {
+                    return adminConflictMessage(role);
+                }
+
+            } else {
+                // now we need to check to see if this is a master admin role
+                if (role.getContainer() instanceof RealmModel) {
+                    RealmModel realm = (RealmModel)role.getContainer();
+                    // If realm role is master admin role then abort
+                    if (realm.getName().equals(Config.getAdminRealm())) {
+                        return adminConflictMessage(role);
+                    }
+                } else {
+                    ClientModel container = (ClientModel)role.getContainer();
+                    // abort if this is an role in master realm and role is an admin role of any realm
+                    if (container.getRealm().getName().equals(Config.getAdminRealm())
+                            && container.getClientId().endsWith("-realm")) {
+                        return adminConflictMessage(role);
+                    }
+                }
+                return true;
+            }
+
+        }
+        return true;
+
+    }
+
+    private boolean adminConflictMessage(RoleModel role) {
+        logger.debug("Trying to assign admin privileges of role: " + role.getName() + " but admin doesn't have same privilege");
+        return false;
+    }
+
     /**
      * Is admin allowed to map this role?
      *
@@ -137,7 +264,7 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
      */
     @Override
     public boolean canMapRole(RoleModel role) {
-        if (root.users().canManageDefault()) return true;
+        if (root.users().canManageDefault()) return checkAdminRoles(role);
         if (!root.isAdminSameRealm()) {
             return false;
         }
@@ -159,7 +286,11 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
 
         Resource roleResource = resource(role);
         Scope mapRoleScope = mapRoleScope(resourceServer);
-        return root.evaluatePermission(roleResource, mapRoleScope, resourceServer);
+        if (root.evaluatePermission(roleResource, mapRoleScope, resourceServer)) {
+            return checkAdminRoles(role);
+        } else {
+            return true;
+        }
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
index 74163d9..40b1f8f 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
@@ -49,6 +49,8 @@ public interface UserPermissionEvaluator {
 
     boolean canImpersonate(UserModel user);
 
+    boolean canImpersonate();
+
     void requireImpersonate(UserModel user);
 
     Map<String, Boolean> getAccess(UserModel user);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
index 13f8aca..46a9d01 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
@@ -451,6 +451,12 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
 
     @Override
     public boolean canImpersonate(UserModel user) {
+        return canImpersonate();
+
+    }
+
+    @Override
+    public boolean canImpersonate() {
         if (root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE)) return true;
 
         if (!root.isAdminSameRealm()) {
@@ -476,7 +482,6 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
 
         Scope scope = root.realmScope(IMPERSONATE_SCOPE);
         return root.evaluatePermission(resource, scope, server);
-
     }
 
     @Override
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IllegalAdminUpgradeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IllegalAdminUpgradeTest.java
new file mode 100644
index 0000000..7c6ced5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IllegalAdminUpgradeTest.java
@@ -0,0 +1,648 @@
+/*
+ * 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.admin;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.ImpersonationConstants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.util.AdminClientUtil;
+
+import javax.ws.rs.ClientErrorException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IllegalAdminUpgradeTest extends AbstractKeycloakTest {
+
+    public static final String CLIENT_NAME = "application";
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+        RealmRepresentation testRealmRep = new RealmRepresentation();
+        testRealmRep.setId(TEST);
+        testRealmRep.setRealm(TEST);
+        testRealmRep.setEnabled(true);
+        testRealms.add(testRealmRep);
+    }
+
+    protected boolean isImportAfterEachMethod() {
+        return true;
+    }
+
+
+    public static void setupUsers(KeycloakSession session) {
+        RealmModel realm = session.realms().getRealmByName(TEST);
+        RealmModel master = session.realms().getRealmByName("master");
+        ClientModel realmAdminClient = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+        ClientModel realmMasterAdminClient = realm.getMasterAdminClient();
+        RoleModel realmManageUsers = realmAdminClient.getRole(AdminRoles.MANAGE_USERS);
+        RoleModel masterManageUsers = realmMasterAdminClient.getRole(AdminRoles.MANAGE_USERS);
+        RoleModel masterMasterManageUSers = master.getMasterAdminClient().getRole(AdminRoles.MANAGE_USERS);
+
+        UserModel realmUser = session.users().addUser(realm, "userAdmin");
+        realmUser.grantRole(realmManageUsers);
+        realmUser.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, realmUser, UserCredentialModel.password("password"));
+
+        UserModel masterUser = session.users().addUser(master, "userAdmin");
+        masterUser.grantRole(masterManageUsers);
+        masterUser.setEnabled(true);
+        session.userCredentialManager().updateCredential(master, masterUser, UserCredentialModel.password("password"));
+
+        UserModel masterAdmin = session.users().addUser(master, "masterAdmin");
+        masterAdmin.grantRole(masterMasterManageUSers);
+        masterAdmin.setEnabled(true);
+        session.userCredentialManager().updateCredential(master, masterAdmin, UserCredentialModel.password("password"));
+
+        UserModel user = session.users().addUser(master, "user");
+        user.grantRole(masterManageUsers);
+        user.setEnabled(true);
+        session.userCredentialManager().updateCredential(master, user, UserCredentialModel.password("password"));
+
+        user = session.users().addUser(realm, "user");
+        user.grantRole(realmManageUsers);
+        user.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, user, UserCredentialModel.password("password"));
+    }
+
+    @Test
+    public void testRestEvaluation() throws Exception {
+        testingClient.server().run(IllegalAdminUpgradeTest::setupUsers);
+
+        UserRepresentation realmUserAdmin = adminClient.realm(TEST).users().search("userAdmin").get(0);
+        UserRepresentation masterUserAdmin = adminClient.realm("master").users().search("userAdmin").get(0);
+        UserRepresentation realmUser = adminClient.realm(TEST).users().search("user").get(0);
+        UserRepresentation masterUser = adminClient.realm("master").users().search("user").get(0);
+
+        ClientRepresentation realmAdminClient = adminClient.realm(TEST).clients().findByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID).get(0);
+        RoleRepresentation realmManageAuthorization = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_AUTHORIZATION).toRepresentation();
+        RoleRepresentation realmViewAuthorization = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_AUTHORIZATION).toRepresentation();
+        RoleRepresentation realmManageClients = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_CLIENTS).toRepresentation();
+        RoleRepresentation realmViewClients = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_CLIENTS).toRepresentation();
+        RoleRepresentation realmManageEvents = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_EVENTS).toRepresentation();
+        RoleRepresentation realmViewEvents = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_EVENTS).toRepresentation();
+        RoleRepresentation realmManageIdentityProviders = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_IDENTITY_PROVIDERS).toRepresentation();
+        RoleRepresentation realmViewIdentityProviders = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_IDENTITY_PROVIDERS).toRepresentation();
+        RoleRepresentation realmManageRealm = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_REALM).toRepresentation();
+        RoleRepresentation realmViewRealm = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_REALM).toRepresentation();
+        RoleRepresentation realmImpersonate = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(ImpersonationConstants.IMPERSONATION_ROLE).toRepresentation();
+        RoleRepresentation realmManageUsers = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.MANAGE_USERS).toRepresentation();
+        RoleRepresentation realmViewUsers = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.VIEW_USERS).toRepresentation();
+        RoleRepresentation realmQueryUsers = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.QUERY_USERS).toRepresentation();
+        RoleRepresentation realmQueryClients = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.QUERY_CLIENTS).toRepresentation();
+        RoleRepresentation realmQueryGroups = adminClient.realm(TEST).clients().get(realmAdminClient.getId()).roles().get(AdminRoles.QUERY_GROUPS).toRepresentation();
+
+        ClientRepresentation masterClient = adminClient.realm("master").clients().findByClientId(TEST + "-realm").get(0);
+        RoleRepresentation masterManageAuthorization = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_AUTHORIZATION).toRepresentation();
+        RoleRepresentation masterViewAuthorization = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_AUTHORIZATION).toRepresentation();
+        RoleRepresentation masterManageClients = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_CLIENTS).toRepresentation();
+        RoleRepresentation masterViewClients = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_CLIENTS).toRepresentation();
+        RoleRepresentation masterManageEvents = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_EVENTS).toRepresentation();
+        RoleRepresentation masterViewEvents = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_EVENTS).toRepresentation();
+        RoleRepresentation masterManageIdentityProviders = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_IDENTITY_PROVIDERS).toRepresentation();
+        RoleRepresentation masterViewIdentityProviders = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_IDENTITY_PROVIDERS).toRepresentation();
+        RoleRepresentation masterManageRealm = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_REALM).toRepresentation();
+        RoleRepresentation masterViewRealm = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_REALM).toRepresentation();
+        RoleRepresentation masterImpersonate = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(ImpersonationConstants.IMPERSONATION_ROLE).toRepresentation();
+        RoleRepresentation masterManageUsers = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.MANAGE_USERS).toRepresentation();
+        RoleRepresentation masterViewUsers = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.VIEW_USERS).toRepresentation();
+        RoleRepresentation masterQueryUsers = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.QUERY_USERS).toRepresentation();
+        RoleRepresentation masterQueryClients = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.QUERY_CLIENTS).toRepresentation();
+        RoleRepresentation masterQueryGroups = adminClient.realm("master").clients().get(masterClient.getId()).roles().get(AdminRoles.QUERY_GROUPS).toRepresentation();
+
+        List<RoleRepresentation> roles = new LinkedList<>();
+
+        {
+            ClientRepresentation client = realmAdminClient;
+            Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
+                    TEST, "userAdmin", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
+            roles.clear();
+            roles.add(realmManageAuthorization);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmViewAuthorization);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmManageClients);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmViewClients);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmManageEvents);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmViewEvents);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmManageIdentityProviders);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmViewIdentityProviders);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmManageRealm);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmViewRealm);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmImpersonate);
+            try {
+                realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(realmManageUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmQueryUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmQueryGroups);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmQueryClients);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            realmClient.close();
+        }
+        // test master manageUsers only admin can do with master realm admin roles
+        {
+            ClientRepresentation client = masterClient;
+            Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
+                    "master", "masterAdmin", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
+            roles.clear();
+            roles.add(masterManageAuthorization);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewAuthorization);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterManageClients);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewClients);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterManageEvents);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewEvents);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterManageIdentityProviders);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewIdentityProviders);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterManageRealm);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewRealm);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterImpersonate);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterManageUsers);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterViewUsers);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterQueryUsers);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterQueryGroups);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            roles.clear();
+            roles.add(masterQueryClients);
+            try {
+                realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+            realmClient.close();
+        }
+        // test master admin can add all admin roles in realm
+        {
+            ClientRepresentation client = realmAdminClient;
+            Keycloak realmClient = AdminClientUtil.createAdminClient();
+            roles.clear();
+            roles.add(realmManageAuthorization);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewAuthorization);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmManageClients);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewClients);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmManageEvents);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewEvents);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmManageIdentityProviders);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewIdentityProviders);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmManageRealm);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmViewRealm);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmImpersonate);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmManageUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(realmViewUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(realmQueryUsers);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(realmQueryGroups);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(realmQueryClients);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm(TEST).users().get(realmUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            realmClient.close();
+        }
+        // test that "admin" in master realm can assign all roles of master realm realm client admin roles
+        {
+            ClientRepresentation client = masterClient;
+            Keycloak realmClient = AdminClientUtil.createAdminClient();
+            roles.clear();
+            roles.add(masterManageAuthorization);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterViewAuthorization);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterManageClients);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterViewClients);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterManageEvents);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterViewEvents);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterManageIdentityProviders);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterViewIdentityProviders);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterManageRealm);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterViewRealm);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterImpersonate);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterManageUsers);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(masterViewUsers);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(masterQueryUsers);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+
+            roles.clear();
+            roles.add(masterQueryGroups);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            roles.clear();
+            roles.add(masterQueryClients);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).add(roles);
+            realmClient.realm("master").users().get(masterUser.getId()).roles().clientLevel(client.getId()).remove(roles);
+
+            realmClient.close();
+        }
+    }
+
+
+
+
+}