ui for permission reference
This commit is contained in:
parent
a41d282e92
commit
536a57a514
22 changed files with 456 additions and 72 deletions
|
@ -31,6 +31,7 @@ import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
@ -41,6 +42,7 @@ import org.keycloak.protocol.ClientInstallationProvider;
|
||||||
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ManagementPermissionReference;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
|
@ -52,6 +54,8 @@ import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.ResourceAdminManager;
|
import org.keycloak.services.managers.ResourceAdminManager;
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||||
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
|
||||||
|
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
|
||||||
import org.keycloak.services.validation.ClientValidator;
|
import org.keycloak.services.validation.ClientValidator;
|
||||||
import org.keycloak.services.validation.PairwiseClientValidator;
|
import org.keycloak.services.validation.PairwiseClientValidator;
|
||||||
import org.keycloak.services.validation.ValidationMessages;
|
import org.keycloak.services.validation.ValidationMessages;
|
||||||
|
@ -536,4 +540,55 @@ public class ClientResource {
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return object stating whether client Authorization permissions have been initialized or not and a reference
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Path("management/permissions")
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
|
public ManagementPermissionReference getManagementPermissions() {
|
||||||
|
auth.roles().requireView(client);
|
||||||
|
|
||||||
|
AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
|
||||||
|
if (!permissions.clients().isPermissionsEnabled(client)) {
|
||||||
|
return new ManagementPermissionReference();
|
||||||
|
}
|
||||||
|
return toMgmtRef(client, permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ManagementPermissionReference toMgmtRef(ClientModel client, AdminPermissionManagement permissions) {
|
||||||
|
ManagementPermissionReference ref = new ManagementPermissionReference();
|
||||||
|
ref.setEnabled(true);
|
||||||
|
ref.setResource(permissions.clients().resource(client).getId());
|
||||||
|
ref.setScopePermissions(permissions.clients().getPermissions(client));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return object stating whether client Authorization permissions have been initialized or not and a reference
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return initialized manage permissions reference
|
||||||
|
*/
|
||||||
|
@Path("management/permissions")
|
||||||
|
@PUT
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
|
public ManagementPermissionReference setManagementPermissionsEnabled(ManagementPermissionReference ref) {
|
||||||
|
auth.clients().requireManage(client);
|
||||||
|
if (ref.isEnabled()) {
|
||||||
|
AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
|
||||||
|
permissions.clients().setPermissionsEnabled(client, ref.isEnabled());
|
||||||
|
return toMgmtRef(client, permissions);
|
||||||
|
} else {
|
||||||
|
return new ManagementPermissionReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ public class ClientsResource {
|
||||||
ClientModel clientModel = realm.getClientById(id);
|
ClientModel clientModel = realm.getClientById(id);
|
||||||
if (clientModel == null) {
|
if (clientModel == null) {
|
||||||
// we do this to make sure somebody can't phish ids
|
// we do this to make sure somebody can't phish ids
|
||||||
if (!auth.clients().canList()) throw new NotFoundException("Could not find client");
|
if (auth.clients().canList()) throw new NotFoundException("Could not find client");
|
||||||
else throw new ForbiddenException();
|
else throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.jboss.resteasy.spi.NotFoundException;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.events.admin.OperationType;
|
import org.keycloak.events.admin.OperationType;
|
||||||
import org.keycloak.events.admin.ResourceType;
|
import org.keycloak.events.admin.ResourceType;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -28,6 +29,7 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.idm.GroupRepresentation;
|
import org.keycloak.representations.idm.GroupRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ManagementPermissionReference;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -50,6 +52,8 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||||
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
|
||||||
|
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @resource Groups
|
* @resource Groups
|
||||||
|
@ -214,4 +218,55 @@ public class GroupResource {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return object stating whether client Authorization permissions have been initialized or not and a reference
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Path("management/permissions")
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
|
public ManagementPermissionReference getManagementPermissions() {
|
||||||
|
auth.groups().requireView(group);
|
||||||
|
|
||||||
|
AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
|
||||||
|
if (!permissions.groups().isPermissionsEnabled(group)) {
|
||||||
|
return new ManagementPermissionReference();
|
||||||
|
}
|
||||||
|
return toMgmtRef(group, permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ManagementPermissionReference toMgmtRef(GroupModel group, AdminPermissionManagement permissions) {
|
||||||
|
ManagementPermissionReference ref = new ManagementPermissionReference();
|
||||||
|
ref.setEnabled(true);
|
||||||
|
ref.setResource(permissions.groups().resource(group).getId());
|
||||||
|
ref.setScopePermissions(permissions.groups().getPermissions(group));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return object stating whether client Authorization permissions have been initialized or not and a reference
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return initialized manage permissions reference
|
||||||
|
*/
|
||||||
|
@Path("management/permissions")
|
||||||
|
@PUT
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
|
public ManagementPermissionReference setManagementPermissionsEnabled(ManagementPermissionReference ref) {
|
||||||
|
auth.groups().requireManage(group);
|
||||||
|
if (ref.isEnabled()) {
|
||||||
|
AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
|
||||||
|
permissions.groups().setPermissionsEnabled(group, ref.isEnabled());
|
||||||
|
return toMgmtRef(group, permissions);
|
||||||
|
} else {
|
||||||
|
return new ManagementPermissionReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,38 @@
|
||||||
package org.keycloak.services.resources.admin.permissions;
|
package org.keycloak.services.resources.admin.permissions;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface ClientPermissionManagement {
|
public interface ClientPermissionManagement {
|
||||||
public static final String MAP_ROLES_SCOPE = "map-roles";
|
public static final String MAP_ROLES_SCOPE = "map-roles";
|
||||||
|
public static final String MAP_ROLES_CLIENT_SCOPE = "map-roles-client-scope";
|
||||||
|
public static final String MAP_ROLES_COMPOSITE_SCOPE = "map-roles-composite";
|
||||||
|
|
||||||
boolean isPermissionsEnabled(ClientModel client);
|
boolean isPermissionsEnabled(ClientModel client);
|
||||||
|
|
||||||
void setPermissionsEnabled(ClientModel client, boolean enable);
|
void setPermissionsEnabled(ClientModel client, boolean enable);
|
||||||
|
|
||||||
|
Resource resource(ClientModel client);
|
||||||
|
|
||||||
|
Map<String, String> getPermissions(ClientModel client);
|
||||||
|
|
||||||
Policy mapRolesPermission(ClientModel client);
|
Policy mapRolesPermission(ClientModel client);
|
||||||
|
|
||||||
|
Policy mapRolesClientScopePermission(ClientModel client);
|
||||||
|
|
||||||
|
Policy mapRolesCompositePermission(ClientModel client);
|
||||||
|
|
||||||
|
Policy managePermission(ClientModel client);
|
||||||
|
|
||||||
|
Policy viewPermission(ClientModel client);
|
||||||
|
|
||||||
ResourceServer resourceServer(ClientModel client);
|
ResourceServer resourceServer(ClientModel client);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,9 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.services.ForbiddenException;
|
import org.keycloak.services.ForbiddenException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,11 +69,11 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
private String getMapRolesPermissionName(ClientModel client) {
|
private String getMapRolesPermissionName(ClientModel client) {
|
||||||
return MAP_ROLES_SCOPE + ".permission.client." + client.getId();
|
return MAP_ROLES_SCOPE + ".permission.client." + client.getId();
|
||||||
}
|
}
|
||||||
private String getMapRoleClientScopePermissionName(ClientModel client) {
|
private String getMapRolesClientScopePermissionName(ClientModel client) {
|
||||||
return RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE + ".permission.client." + client.getId();
|
return MAP_ROLES_CLIENT_SCOPE + ".permission.client." + client.getId();
|
||||||
}
|
}
|
||||||
private String getMapRoleCompositePermissionName(ClientModel client) {
|
private String getMapRolesCompositePermissionName(ClientModel client) {
|
||||||
return RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE + ".permission.client." + client.getId();
|
return MAP_ROLES_COMPOSITE_SCOPE + ".permission.client." + client.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(ClientModel client) {
|
private void initialize(ClientModel client) {
|
||||||
|
@ -88,13 +90,13 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
if (mapRoleScope == null) {
|
if (mapRoleScope == null) {
|
||||||
mapRoleScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_SCOPE, server);
|
mapRoleScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_SCOPE, server);
|
||||||
}
|
}
|
||||||
Scope mapRoleClientScope = mapRoleClientScope(server);
|
Scope mapRoleClientScope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_CLIENT_SCOPE, server.getId());
|
||||||
if (mapRoleClientScope == null) {
|
if (mapRoleClientScope == null) {
|
||||||
mapRoleClientScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, server);
|
mapRoleClientScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_CLIENT_SCOPE, server);
|
||||||
}
|
}
|
||||||
Scope mapRoleCompositeScope = mapRoleCompositeScope(server);
|
Scope mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_COMPOSITE_SCOPE, server.getId());
|
||||||
if (mapRoleCompositeScope == null) {
|
if (mapRoleCompositeScope == null) {
|
||||||
mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, server);
|
mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_COMPOSITE_SCOPE, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
String resourceName = getResourceName(client);
|
String resourceName = getResourceName(client);
|
||||||
|
@ -129,12 +131,12 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
if (mapRolePermission == null) {
|
if (mapRolePermission == null) {
|
||||||
Helper.addEmptyScopePermission(authz, server, mapRolePermissionName, resource, mapRoleScope);
|
Helper.addEmptyScopePermission(authz, server, mapRolePermissionName, resource, mapRoleScope);
|
||||||
}
|
}
|
||||||
String mapRoleClientScopePermissionName = getMapRoleClientScopePermissionName(client);
|
String mapRoleClientScopePermissionName = getMapRolesClientScopePermissionName(client);
|
||||||
Policy mapRoleClientScopePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleClientScopePermissionName, server.getId());
|
Policy mapRoleClientScopePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleClientScopePermissionName, server.getId());
|
||||||
if (mapRoleClientScopePermission == null) {
|
if (mapRoleClientScopePermission == null) {
|
||||||
Helper.addEmptyScopePermission(authz, server, mapRoleClientScopePermissionName, resource, mapRoleClientScope);
|
Helper.addEmptyScopePermission(authz, server, mapRoleClientScopePermissionName, resource, mapRoleClientScope);
|
||||||
}
|
}
|
||||||
String mapRoleCompositePermissionName = getMapRoleCompositePermissionName(client);
|
String mapRoleCompositePermissionName = getMapRolesCompositePermissionName(client);
|
||||||
Policy mapRoleCompositePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleCompositePermissionName, server.getId());
|
Policy mapRoleCompositePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleCompositePermissionName, server.getId());
|
||||||
if (mapRoleCompositePermission == null) {
|
if (mapRoleCompositePermission == null) {
|
||||||
Helper.addEmptyScopePermission(authz, server, mapRoleCompositePermissionName, resource, mapRoleCompositeScope);
|
Helper.addEmptyScopePermission(authz, server, mapRoleCompositePermissionName, resource, mapRoleCompositeScope);
|
||||||
|
@ -155,8 +157,8 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
deletePolicy(getManagePermissionName(client), client, server);
|
deletePolicy(getManagePermissionName(client), client, server);
|
||||||
deletePolicy(getViewPermissionName(client), client, server);
|
deletePolicy(getViewPermissionName(client), client, server);
|
||||||
deletePolicy(getMapRolesPermissionName(client), client, server);
|
deletePolicy(getMapRolesPermissionName(client), client, server);
|
||||||
deletePolicy(getMapRoleClientScopePermissionName(client), client, server);
|
deletePolicy(getMapRolesClientScopePermissionName(client), client, server);
|
||||||
deletePolicy(getMapRoleCompositePermissionName(client), client, server);
|
deletePolicy(getMapRolesCompositePermissionName(client), client, server);
|
||||||
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
|
||||||
if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
|
if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
|
||||||
}
|
}
|
||||||
|
@ -190,12 +192,6 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
private Scope mapRolesScope(ResourceServer server) {
|
private Scope mapRolesScope(ResourceServer server) {
|
||||||
return authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_SCOPE, server.getId());
|
return authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_SCOPE, server.getId());
|
||||||
}
|
}
|
||||||
private Scope mapRoleClientScope(ResourceServer server) {
|
|
||||||
return authz.getStoreFactory().getScopeStore().findByName(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, server.getId());
|
|
||||||
}
|
|
||||||
private Scope mapRoleCompositeScope(ResourceServer server) {
|
|
||||||
return authz.getStoreFactory().getScopeStore().findByName(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, server.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canList() {
|
public boolean canList() {
|
||||||
|
@ -250,6 +246,27 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource resource(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
||||||
|
if (resource == null) return null;
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPermissions(ClientModel client) {
|
||||||
|
Map<String, String> scopes = new HashMap<>();
|
||||||
|
scopes.put(MAP_ROLES_SCOPE, mapRolesPermission(client).getId());
|
||||||
|
scopes.put(MAP_ROLES_CLIENT_SCOPE, mapRolesClientScopePermission(client).getId());
|
||||||
|
scopes.put(MAP_ROLES_COMPOSITE_SCOPE, mapRolesCompositePermission(client).getId());
|
||||||
|
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(client).getId());
|
||||||
|
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(client).getId());
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canManage(ClientModel client) {
|
public boolean canManage(ClientModel client) {
|
||||||
if (!root.isAdminSameRealm()) {
|
if (!root.isAdminSameRealm()) {
|
||||||
|
@ -397,6 +414,34 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesPermissionName(client), server.getId());
|
return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesPermissionName(client), server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy mapRolesClientScopePermission(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesClientScopePermissionName(client), server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy mapRolesCompositePermission(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesCompositePermissionName(client), server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy managePermission(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
return authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy viewPermission(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
return authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceServer resourceServer(ClientModel client) {
|
public ResourceServer resourceServer(ClientModel client) {
|
||||||
return authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
|
return authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
|
||||||
|
@ -410,7 +455,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
||||||
if (resource == null) return false;
|
if (resource == null) return false;
|
||||||
|
|
||||||
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRoleCompositePermissionName(client), server.getId());
|
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolesCompositePermissionName(client), server.getId());
|
||||||
if (policy == null) {
|
if (policy == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -421,7 +466,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope scope = mapRoleCompositeScope(server);
|
Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_COMPOSITE_SCOPE, server.getId());
|
||||||
return root.evaluatePermission(resource, scope, server);
|
return root.evaluatePermission(resource, scope, server);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -432,7 +477,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
||||||
if (resource == null) return false;
|
if (resource == null) return false;
|
||||||
|
|
||||||
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRoleClientScopePermissionName(client), server.getId());
|
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolesClientScopePermissionName(client), server.getId());
|
||||||
if (policy == null) {
|
if (policy == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -443,7 +488,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope scope = mapRoleClientScope(server);
|
Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_CLIENT_SCOPE, server.getId());
|
||||||
return root.evaluatePermission(resource, scope, server);
|
return root.evaluatePermission(resource, scope, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.keycloak.services.resources.admin.permissions;
|
package org.keycloak.services.resources.admin.permissions;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
|
||||||
|
@ -34,4 +35,8 @@ public interface GroupPermissionManagement {
|
||||||
Policy manageMembersPermission(GroupModel group);
|
Policy manageMembersPermission(GroupModel group);
|
||||||
Policy viewPermissionGroup(GroupModel group);
|
Policy viewPermissionGroup(GroupModel group);
|
||||||
Policy managePermissionGroup(GroupModel group);
|
Policy managePermissionGroup(GroupModel group);
|
||||||
|
|
||||||
|
Resource resource(GroupModel group);
|
||||||
|
|
||||||
|
Map<String, String> getPermissions(GroupModel group);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,16 @@ import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
import org.keycloak.authorization.model.Scope;
|
||||||
import org.keycloak.models.AdminRoles;
|
import org.keycloak.models.AdminRoles;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.services.ForbiddenException;
|
import org.keycloak.services.ForbiddenException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,16 +57,16 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getGroupResourceName(GroupModel group) {
|
private static String getGroupResourceName(GroupModel group) {
|
||||||
return "group.resource." + getGroupSuffix(group);
|
return "group.resource." + group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String getManagePermissionGroup(GroupModel group) {
|
public static String getManagePermissionGroup(GroupModel group) {
|
||||||
return "manage.permission.group." + getGroupSuffix(group);
|
return "manage.permission.group." + group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getManageMembersPermissionGroup(GroupModel group) {
|
public static String getManageMembersPermissionGroup(GroupModel group) {
|
||||||
return "manage.members.permission.group." + getGroupSuffix(group);
|
return "manage.members.permission.group." + group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getGroupSuffix(GroupModel group) {
|
public static String getGroupSuffix(GroupModel group) {
|
||||||
|
@ -71,11 +74,11 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getViewPermissionGroup(GroupModel group) {
|
public static String getViewPermissionGroup(GroupModel group) {
|
||||||
return "view.permission.group." + getGroupSuffix(group);
|
return "view.permission.group." + group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getViewMembersPermissionGroup(GroupModel group) {
|
public static String getViewMembersPermissionGroup(GroupModel group) {
|
||||||
return "view.members.permission.group." + getGroupSuffix(group);
|
return "view.members.permission.group." + group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(GroupModel group) {
|
private void initialize(GroupModel group) {
|
||||||
|
@ -102,7 +105,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
|
||||||
Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
|
Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
|
||||||
Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
|
Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
|
||||||
}
|
}
|
||||||
String viewPermissionName = getManagePermissionGroup(group);
|
String viewPermissionName = getViewPermissionGroup(group);
|
||||||
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
|
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
|
||||||
if (viewPermission == null) {
|
if (viewPermission == null) {
|
||||||
Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
|
Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
|
||||||
|
@ -213,6 +216,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
|
||||||
return authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
|
return authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource resource(GroupModel group) {
|
||||||
|
ResourceServer server = root.realmResourceServer();
|
||||||
|
if (server == null) return null;
|
||||||
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
|
||||||
|
if (resource == null) return null;
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPermissions(GroupModel group) {
|
||||||
|
Map<String, String> scopes = new HashMap<>();
|
||||||
|
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermissionGroup(group).getId());
|
||||||
|
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermissionGroup(group).getId());
|
||||||
|
scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
|
||||||
|
scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canManage(GroupModel group) {
|
public boolean canManage(GroupModel group) {
|
||||||
|
|
|
@ -141,19 +141,19 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
|
||||||
@Override
|
@Override
|
||||||
public boolean canMapRole(RoleModel role) {
|
public boolean canMapRole(RoleModel role) {
|
||||||
if (!root.isAdminSameRealm()) {
|
if (!root.isAdminSameRealm()) {
|
||||||
return root.users().canManage();
|
return root.users().canManageDefault();
|
||||||
}
|
}
|
||||||
if (role.getContainer() instanceof ClientModel) {
|
if (role.getContainer() instanceof ClientModel) {
|
||||||
if (root.clients().canMapRoles((ClientModel)role.getContainer())) return true;
|
if (root.clients().canMapRoles((ClientModel)role.getContainer())) return true;
|
||||||
}
|
}
|
||||||
if (!isPermissionsEnabled(role)){
|
if (!isPermissionsEnabled(role)){
|
||||||
return root.users().canManage();
|
return root.users().canManageDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceServer resourceServer = getResourceServer(role);
|
ResourceServer resourceServer = getResourceServer(role);
|
||||||
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), resourceServer.getId());
|
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), resourceServer.getId());
|
||||||
if (policy.getAssociatedPolicies().isEmpty()) {
|
if (policy.getAssociatedPolicies().isEmpty()) {
|
||||||
return root.users().canManage(); // if no policies applied, just do default
|
return root.users().canManageDefault(); // if no policies applied, just do default
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource roleResource = resource(role);
|
Resource roleResource = resource(role);
|
||||||
|
|
|
@ -175,7 +175,11 @@ public abstract class AbstractKeycloakTest {
|
||||||
|
|
||||||
// Cleanup objects
|
// Cleanup objects
|
||||||
for (TestCleanup cleanup : testContext.getCleanups().values()) {
|
for (TestCleanup cleanup : testContext.getCleanups().values()) {
|
||||||
if (cleanup != null) cleanup.executeCleanup();
|
try {
|
||||||
|
if (cleanup != null) cleanup.executeCleanup();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
testContext.getCleanups().clear();
|
testContext.getCleanups().clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testUI() throws Exception {
|
public void testUI() throws Exception {
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
|
testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
|
testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
|
||||||
|
@ -308,7 +308,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
realmRoleSet.add(realmRole);
|
realmRoleSet.add(realmRole);
|
||||||
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
|
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
|
||||||
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
|
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
|
||||||
realmRole2Set.add(realmRole);
|
realmRole2Set.add(realmRole2);
|
||||||
ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId("role-namespace").get(0);
|
ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId("role-namespace").get(0);
|
||||||
RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
|
RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
|
||||||
List<RoleRepresentation> clientRoleSet = new LinkedList<>();
|
List<RoleRepresentation> clientRoleSet = new LinkedList<>();
|
||||||
|
@ -395,18 +395,18 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
TEST, "groupManager", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
|
TEST, "groupManager", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
|
||||||
List<RoleRepresentation> roles = null;
|
List<RoleRepresentation> roles = null;
|
||||||
realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
|
realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
|
||||||
roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
|
roles = realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).listAll();
|
||||||
Assert.assertTrue(roles.stream().anyMatch((r) -> {
|
Assert.assertTrue(roles.stream().anyMatch((r) -> {
|
||||||
return r.getName().equals("client-role");
|
return r.getName().equals("client-role");
|
||||||
}));
|
}));
|
||||||
realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).remove(clientRoleSet);
|
realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).remove(clientRoleSet);
|
||||||
|
|
||||||
roles = realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().listAvailable();
|
roles = realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().listAvailable();
|
||||||
Assert.assertEquals(roles.size(), 1);
|
Assert.assertEquals(roles.size(), 1);
|
||||||
realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRoleSet);
|
realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().add(realmRoleSet);
|
||||||
realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().remove(realmRoleSet);
|
realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().remove(realmRoleSet);
|
||||||
try {
|
try {
|
||||||
realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRole2Set);
|
realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().add(realmRole2Set);
|
||||||
Assert.fail("should fail with forbidden exception");
|
Assert.fail("should fail with forbidden exception");
|
||||||
} catch (ClientErrorException e) {
|
} catch (ClientErrorException e) {
|
||||||
Assert.assertEquals(e.getResponse().getStatus(), 403);
|
Assert.assertEquals(e.getResponse().getStatus(), 403);
|
||||||
|
@ -428,6 +428,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
|
Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
|
||||||
TEST, "clientMapper", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
|
TEST, "clientMapper", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
|
||||||
List<RoleRepresentation> roles = null;
|
List<RoleRepresentation> roles = null;
|
||||||
|
roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
|
||||||
|
Assert.assertTrue(roles.isEmpty());
|
||||||
realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
|
realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
|
||||||
roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
|
roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
|
||||||
Assert.assertTrue(roles.stream().anyMatch((r) -> {
|
Assert.assertTrue(roles.stream().anyMatch((r) -> {
|
||||||
|
@ -455,9 +457,6 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
|
testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
|
||||||
|
|
||||||
UserRepresentation user1 = adminClient.realm(TEST).users().search("user1").get(0);
|
UserRepresentation user1 = adminClient.realm(TEST).users().search("user1").get(0);
|
||||||
UserRepresentation user2 = adminClient.realm(TEST).users().search("user2").get(0);
|
|
||||||
UserRepresentation user3 = adminClient.realm(TEST).users().search("user3").get(0);
|
|
||||||
UserRepresentation user4 = adminClient.realm(TEST).users().search("user4").get(0);
|
|
||||||
RoleRepresentation realmRole = adminClient.realm(TEST).roles().get("realm-role").toRepresentation();
|
RoleRepresentation realmRole = adminClient.realm(TEST).roles().get("realm-role").toRepresentation();
|
||||||
List<RoleRepresentation> realmRoleSet = new LinkedList<>();
|
List<RoleRepresentation> realmRoleSet = new LinkedList<>();
|
||||||
realmRoleSet.add(realmRole);
|
realmRoleSet.add(realmRole);
|
||||||
|
|
|
@ -1306,7 +1306,8 @@ credential-reset-actions-timeout.tooltip=Maximum time before the action permit e
|
||||||
ldap-mappers=LDAP Mappers
|
ldap-mappers=LDAP Mappers
|
||||||
create-ldap-mapper=Create LDAP mapper
|
create-ldap-mapper=Create LDAP mapper
|
||||||
map-role-mgmt-scope-description=Policies that decide if an admin can map this role to a user or group
|
map-role-mgmt-scope-description=Policies that decide if an admin can map this role to a user or group
|
||||||
manage-mgmt-scope-description=Policies that decide if an admin can manage this resource or resources
|
manage-authz-users-scope-description=Policies that decide if an admin can manage all users in the realm
|
||||||
|
view-authz-users-scope-description=Policies that decide if an admin can view all users in realm
|
||||||
permissions-enabled-role=Permissions Enabled
|
permissions-enabled-role=Permissions Enabled
|
||||||
permissions-enabled-role.tooltip=Whether or not to enable fine grain permissions for managing this role. Disabling will delete all current permissions that have been set up.
|
permissions-enabled-role.tooltip=Whether or not to enable fine grain permissions for managing this role. Disabling will delete all current permissions that have been set up.
|
||||||
manage-permissions-role.tooltip=Fine grain permissions for managing roles. For example, you can define different policies for who is allowed to map a role.
|
manage-permissions-role.tooltip=Fine grain permissions for managing roles. For example, you can define different policies for who is allowed to map a role.
|
||||||
|
@ -1314,6 +1315,20 @@ lookup=Lookup
|
||||||
manage-permissions-users.tooltip=Fine grain permssions for managing all users in realm. You can define different policies for who is allowed to manage users in the realm.
|
manage-permissions-users.tooltip=Fine grain permssions for managing all users in realm. You can define different policies for who is allowed to manage users in the realm.
|
||||||
permissions-enabled-users=Permissions Enabled
|
permissions-enabled-users=Permissions Enabled
|
||||||
permissions-enabled-users.tooltip=Whether or not to enable fine grain permissions for managing users. Disabling will delete all current permissions that have been set up.
|
permissions-enabled-users.tooltip=Whether or not to enable fine grain permissions for managing users. Disabling will delete all current permissions that have been set up.
|
||||||
|
manage-permissions-client.tooltip=Fine grain permssions for admins that want to manage this client or apply roles defined by this client.
|
||||||
|
manage-permissions-group.tooltip=Fine grain permssions for admins that want to manage this group or the members of this group.
|
||||||
|
manage-authz-group-scope-description=Policies that decide if an admin can manage this group
|
||||||
|
view-authz-group-scope-description=Policies that decide if an admin can view this group
|
||||||
|
view.members-authz-group-scope-description=Policies that decide if an admin can manage the members of this group
|
||||||
|
manage.members-authz-group-scope-description=Policies that decide if an admin can view the members of this group
|
||||||
|
manage-authz-client-scope-description=Policies that decide if an admin can manage this client
|
||||||
|
view-authz-client-scope-description=Policies that decide if an admin can view this client
|
||||||
|
map-roles-authz-client-scope-description=Policies that decide if an admin can map roles defined by this client
|
||||||
|
map-roles-client-scope-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client to the client scope of another client
|
||||||
|
map-roles-composite-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client as a composite to another role
|
||||||
|
map-role-authz-role-scope-description=Policies that decide if an admin can map role this role to a user or group
|
||||||
|
map-role-client-scope-authz-role-scope-description=Policies that decide if an admin can apply this role to the client scope of a client
|
||||||
|
map-role-composite-authz-role-scope-description=Policies that decide if an admin can apply this role as a composite to another role
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -424,6 +424,30 @@ module.config(['$routeProvider', function ($routeProvider) {
|
||||||
},
|
},
|
||||||
controller : 'UsersPermissionsCtrl'
|
controller : 'UsersPermissionsCtrl'
|
||||||
})
|
})
|
||||||
|
.when('/realms/:realm/clients/:client/permissions', {
|
||||||
|
templateUrl : resourceUrl + '/partials/authz/mgmt/client-permissions.html',
|
||||||
|
resolve : {
|
||||||
|
realm : function(RealmLoader) {
|
||||||
|
return RealmLoader();
|
||||||
|
},
|
||||||
|
client : function(ClientLoader) {
|
||||||
|
return ClientLoader();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controller : 'ClientPermissionsCtrl'
|
||||||
|
})
|
||||||
|
.when('/realms/:realm/groups/:group/permissions', {
|
||||||
|
templateUrl : resourceUrl + '/partials/authz/mgmt/group-permissions.html',
|
||||||
|
resolve : {
|
||||||
|
realm : function(RealmLoader) {
|
||||||
|
return RealmLoader();
|
||||||
|
},
|
||||||
|
group : function(GroupLoader) {
|
||||||
|
return GroupLoader();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controller : 'GroupPermissionsCtrl'
|
||||||
|
})
|
||||||
;
|
;
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
|
@ -2419,3 +2419,35 @@ module.controller('UsersPermissionsCtrl', function($scope, $http, $route, $locat
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.controller('ClientPermissionsCtrl', function($scope, $http, $route, $location, realm, client, ClientManagementPermissions, Notifications) {
|
||||||
|
$scope.client = client;
|
||||||
|
$scope.realm = realm;
|
||||||
|
ClientManagementPermissions.get({realm: realm.realm, client: client.id}, function(data) {
|
||||||
|
$scope.permissions = data;
|
||||||
|
});
|
||||||
|
$scope.setEnabled = function() {
|
||||||
|
var param = { enabled: $scope.permissions.enabled};
|
||||||
|
$scope.permissions = ClientManagementPermissions.update({realm: realm.realm, client: client.id}, param);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.controller('GroupPermissionsCtrl', function($scope, $http, $route, $location, realm, group, GroupManagementPermissions, Client, Notifications) {
|
||||||
|
$scope.group = group;
|
||||||
|
$scope.realm = realm;
|
||||||
|
Client.query({realm: realm.realm, clientId: getManageClientId(realm)}, function(data) {
|
||||||
|
$scope.realmManagementClientId = data[0].id;
|
||||||
|
});
|
||||||
|
GroupManagementPermissions.get({realm: realm.realm, group: group.id}, function(data) {
|
||||||
|
$scope.permissions = data;
|
||||||
|
});
|
||||||
|
$scope.setEnabled = function() {
|
||||||
|
var param = { enabled: $scope.permissions.enabled};
|
||||||
|
$scope.permissions = GroupManagementPermissions.update({realm: realm.realm, group: group.id}, param);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -144,4 +144,50 @@ module.service('AuthzDialog', function($modal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.factory('RoleManagementPermissions', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/management/permissions', {
|
||||||
|
realm : '@realm',
|
||||||
|
role : '@role'
|
||||||
|
}, {
|
||||||
|
update: {
|
||||||
|
method: 'PUT'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.factory('UsersManagementPermissions', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/users-management-permissions', {
|
||||||
|
realm : '@realm'
|
||||||
|
}, {
|
||||||
|
update: {
|
||||||
|
method: 'PUT'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.factory('ClientManagementPermissions', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/clients/:client/management/permissions', {
|
||||||
|
realm : '@realm',
|
||||||
|
client : '@client'
|
||||||
|
}, {
|
||||||
|
update: {
|
||||||
|
method: 'PUT'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.factory('GroupManagementPermissions', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/groups/:group/management/permissions', {
|
||||||
|
realm : '@realm',
|
||||||
|
group : '@group'
|
||||||
|
}, {
|
||||||
|
update: {
|
||||||
|
method: 'PUT'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -842,28 +842,6 @@ module.factory('Role', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('RoleManagementPermissions', function($resource) {
|
|
||||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/management/permissions', {
|
|
||||||
realm : '@realm',
|
|
||||||
role : '@role'
|
|
||||||
}, {
|
|
||||||
update: {
|
|
||||||
method: 'PUT'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.factory('UsersManagementPermissions', function($resource) {
|
|
||||||
return $resource(authUrl + '/admin/realms/:realm/users-management-permissions', {
|
|
||||||
realm : '@realm'
|
|
||||||
}, {
|
|
||||||
update: {
|
|
||||||
method: 'PUT'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
module.factory('RoleById', function($resource) {
|
module.factory('RoleById', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role', {
|
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
|
||||||
|
<li>{{client.clientId}}</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<kc-tabs-client></kc-tabs-client>
|
||||||
|
|
||||||
|
<form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
|
||||||
|
<fieldset class="border-top">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input ng-model="permissions.enabled" ng-click="setEnabled()" name="permissionsEnabled" id="permissionsEnabled" ng-disabled="!access.manageAuthorization" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'permissions-enabled-role.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<table class="datatable table table-striped table-bordered dataTable no-footer" data-ng-show="permissions.enabled">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{:: 'scope-name' | translate}}</th>
|
||||||
|
<th>{{:: 'description' | translate}}</th>
|
||||||
|
<th colspan="2">{{:: 'actions' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
|
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
|
<td translate="{{scopeName}}-authz-client-scope-description"></td>
|
||||||
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<kc-menu></kc-menu>
|
|
@ -2,7 +2,6 @@
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">{{:: 'roles' | translate}}</a></li>
|
|
||||||
<li>{{role.name}}</li>
|
<li>{{role.name}}</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
<td translate="{{scopeName}}-mgmt-scope-description"></td>
|
<td translate="{{scopeName}}-authz-role-scope-description"></td>
|
||||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#/realms/{{realm.realm}}/groups">{{:: 'groups' | translate}}</a></li>
|
||||||
|
<li>{{group.name}}</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<kc-tabs-group></kc-tabs-group>
|
||||||
|
|
||||||
|
<form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
|
||||||
|
<fieldset class="border-top">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input ng-model="permissions.enabled" ng-click="setEnabled()" name="permissionsEnabled" id="permissionsEnabled" ng-disabled="!access.manageAuthorization" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'permissions-enabled-role.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<table class="datatable table table-striped table-bordered dataTable no-footer" data-ng-show="permissions.enabled">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{:: 'scope-name' | translate}}</th>
|
||||||
|
<th>{{:: 'description' | translate}}</th>
|
||||||
|
<th colspan="2">{{:: 'actions' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
|
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
|
<td translate="{{scopeName}}-authz-group-scope-description"></td>
|
||||||
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<kc-menu></kc-menu>
|
|
@ -28,7 +28,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
<td translate="{{scopeName}}-mgmt-scope-description"></td>
|
<td translate="{{scopeName}}-authz-role-scope-description"></td>
|
||||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
<td translate="{{scopeName}}-mgmt-scope-description"></td>
|
<td translate="{{scopeName}}-authz-users-scope-description"></td>
|
||||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -43,5 +43,9 @@
|
||||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/service-account-roles">{{:: 'service-account-roles' | translate}}</a>
|
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/service-account-roles">{{:: 'service-account-roles' | translate}}</a>
|
||||||
<kc-tooltip>{{:: 'service-account-roles.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'service-account-roles.tooltip' | translate}}</kc-tooltip>
|
||||||
</li>
|
</li>
|
||||||
|
<li ng-class="{active: path[4] == 'permissions'}">
|
||||||
|
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
||||||
|
<kc-tooltip>{{:: 'manage-permissions-client.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
|
@ -9,5 +9,9 @@
|
||||||
<li ng-class="{active: path[4] == 'attributes'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/attributes">{{:: 'attributes' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'attributes'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/attributes">{{:: 'attributes' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'members'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/members">{{:: 'members' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'members'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/members">{{:: 'members' | translate}}</a></li>
|
||||||
|
<li ng-class="{active: path[4] == 'permissions'}">
|
||||||
|
<a href="#/realms/{{realm.realm}}/groups/{{group.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
||||||
|
<kc-tooltip>{{:: 'manage-permissions-group.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
Loading…
Reference in a new issue