mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Allow mapping Admin roles by server administrator only
Closes #39956 # Conflicts: # services/src/main/java/org/keycloak/services/resources/admin/fgap/RolePermissionsV2.java # tests/base/src/test/java/org/keycloak/tests/admin/authz/fgap/RoleResourceTypeEvaluationTest.java Signed-off-by: vramik <vramik@redhat.com>
This commit is contained in:
parent
e36fff1287
commit
e5a2d3789d
@ -19,6 +19,7 @@ package org.keycloak.services.resources.admin.permissions;
|
||||
|
||||
import static org.keycloak.authorization.AdminPermissionsSchema.ROLES_RESOURCE_TYPE;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AdminPermissionsSchema;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
@ -49,12 +50,28 @@ public class RolePermissionsV2 extends RolePermissions {
|
||||
super(session, realm, authz, root);
|
||||
}
|
||||
|
||||
private boolean hasMasterAdminRole() {
|
||||
RealmModel masterRealm = root.adminsRealm().getName().equals(Config.getAdminRealm()) ?
|
||||
root.adminsRealm():
|
||||
session.realms().getRealmByName(Config.getAdminRealm());
|
||||
|
||||
RoleModel adminRole = masterRealm.getRole(AdminRoles.ADMIN);
|
||||
return root.admin().hasRole(adminRole);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMapClientScope(RoleModel role) {
|
||||
if (root.clients().canManageClientsDefault()) return true;
|
||||
|
||||
if (role.getContainer() instanceof ClientModel clientModel) {
|
||||
if (root.clients().canMapClientScopeRoles(clientModel)) return true;
|
||||
if (root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS)) {
|
||||
return true;
|
||||
}
|
||||
if (root.clients().canMapClientScopeRoles(clientModel)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (root.hasOneAdminRole(AdminRoles.MANAGE_REALM)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasPermission(role, MAP_ROLE_CLIENT_SCOPE_SCOPE);
|
||||
@ -62,24 +79,32 @@ public class RolePermissionsV2 extends RolePermissions {
|
||||
|
||||
@Override
|
||||
public boolean canMapComposite(RoleModel role) {
|
||||
if (canManageDefault(role)) return checkAdminRoles(role);
|
||||
if (AdminRoles.ALL_ROLES.contains(role.getName()) && !hasMasterAdminRole()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (role.getContainer() instanceof ClientModel clientModel) {
|
||||
if (root.clients().canMapCompositeRoles(clientModel)) return true;
|
||||
}
|
||||
|
||||
return hasPermission(role, MAP_ROLE_COMPOSITE_SCOPE) && checkAdminRoles(role);
|
||||
return hasPermission(role, MAP_ROLE_COMPOSITE_SCOPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMapRole(RoleModel role) {
|
||||
if (root.hasOneAdminRole(AdminRoles.MANAGE_USERS)) return checkAdminRoles(role);
|
||||
if (AdminRoles.ALL_ROLES.contains(role.getName()) && !hasMasterAdminRole()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (root.hasOneAdminRole(AdminRoles.MANAGE_USERS)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (role.getContainer() instanceof ClientModel clientModel) {
|
||||
if (root.clients().canMapRoles(clientModel)) return true;
|
||||
}
|
||||
|
||||
return hasPermission(role, MAP_ROLE_SCOPE) && checkAdminRoles(role);
|
||||
return hasPermission(role, MAP_ROLE_SCOPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -25,6 +25,7 @@ import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.ClientScopeResource;
|
||||
import org.keycloak.admin.client.resource.ScopePermissionsResource;
|
||||
import org.keycloak.authorization.AdminPermissionsSchema;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ClientScopeRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
@ -171,4 +172,35 @@ public class RoleResourceTypeEvaluationTest extends AbstractPermissionTest {
|
||||
assertThat(ex, instanceOf(ForbiddenException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMappingAdminRoles() {
|
||||
UserRepresentation myadmin = realm.admin().users().search("myadmin").get(0);
|
||||
ClientRepresentation realmManagement = realm.admin().clients().findByClientId("realm-management").get(0);
|
||||
RoleRepresentation createClientRole = realm.admin().clients().get(realmManagement.getId()).roles().get(AdminRoles.CREATE_CLIENT).toRepresentation();
|
||||
|
||||
// create permission to map roles from all clients and to all users
|
||||
UserPolicyRepresentation onlyMyAdminUserPolicy = createUserPolicy(realm, client, "Only My Admin User Policy", myadmin.getId());
|
||||
createAllPermission(client, AdminPermissionsSchema.CLIENTS_RESOURCE_TYPE, onlyMyAdminUserPolicy, Set.of(MAP_ROLES));
|
||||
createAllPermission(client, AdminPermissionsSchema.USERS_RESOURCE_TYPE, onlyMyAdminUserPolicy, Set.of(MAP_ROLES));
|
||||
|
||||
// create a role
|
||||
RoleRepresentation role = new RoleRepresentation();
|
||||
role.setName("myRole");
|
||||
ClientRepresentation myclient = realm.admin().clients().findByClientId("myclient").get(0);
|
||||
realm.admin().clients().get(myclient.getId()).roles().create(role);
|
||||
role = realm.admin().clients().get(myclient.getId()).roles().get("myRole").toRepresentation();
|
||||
|
||||
// should pass
|
||||
realmAdminClient.realm(realm.getName()).users().get(myadmin.getId()).roles().clientLevel(myclient.getId()).add(List.of(role));
|
||||
|
||||
// should fail as it is admin role and myadmin does not have master realm admin role assigned
|
||||
try {
|
||||
realmAdminClient.realm(realm.getName()).users().get(myadmin.getId()).roles().clientLevel(realmManagement.getId())
|
||||
.add(List.of(createClientRole));
|
||||
fail("Expected exception wasn't thrown.");
|
||||
} catch (Exception ex) {
|
||||
assertThat(ex, instanceOf(ForbiddenException.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user