remove scope

This commit is contained in:
Bill Burke 2017-06-16 11:26:43 -04:00
parent 94528976d4
commit a994af9010
33 changed files with 612 additions and 188 deletions

View file

@ -31,12 +31,15 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil; import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
import org.keycloak.representations.JsonWebToken; import org.keycloak.representations.JsonWebToken;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.clientregistration.policy.RegistrationAuth; import org.keycloak.services.clientregistration.policy.RegistrationAuth;
import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyException; import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyException;
import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyManager; import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.util.TokenUtil; import org.keycloak.util.TokenUtil;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
@ -231,44 +234,72 @@ public class ClientRegistrationAuth {
return initialAccessModel; return initialAccessModel;
} }
private boolean hasRole(String... role) { private boolean hasRole(String... roles) {
try { try {
Map<String, Object> otherClaims = jwt.getOtherClaims(); if (jwt.getIssuedFor().equals(Constants.ADMIN_CLI_CLIENT_ID)
if (otherClaims != null) { || jwt.getIssuedFor().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
Map<String, Map<String, List<String>>> resourceAccess = (Map<String, Map<String, List<String>>>) jwt.getOtherClaims().get("resource_access"); return hasRoleInModel(roles);
if (resourceAccess == null) {
return false;
}
List<String> roles = null; } else {
return hasRoleInToken(roles);
Map<String, List<String>> map;
if (realm.getName().equals(Config.getAdminRealm())) {
map = resourceAccess.get(realm.getMasterAdminClient().getClientId());
} else {
map = resourceAccess.get(Constants.REALM_MANAGEMENT_CLIENT_ID);
}
if (map != null) {
roles = map.get("roles");
}
if (roles == null) {
return false;
}
for (String r : role) {
if (roles.contains(r)) {
return true;
}
}
} }
return false;
} catch (Throwable t) { } catch (Throwable t) {
return false; return false;
} }
} }
private boolean hasRoleInModel(String[] roles) {
ClientModel roleNamespace;
UserModel user = session.users().getUserById(jwt.getSubject(), realm);
if (user == null) {
return false;
}
if (realm.getName().equals(Config.getAdminRealm())) {
roleNamespace = realm.getMasterAdminClient();
} else {
roleNamespace = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
}
for (String role : roles) {
RoleModel roleModel = roleNamespace.getRole(role);
if (user.hasRole(roleModel)) return true;
}
return false;
}
private boolean hasRoleInToken(String[] role) {
Map<String, Object> otherClaims = jwt.getOtherClaims();
if (otherClaims != null) {
Map<String, Map<String, List<String>>> resourceAccess = (Map<String, Map<String, List<String>>>) jwt.getOtherClaims().get("resource_access");
if (resourceAccess == null) {
return false;
}
List<String> roles = null;
Map<String, List<String>> map;
if (realm.getName().equals(Config.getAdminRealm())) {
map = resourceAccess.get(realm.getMasterAdminClient().getClientId());
} else {
map = resourceAccess.get(Constants.REALM_MANAGEMENT_CLIENT_ID);
}
if (map != null) {
roles = map.get("roles");
}
if (roles == null) {
return false;
}
for (String r : role) {
if (roles.contains(r)) {
return true;
}
}
}
return false;
}
private boolean authenticateClient(ClientModel client) { private boolean authenticateClient(ClientModel client) {
if (client == null) { if (client == null) {
return false; return false;

View file

@ -159,7 +159,6 @@ public class RealmManager {
ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId); ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN); adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
} }
adminConsole.addScopeMapping(adminRole);
} }
protected void setupAdminConsoleLocaleMapper(RealmModel realm) { protected void setupAdminConsoleLocaleMapper(RealmModel realm) {
@ -194,7 +193,6 @@ public class RealmManager {
ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId); ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN); adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
} }
adminCli.addScopeMapping(adminRole);
} }
} }

View file

@ -834,7 +834,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @NoCache
public List<RequiredActionProviderRepresentation> getRequiredActions() { public List<RequiredActionProviderRepresentation> getRequiredActions() {
auth.realm().requireViewRealm(); auth.requireAnyAdminRole();
List<RequiredActionProviderRepresentation> list = new LinkedList<>(); List<RequiredActionProviderRepresentation> list = new LinkedList<>();
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) { for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {

View file

@ -140,7 +140,7 @@ public class ClientRoleMappingsResource {
Set<RoleModel> available = client.getRoles(); Set<RoleModel> available = client.getRoles();
available = available.stream().filter(r -> available = available.stream().filter(r ->
canMapRole(r) auth.roles().canMapRole(r)
).collect(Collectors.toSet()); ).collect(Collectors.toSet());
return getAvailableRoles(user, available); return getAvailableRoles(user, available);
} }
@ -174,23 +174,13 @@ public class ClientRoleMappingsResource {
if (roleModel == null || !roleModel.getId().equals(role.getId())) { if (roleModel == null || !roleModel.getId().equals(role.getId())) {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
user.grantRole(roleModel); user.grantRole(roleModel);
} }
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success(); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
} }
private void checkMapRolePermission(RoleModel roleModel) {
if (!canMapRole(roleModel)) {
throw new ForbiddenException();
}
}
private boolean canMapRole(RoleModel roleModel) {
return auth.roles().canMapRole(roleModel);
}
/** /**
* Delete client-level roles from user role mapping * Delete client-level roles from user role mapping
* *
@ -210,7 +200,7 @@ public class ClientRoleMappingsResource {
ClientModel client = (ClientModel) roleModel.getContainer(); ClientModel client = (ClientModel) roleModel.getContainer();
if (!client.getId().equals(this.client.getId())) continue; if (!client.getId().equals(this.client.getId())) continue;
} }
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
user.deleteRoleMapping(roleModel); user.deleteRoleMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel)); roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
@ -222,7 +212,7 @@ public class ClientRoleMappingsResource {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
try { try {
user.deleteRoleMapping(roleModel); user.deleteRoleMapping(roleModel);
} catch (ModelException me) { } catch (ModelException me) {

View file

@ -76,13 +76,20 @@ public class ClientTemplatesResource {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @NoCache
public List<ClientTemplateRepresentation> getClientTemplates() { public List<ClientTemplateRepresentation> getClientTemplates() {
auth.clients().requireView(); auth.clients().requireListTemplates();
List<ClientTemplateRepresentation> rep = new ArrayList<>(); List<ClientTemplateRepresentation> rep = new ArrayList<>();
List<ClientTemplateModel> clientModels = realm.getClientTemplates(); List<ClientTemplateModel> clientModels = realm.getClientTemplates();
boolean viewable = auth.clients().canViewTemplates();
for (ClientTemplateModel clientModel : clientModels) { for (ClientTemplateModel clientModel : clientModels) {
rep.add(ModelToRepresentation.toRepresentation(clientModel)); if (viewable) rep.add(ModelToRepresentation.toRepresentation(clientModel));
else {
ClientTemplateRepresentation tempRep = new ClientTemplateRepresentation();
tempRep.setName(clientModel.getName());
tempRep.setId(clientModel.getId());
tempRep.setProtocol(clientModel.getProtocol());
}
} }
return rep; return rep;
} }

View file

@ -96,18 +96,11 @@ public class RealmsAdminResource {
@NoCache @NoCache
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public List<RealmRepresentation> getRealms() { public List<RealmRepresentation> getRealms() {
RealmManager realmManager = new RealmManager(session);
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>(); List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) { List<RealmModel> realms = session.realms().getRealms();
List<RealmModel> realms = session.realms().getRealms(); for (RealmModel realm : realms) {
for (RealmModel realm : realms) { addRealmRep(reps, realm);
addRealmRep(reps, realm, realm.getMasterAdminClient());
}
} else {
ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
addRealmRep(reps, auth.getRealm(), adminApp);
} }
if (reps.isEmpty()) { if (reps.isEmpty()) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
@ -116,10 +109,10 @@ public class RealmsAdminResource {
return reps; return reps;
} }
protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ClientModel realmManagementClient) { protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm) {
if (auth.hasAppRole(realmManagementClient, AdminRoles.VIEW_REALM)) { if (AdminPermissions.realms(session, auth).canView(realm)) {
reps.add(ModelToRepresentation.toRepresentation(realm, false)); reps.add(ModelToRepresentation.toRepresentation(realm, false));
} else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) { } else if (AdminPermissions.realms(session, auth).isAdmin(realm)) {
RealmRepresentation rep = new RealmRepresentation(); RealmRepresentation rep = new RealmRepresentation();
rep.setRealm(realm.getName()); rep.setRealm(realm.getName());
reps.add(rep); reps.add(rep);
@ -140,12 +133,7 @@ public class RealmsAdminResource {
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) { public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
RealmManager realmManager = new RealmManager(session); RealmManager realmManager = new RealmManager(session);
realmManager.setContextPath(keycloak.getContextPath()); realmManager.setContextPath(keycloak.getContextPath());
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) { AdminPermissions.realms(session, auth).requireCreateRealm();
throw new ForbiddenException();
}
if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
throw new ForbiddenException();
}
logger.debugv("importRealm: {0}", rep.getRealm()); logger.debugv("importRealm: {0}", rep.getRealm());

View file

@ -232,7 +232,7 @@ public class RoleMapperResource {
if (roleModel == null || !roleModel.getId().equals(role.getId())) { if (roleModel == null || !roleModel.getId().equals(role.getId())) {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
roleMapper.grantRole(roleModel); roleMapper.grantRole(roleModel);
} }
@ -256,7 +256,7 @@ public class RoleMapperResource {
roles = new LinkedList<>(); roles = new LinkedList<>();
for (RoleModel roleModel : roleModels) { for (RoleModel roleModel : roleModels) {
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
roleMapper.deleteRoleMapping(roleModel); roleMapper.deleteRoleMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel)); roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
@ -267,7 +267,7 @@ public class RoleMapperResource {
if (roleModel == null || !roleModel.getId().equals(role.getId())) { if (roleModel == null || !roleModel.getId().equals(role.getId())) {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
checkMapRolePermission(roleModel); auth.roles().requireMapRole(roleModel);
try { try {
roleMapper.deleteRoleMapping(roleModel); roleMapper.deleteRoleMapping(roleModel);
} catch (ModelException me) { } catch (ModelException me) {
@ -283,12 +283,6 @@ public class RoleMapperResource {
} }
private void checkMapRolePermission(RoleModel roleModel) {
if (!canMapRole(roleModel)) {
throw new ForbiddenException();
}
}
private boolean canMapRole(RoleModel roleModel) { private boolean canMapRole(RoleModel roleModel) {
return auth.roles().canMapRole(roleModel); return auth.roles().canMapRole(roleModel);
} }

View file

@ -67,7 +67,7 @@ public abstract class RoleResource {
if (composite == null) { if (composite == null) {
throw new NotFoundException("Could not find composite role"); throw new NotFoundException("Could not find composite role");
} }
auth.roles().requireManage(composite); auth.roles().requireMapComposite(composite);
role.addCompositeRole(composite); role.addCompositeRole(composite);
} }

View file

@ -534,7 +534,7 @@ public class UserResource {
@Path("role-mappings") @Path("role-mappings")
public RoleMapperResource getRoleMappings() { public RoleMapperResource getRoleMappings() {
AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.users().requireManage(user); AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.users().requireMapRoles(user);
AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.users().requireView(user); AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.users().requireView(user);
RoleMapperResource resource = new RoleMapperResource(realm, auth, user, adminEvent, manageCheck, viewCheck); RoleMapperResource resource = new RoleMapperResource(realm, auth, user, adminEvent, manageCheck, viewCheck);
ResteasyProviderFactory.getInstance().injectProperties(resource); ResteasyProviderFactory.getInstance().injectProperties(resource);
@ -756,13 +756,13 @@ public class UserResource {
@Path("groups/{groupId}") @Path("groups/{groupId}")
@NoCache @NoCache
public void removeMembership(@PathParam("groupId") String groupId) { public void removeMembership(@PathParam("groupId") String groupId) {
auth.users().requireManage(user); auth.users().requireManageGroupMembership(user);
GroupModel group = session.realms().getGroupById(groupId, realm); GroupModel group = session.realms().getGroupById(groupId, realm);
if (group == null) { if (group == null) {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
auth.groups().requireManageMembers(group); auth.groups().requireManageMembership(group);
try { try {
if (user.isMemberOf(group)){ if (user.isMemberOf(group)){
@ -780,12 +780,12 @@ public class UserResource {
@Path("groups/{groupId}") @Path("groups/{groupId}")
@NoCache @NoCache
public void joinGroup(@PathParam("groupId") String groupId) { public void joinGroup(@PathParam("groupId") String groupId) {
auth.users().requireManage(user); auth.users().requireManageGroupMembership(user);
GroupModel group = session.realms().getGroupById(groupId, realm); GroupModel group = session.realms().getGroupById(groupId, realm);
if (group == null) { if (group == null) {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
//auth.groups().requireManageMembers(group); auth.groups().requireManageMembership(group);
if (!user.isMemberOf(group)){ if (!user.isMemberOf(group)){
user.joinGroup(group); user.joinGroup(group);
adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();

View file

@ -25,6 +25,8 @@ import org.keycloak.services.resources.admin.AdminAuth;
public interface AdminPermissionEvaluator { public interface AdminPermissionEvaluator {
RealmPermissionEvaluator realm(); RealmPermissionEvaluator realm();
void requireAnyAdminRole();
AdminAuth adminAuth(); AdminAuth adminAuth();
RolePermissionEvaluator roles(); RolePermissionEvaluator roles();

View file

@ -35,6 +35,10 @@ public class AdminPermissions {
return new MgmtPermissions(session, realm, adminsRealm, admin); return new MgmtPermissions(session, realm, adminsRealm, admin);
} }
public static RealmsPermissionEvaluator realms(KeycloakSession session, AdminAuth auth) {
return new MgmtPermissions(session, auth);
}
public static AdminPermissionManagement management(KeycloakSession session, RealmModel realm) { public static AdminPermissionManagement management(KeycloakSession session, RealmModel realm) {
return new MgmtPermissions(session, realm); return new MgmtPermissions(session, realm);
} }

View file

@ -115,16 +115,12 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
String managePermissionName = getManagePermissionName(client); String managePermissionName = getManagePermissionName(client);
Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId()); Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
if (managePermission == null) { if (managePermission == null) {
RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS); Helper.addEmptyScopePermission(authz, server, managePermissionName, resource, manageScope);
Policy manageClientsPolicy = root.roles().rolePolicy(server, role);
Helper.addScopePermission(authz, server, managePermissionName, resource, manageScope, manageClientsPolicy);
} }
String viewPermissionName = getViewPermissionName(client); String viewPermissionName = getViewPermissionName(client);
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId()); Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
if (viewPermission == null) { if (viewPermission == null) {
RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.VIEW_CLIENTS); Helper.addEmptyScopePermission(authz, server, viewPermissionName, resource, viewScope);
Policy viewClientsPolicy = root.roles().rolePolicy(server, role);
Helper.addScopePermission(authz, server, viewPermissionName, resource, viewScope, viewClientsPolicy);
} }
String mapRolePermissionName = getMapRolesPermissionName(client); String mapRolePermissionName = getMapRolesPermissionName(client);
Policy mapRolePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRolePermissionName, server.getId()); Policy mapRolePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRolePermissionName, server.getId());
@ -216,7 +212,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
throw new ForbiddenException(); throw new ForbiddenException();
} }
} }
public boolean canManageClientDefault() { public boolean canManageClientsDefault() {
return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS); return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS);
} }
public boolean canViewClientDefault() { public boolean canViewClientDefault() {
@ -225,7 +221,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
@Override @Override
public boolean canManage() { public boolean canManage() {
return canManageClientDefault(); return canManageClientsDefault();
} }
@Override @Override
@ -236,7 +232,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
} }
@Override @Override
public boolean canView() { public boolean canView() {
return canManageClientDefault() || canViewClientDefault(); return canManageClientsDefault() || canViewClientDefault();
} }
@Override @Override
@ -269,25 +265,26 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
@Override @Override
public boolean canManage(ClientModel client) { public boolean canManage(ClientModel client) {
if (canManageClientsDefault()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canManage(); return false;
} }
ResourceServer server = resourceServer(client); ResourceServer server = resourceServer(client);
if (server == null) return canManage(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
if (resource == null) return canManage(); if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId()); Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
if (policy == null) { if (policy == null) {
return canManage(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return canManage(); return false;
} }
Scope scope = manageScope(server); Scope scope = manageScope(server);
@ -303,25 +300,30 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
@Override @Override
public boolean canView(ClientModel client) { public boolean canView(ClientModel client) {
return hasView(client) || canManage(client);
}
private boolean hasView(ClientModel client) {
if (canView()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canView(); return false;
} }
ResourceServer server = resourceServer(client); ResourceServer server = resourceServer(client);
if (server == null) return canView(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
if (resource == null) return canView(); if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId()); Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
if (policy == null) { if (policy == null) {
return canView(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return canView(); return false;
} }
Scope scope = viewScope(server); Scope scope = viewScope(server);
@ -344,7 +346,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
@Override @Override
public boolean canManageTemplates() { public boolean canManageTemplates() {
return canManageClientDefault(); return canManageClientsDefault();
} }
@Override @Override
@ -362,7 +364,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
@Override @Override
public boolean canManage(ClientTemplateModel template) { public boolean canManage(ClientTemplateModel template) {
return canManageClientDefault(); return canManageClientsDefault();
} }
@Override @Override

View file

@ -53,5 +53,9 @@ public interface GroupPermissionEvaluator {
void requireManageMembers(GroupModel group); void requireManageMembers(GroupModel group);
boolean canManageMembership(GroupModel group);
void requireManageMembership(GroupModel group);
Map<String, Boolean> getAccess(GroupModel group); Map<String, Boolean> getAccess(GroupModel group);
} }

View file

@ -33,10 +33,14 @@ public interface GroupPermissionManagement {
Policy viewMembersPermission(GroupModel group); Policy viewMembersPermission(GroupModel group);
Policy manageMembersPermission(GroupModel group); Policy manageMembersPermission(GroupModel group);
Policy manageMembershipPermission(GroupModel group);
Policy viewPermission(GroupModel group); Policy viewPermission(GroupModel group);
Policy managePermission(GroupModel group); Policy managePermission(GroupModel group);
Resource resource(GroupModel group); Resource resource(GroupModel group);
Map<String, String> getPermissions(GroupModel group); Map<String, String> getPermissions(GroupModel group);
} }

View file

@ -41,6 +41,7 @@ import java.util.Set;
class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement { class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement {
private static final Logger logger = Logger.getLogger(GroupPermissions.class); private static final Logger logger = Logger.getLogger(GroupPermissions.class);
public static final String MAP_ROLE_SCOPE = "map-role"; public static final String MAP_ROLE_SCOPE = "map-role";
public static final String MANAGE_MEMBERSHIP_SCOPE = "manage.membership";
public static final String MANAGE_MEMBERS_SCOPE = "manage.members"; public static final String MANAGE_MEMBERS_SCOPE = "manage.members";
public static final String VIEW_MEMBERS_SCOPE = "view.members"; public static final String VIEW_MEMBERS_SCOPE = "view.members";
protected final KeycloakSession session; protected final KeycloakSession session;
@ -68,6 +69,10 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
return "manage.members.permission.group." + group.getId(); return "manage.members.permission.group." + group.getId();
} }
public static String getManageMembershipPermissionGroup(GroupModel group) {
return "manage.membership.permission.group." + group.getId();
}
public static String getGroupSuffix(GroupModel group) { public static String getGroupSuffix(GroupModel group) {
return ModelToRepresentation.buildGroupPath(group).replace('/', '.'); return ModelToRepresentation.buildGroupPath(group).replace('/', '.');
} }
@ -88,6 +93,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Scope viewScope = root.realmViewScope(); Scope viewScope = root.realmViewScope();
Scope manageMembersScope = root.initializeRealmScope(MANAGE_MEMBERS_SCOPE); Scope manageMembersScope = root.initializeRealmScope(MANAGE_MEMBERS_SCOPE);
Scope viewMembersScope = root.initializeRealmScope(VIEW_MEMBERS_SCOPE); Scope viewMembersScope = root.initializeRealmScope(VIEW_MEMBERS_SCOPE);
Scope manageMembershipScope = root.initializeRealmScope(MANAGE_MEMBERSHIP_SCOPE);
String groupResourceName = getGroupResourceName(group); String groupResourceName = getGroupResourceName(group);
Resource groupResource = authz.getStoreFactory().getResourceStore().findByName(groupResourceName, server.getId()); Resource groupResource = authz.getStoreFactory().getResourceStore().findByName(groupResourceName, server.getId());
@ -96,19 +102,19 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Set<Scope> scopeset = new HashSet<>(); Set<Scope> scopeset = new HashSet<>();
scopeset.add(manageScope); scopeset.add(manageScope);
scopeset.add(viewScope); scopeset.add(viewScope);
scopeset.add(manageMembershipScope);
scopeset.add(manageMembersScope);
groupResource.updateScopes(scopeset); groupResource.updateScopes(scopeset);
} }
String managePermissionName = getManagePermissionGroup(group); String managePermissionName = getManagePermissionGroup(group);
Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId()); Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
if (managePermission == null) { if (managePermission == null) {
Policy manageUsersPolicy = root.roles().manageUsersPolicy(server); Helper.addEmptyScopePermission(authz, server, managePermissionName, groupResource, manageScope);
Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
} }
String viewPermissionName = getViewPermissionGroup(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); Helper.addEmptyScopePermission(authz, server, viewPermissionName, groupResource, viewScope);
Helper.addScopePermission(authz, server, viewPermissionName, groupResource, viewScope, viewUsersPolicy);
} }
String manageMembersPermissionName = getManageMembersPermissionGroup(group); String manageMembersPermissionName = getManageMembersPermissionGroup(group);
Policy manageMembersPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId()); Policy manageMembersPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId());
@ -120,6 +126,12 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
if (viewMembersPermission == null) { if (viewMembersPermission == null) {
Helper.addEmptyScopePermission(authz, server, viewMembersPermissionName, groupResource, viewMembersScope); Helper.addEmptyScopePermission(authz, server, viewMembersPermissionName, groupResource, viewMembersScope);
} }
String manageMembershipPermissionName = getManageMembershipPermissionGroup(group);
Policy manageMembershipPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembershipPermissionName, server.getId());
if (manageMembershipPermission == null) {
Helper.addEmptyScopePermission(authz, server, manageMembershipPermissionName, groupResource, manageMembershipScope);
}
} }
@Override @Override
@ -199,6 +211,14 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
return authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId()); return authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId());
} }
@Override
public Policy manageMembershipPermission(GroupModel group) {
ResourceServer server = root.realmResourceServer();
if (server == null) return null;
String manageMembershipPermissionName = getManageMembershipPermissionGroup(group);
return authz.getStoreFactory().getPolicyStore().findByName(manageMembershipPermissionName, server.getId());
}
@Override @Override
public Policy viewPermission(GroupModel group) { public Policy viewPermission(GroupModel group) {
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
@ -231,6 +251,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(group).getId()); scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(group).getId());
scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId()); scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId()); scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
scopes.put(MANAGE_MEMBERSHIP_SCOPE, manageMembershipPermission(group).getId());
return scopes; return scopes;
} }
@ -239,25 +260,26 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override @Override
public boolean canManage(GroupModel group) { public boolean canManage(GroupModel group) {
if (canManage()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canManage(); return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return canManage(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canManage(); if (resource == null) return false;
Policy policy = managePermission(group); Policy policy = managePermission(group);
if (policy == null) { if (policy == null) {
return canManage(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return canManage(); return false;
} }
Scope scope = root.realmManageScope(); Scope scope = root.realmManageScope();
@ -272,25 +294,31 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
} }
@Override @Override
public boolean canView(GroupModel group) { public boolean canView(GroupModel group) {
return hasView(group) || canManage(group);
}
private boolean hasView(GroupModel group) {
if (canView()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canView(); return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return canView(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canView(); if (resource == null) return false;
Policy policy = viewPermission(group); Policy policy = viewPermission(group);
if (policy == null) { if (policy == null) {
return canView(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then abort // if no policies attached to permission then abort
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return canView(); return false;
} }
Scope scope = root.realmViewScope(); Scope scope = root.realmViewScope();
@ -335,25 +363,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
} }
private boolean canViewMembersEvaluation(GroupModel group) { private boolean canViewMembersEvaluation(GroupModel group) {
if (root.users().canView()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return root.users().canView(); return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return root.users().canView(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return root.users().canView(); if (resource == null) return false;
Policy policy = viewMembersPermission(group); Policy policy = viewMembersPermission(group);
if (policy == null) { if (policy == null) {
return root.users().canView(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return root.users().canView(); return false;
} }
Scope scope = authz.getStoreFactory().getScopeStore().findByName(VIEW_MEMBERS_SCOPE, server.getId()); Scope scope = authz.getStoreFactory().getScopeStore().findByName(VIEW_MEMBERS_SCOPE, server.getId());
@ -372,25 +402,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override @Override
public boolean canManageMembers(GroupModel group) { public boolean canManageMembers(GroupModel group) {
if (root.users().canManage()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return root.users().canManage(); return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return root.users().canManage(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return root.users().canManage(); if (resource == null) return false;
Policy policy = manageMembersPermission(group); Policy policy = manageMembersPermission(group);
if (policy == null) { if (policy == null) {
return root.users().canManage(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return root.users().canManage(); return false;
} }
Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERS_SCOPE, server.getId()); Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERS_SCOPE, server.getId());
@ -404,11 +436,48 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
} }
} }
@Override
public boolean canManageMembership(GroupModel group) {
if (canManage(group)) return true;
if (!root.isAdminSameRealm()) {
return false;
}
ResourceServer server = root.realmResourceServer();
if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return false;
Policy policy = manageMembershipPermission(group);
if (policy == null) {
return false;
}
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return false;
}
Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERSHIP_SCOPE, server.getId());
return root.evaluatePermission(resource, scope, server);
}
@Override
public void requireManageMembership(GroupModel group) {
if (!canManageMembership(group)) {
throw new ForbiddenException();
}
}
@Override @Override
public Map<String, Boolean> getAccess(GroupModel group) { public Map<String, Boolean> getAccess(GroupModel group) {
Map<String, Boolean> map = new HashMap<>(); Map<String, Boolean> map = new HashMap<>();
map.put("view", canView(group)); map.put("view", canView(group));
map.put("manage", canManage(group)); map.put("manage", canManage(group));
map.put("manageMembership", canManageMembership(group));
return map; return map;
} }

View file

@ -40,6 +40,7 @@ import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.services.ForbiddenException; import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
@ -51,7 +52,7 @@ import java.util.List;
* @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 $
*/ */
class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManagement { class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManagement, RealmsPermissionEvaluator {
private static final Logger logger = Logger.getLogger(MgmtPermissions.class); private static final Logger logger = Logger.getLogger(MgmtPermissions.class);
protected RealmModel realm; protected RealmModel realm;
@ -85,7 +86,21 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
&& !auth.getRealm().equals(new RealmManager(session).getKeycloakAdminstrationRealm())) { && !auth.getRealm().equals(new RealmManager(session).getKeycloakAdminstrationRealm())) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)) { if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
|| auth.getClient().getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser());
} else {
this.identity = new KeycloakIdentity(auth.getToken(), session);
}
}
MgmtPermissions(KeycloakSession session, AdminAuth auth) {
this.session = session;
this.auth = auth;
this.admin = auth.getUser();
this.adminsRealm = auth.getRealm();
if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
|| auth.getClient().getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser()); this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser());
} else { } else {
@ -117,17 +132,36 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
@Override
public void requireAnyAdminRole() {
if (!hasAnyAdminRole()) {
throw new ForbiddenException();
}
}
public boolean hasAnyAdminRole() { public boolean hasAnyAdminRole() {
return hasOneAdminRole(AdminRoles.ALL_REALM_ROLES); return hasOneAdminRole(AdminRoles.ALL_REALM_ROLES);
} }
public boolean hasAnyAdminRole(RealmModel realm) {
return hasOneAdminRole(realm, AdminRoles.ALL_REALM_ROLES);
}
public boolean hasOneAdminRole(String... adminRoles) { public boolean hasOneAdminRole(String... adminRoles) {
String clientId;
RealmModel realm = this.realm;
return hasOneAdminRole(realm, adminRoles);
}
public boolean hasOneAdminRole(RealmModel realm, String... adminRoles) {
String clientId; String clientId;
RealmManager realmManager = new RealmManager(session); RealmManager realmManager = new RealmManager(session);
if (adminsRealm.equals(realmManager.getKeycloakAdminstrationRealm())) { if (adminsRealm.equals(realmManager.getKeycloakAdminstrationRealm())) {
clientId = realm.getMasterAdminClient().getClientId(); clientId = realm.getMasterAdminClient().getClientId();
} else if (adminsRealm.equals(realm)) {
clientId = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm)).getClientId();
} else { } else {
clientId = realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())).getClientId(); return false;
} }
for (String adminRole : adminRoles) { for (String adminRole : adminRoles) {
if (identity.hasClientRole(clientId, adminRole)) return true; if (identity.hasClientRole(clientId, adminRole)) return true;
@ -136,7 +170,6 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
} }
public boolean isAdminSameRealm() { public boolean isAdminSameRealm() {
return auth == null || realm.getId().equals(auth.getRealm().getId()); return auth == null || realm.getId().equals(auth.getRealm().getId());
} }
@ -274,6 +307,33 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
} }
} }
@Override
public boolean canView(RealmModel realm) {
return hasOneAdminRole(realm, AdminRoles.VIEW_REALM, AdminRoles.MANAGE_REALM);
}
@Override
public boolean isAdmin(RealmModel realm) {
return hasAnyAdminRole(realm);
}
@Override
public boolean canCreateRealm() {
RealmManager realmManager = new RealmManager(session);
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
return false;
}
return identity.hasRealmRole(AdminRoles.CREATE_REALM);
}
@Override
public void requireCreateRealm() {
if (!canCreateRealm()) {
throw new ForbiddenException();
}
}
} }

View file

@ -16,12 +16,14 @@
*/ */
package org.keycloak.services.resources.admin.permissions; package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.RealmModel;
/** /**
* @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 RealmPermissionEvaluator { public interface RealmPermissionEvaluator {
boolean canListRealm(); boolean canListRealms();
void requireViewRealmNameList(); void requireViewRealmNameList();

View file

@ -76,17 +76,18 @@ class RealmPermissions implements RealmPermissionEvaluator {
} }
@Override @Override
public boolean canListRealm() { public boolean canListRealms() {
return root.hasAnyAdminRole(); return root.hasAnyAdminRole();
} }
@Override @Override
public void requireViewRealmNameList() { public void requireViewRealmNameList() {
if (!canListRealm()) { if (!canListRealms()) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
} }
@Override @Override
public boolean canManageRealm() { public boolean canManageRealm() {
return canManageRealmDefault(); return canManageRealmDefault();

View file

@ -0,0 +1,33 @@
/*
* 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.services.resources.admin.permissions;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface RealmsPermissionEvaluator {
boolean canView(RealmModel realm);
boolean isAdmin(RealmModel realm);
boolean canCreateRealm();
void requireCreateRealm();
}

View file

@ -69,10 +69,15 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
} else { } else {
ResourceServer server = resourceServer(role); ResourceServer server = resourceServer(role);
if (server == null) return; if (server == null) return;
Policy policy = mapRolePermission(role);
if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
policy = mapClientScopePermission(role);
if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
policy = mapCompositePermission(role);
if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId()); if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), server.getId());
if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
} }
} }
@ -140,20 +145,22 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
*/ */
@Override @Override
public boolean canMapRole(RoleModel role) { public boolean canMapRole(RoleModel role) {
if (root.users().canManageDefault()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return root.users().canManageDefault(); return false;
} }
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().canManageDefault(); return false;
} }
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().canManageDefault(); // if no policies applied, just do default return false;
} }
Resource roleResource = resource(role); Resource roleResource = resource(role);
@ -216,20 +223,22 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
@Override @Override
public boolean canMapComposite(RoleModel role) { public boolean canMapComposite(RoleModel role) {
if (canManageDefault(role)) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canManage(role); return false;
} }
if (role.getContainer() instanceof ClientModel) { if (role.getContainer() instanceof ClientModel) {
if (root.clients().canMapCompositeRoles((ClientModel)role.getContainer())) return true; if (root.clients().canMapCompositeRoles((ClientModel)role.getContainer())) return true;
} }
if (!isPermissionsEnabled(role)){ if (!isPermissionsEnabled(role)){
return canManage(role); return false;
} }
ResourceServer resourceServer = getResourceServer(role); ResourceServer resourceServer = getResourceServer(role);
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapCompositePermissionName(role), resourceServer.getId()); Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapCompositePermissionName(role), resourceServer.getId());
if (policy.getAssociatedPolicies().isEmpty()) { if (policy.getAssociatedPolicies().isEmpty()) {
return canManage(role); return false;
} }
Resource roleResource = resource(role); Resource roleResource = resource(role);
@ -248,20 +257,21 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
@Override @Override
public boolean canMapClientScope(RoleModel role) { public boolean canMapClientScope(RoleModel role) {
if (root.clients().canManageClientsDefault()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return root.clients().canManage(); return false;
} }
if (role.getContainer() instanceof ClientModel) { if (role.getContainer() instanceof ClientModel) {
if (root.clients().canMapClientScopeRoles((ClientModel)role.getContainer())) return true; if (root.clients().canMapClientScopeRoles((ClientModel)role.getContainer())) return true;
} }
if (!isPermissionsEnabled(role)){ if (!isPermissionsEnabled(role)){
return root.clients().canManage(); return false;
} }
ResourceServer resourceServer = getResourceServer(role); ResourceServer resourceServer = getResourceServer(role);
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapClientScopePermissionName(role), resourceServer.getId()); Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapClientScopePermissionName(role), resourceServer.getId());
if (policy.getAssociatedPolicies().isEmpty()) { if (policy.getAssociatedPolicies().isEmpty()) {
return root.clients().canManage(); return false;
} }
Resource roleResource = resource(role); Resource roleResource = resource(role);
@ -288,6 +298,16 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
return false; return false;
} }
public boolean canManageDefault(RoleModel role) {
if (role.getContainer() instanceof RealmModel) {
return root.realm().canManageRealmDefault();
} else if (role.getContainer() instanceof ClientModel) {
ClientModel client = (ClientModel)role.getContainer();
return root.clients().canManageClientsDefault();
}
return false;
}
@Override @Override
public void requireManage(RoleModel role) { public void requireManage(RoleModel role) {
if (!canManage(role)) { if (!canManage(role)) {
@ -375,25 +395,15 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
Resource resource = authz.getStoreFactory().getResourceStore().create(getRoleResourceName(role), server, server.getClientId()); Resource resource = authz.getStoreFactory().getResourceStore().create(getRoleResourceName(role), server, server.getClientId());
resource.setType("Role"); resource.setType("Role");
Scope mapRoleScope = getMapRoleScope(server); Scope mapRoleScope = getMapRoleScope(server);
Policy policy = manageUsersPolicy(server); Policy mapRolePermission = Helper.addEmptyScopePermission(authz, server, getMapRolePermissionName(role), resource, mapRoleScope);
Policy mapRolePermission = Helper.addScopePermission(authz, server, getMapRolePermissionName(role), resource, mapRoleScope, policy);
mapRolePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE); mapRolePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
Scope mapClientScope = getMapClientScope(server); Scope mapClientScope = getMapClientScope(server);
RoleModel mngClients = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS); Policy mapClientScopePermission = Helper.addEmptyScopePermission(authz, server, getMapClientScopePermissionName(role), resource, mapClientScope);
Policy mngClientsPolicy = rolePolicy(server, mngClients);
Policy mapClientScopePermission = Helper.addScopePermission(authz, server, getMapClientScopePermissionName(role), resource, mapClientScope, mngClientsPolicy);
mapClientScopePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE); mapClientScopePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
Scope mapCompositeScope = getMapCompositeScope(server); Scope mapCompositeScope = getMapCompositeScope(server);
if (role.getContainer() instanceof RealmModel) { Policy mapCompositePermission = Helper.addEmptyScopePermission(authz, server, getMapCompositePermissionName(role), resource, mapCompositeScope);
RoleModel mngRealm = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_REALM);
policy = rolePolicy(server, mngRealm);
} else {
policy = mngClientsPolicy;
}
Policy mapCompositePermission = Helper.addScopePermission(authz, server, getMapCompositePermissionName(role), resource, mapCompositeScope, policy);
mapCompositePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE); mapCompositePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
return resource; return resource;
} }

View file

@ -16,6 +16,7 @@
*/ */
package org.keycloak.services.resources.admin.permissions; package org.keycloak.services.resources.admin.permissions;
import org.keycloak.authorization.model.Policy;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import java.util.Map; import java.util.Map;
@ -25,7 +26,7 @@ import java.util.Map;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public interface UserPermissionEvaluator { public interface UserPermissionEvaluator {
boolean canManage(); boolean canManage();
void requireManage(); void requireManage();
@ -51,4 +52,12 @@ public interface UserPermissionEvaluator {
void requireImpersonate(UserModel user); void requireImpersonate(UserModel user);
Map<String, Boolean> getAccess(UserModel user); Map<String, Boolean> getAccess(UserModel user);
boolean canMapRoles(UserModel user);
void requireMapRoles(UserModel user);
boolean canManageGroupMembership(UserModel user);
void requireManageGroupMembership(UserModel user);
} }

View file

@ -38,4 +38,10 @@ public interface UserPermissionManagement {
Policy managePermission(); Policy managePermission();
Policy viewPermission(); Policy viewPermission();
Policy manageGroupMembershipPermission();
Policy mapRolesPermission();
Policy impersonatePermission();
} }

View file

@ -45,6 +45,12 @@ import java.util.Set;
*/ */
class UserPermissions implements UserPermissionEvaluator, UserPermissionManagement { class UserPermissions implements UserPermissionEvaluator, UserPermissionManagement {
private static final Logger logger = Logger.getLogger(UserPermissions.class); private static final Logger logger = Logger.getLogger(UserPermissions.class);
public static final String MAP_ROLES_SCOPE="map-roles";
public static final String IMPERSONATE_SCOPE="impersonate";
public static final String MANAGE_GROUP_MEMBERSHIP_SCOPE="manage-group-membership";
public static final String MAP_ROLES_PERMISSION_USERS = "map-roles.permission.users";
public static final String IMPERSONATE_PERMISSION_USERS = "impersonate.permission.users";
public static final String MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS = "manage-group-membership.permission.users";
public static final String MANAGE_PERMISSION_USERS = "manage.permission.users"; public static final String MANAGE_PERMISSION_USERS = "manage.permission.users";
public static final String VIEW_PERMISSION_USERS = "view.permission.users"; public static final String VIEW_PERMISSION_USERS = "view.permission.users";
public static final String USERS_RESOURCE = "Users"; public static final String USERS_RESOURCE = "Users";
@ -67,6 +73,9 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
Scope manageScope = root.realmManageScope(); Scope manageScope = root.realmManageScope();
Scope viewScope = root.realmViewScope(); Scope viewScope = root.realmViewScope();
Scope mapRolesScope = root.initializeRealmScope(MAP_ROLES_SCOPE);
Scope impersonateScope = root.initializeRealmScope(IMPERSONATE_SCOPE);
Scope manageGroupMembershipScope = root.initializeRealmScope(MANAGE_GROUP_MEMBERSHIP_SCOPE);
Resource usersResource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId()); Resource usersResource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
if (usersResource == null) { if (usersResource == null) {
@ -74,17 +83,30 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
Set<Scope> scopeset = new HashSet<>(); Set<Scope> scopeset = new HashSet<>();
scopeset.add(manageScope); scopeset.add(manageScope);
scopeset.add(viewScope); scopeset.add(viewScope);
scopeset.add(mapRolesScope);
scopeset.add(impersonateScope);
scopeset.add(manageGroupMembershipScope);
usersResource.updateScopes(scopeset); usersResource.updateScopes(scopeset);
} }
Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId()); Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
if (managePermission == null) { if (managePermission == null) {
Policy manageUsersPolicy = root.roles().manageUsersPolicy(server); Helper.addEmptyScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope);
Helper.addScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope, manageUsersPolicy);
} }
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId()); Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
if (viewPermission == null) { if (viewPermission == null) {
Policy viewUsersPolicy = root.roles().viewUsersPolicy(server); Helper.addEmptyScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope);
Helper.addScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope, viewUsersPolicy); }
Policy mapRolesPermission = authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
if (mapRolesPermission == null) {
Helper.addEmptyScopePermission(authz, server, MAP_ROLES_PERMISSION_USERS, usersResource, mapRolesScope);
}
Policy membershipPermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
if (membershipPermission == null) {
Helper.addEmptyScopePermission(authz, server, MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, usersResource, manageGroupMembershipScope);
}
Policy impersonatePermission = authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
if (impersonatePermission == null) {
Helper.addEmptyScopePermission(authz, server, IMPERSONATE_PERMISSION_USERS, usersResource, impersonateScope);
} }
} }
@ -93,6 +115,9 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
Map<String, String> scopes = new HashMap<>(); Map<String, String> scopes = new HashMap<>();
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission().getId()); scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission().getId());
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission().getId()); scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission().getId());
scopes.put(MAP_ROLES_SCOPE, mapRolesPermission().getId());
scopes.put(MANAGE_GROUP_MEMBERSHIP_SCOPE, manageGroupMembershipPermission().getId());
scopes.put(IMPERSONATE_SCOPE, impersonatePermission().getId());
return scopes; return scopes;
} }
@ -117,7 +142,22 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
} else { } else {
ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId()); ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
if (server == null) return; if (server == null) return;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId()); Policy policy = managePermission();
if (policy == null) {
authz.getStoreFactory().getPolicyStore().delete(policy.getId());
}
policy = viewPermission();
if (policy == null) {
authz.getStoreFactory().getPolicyStore().delete(policy.getId());
}
policy = mapRolesPermission();
if (policy == null) {
authz.getStoreFactory().getPolicyStore().delete(policy.getId());
}
policy = manageGroupMembershipPermission();
if (policy == null) { if (policy == null) {
authz.getStoreFactory().getPolicyStore().delete(policy.getId()); authz.getStoreFactory().getPolicyStore().delete(policy.getId());
@ -153,6 +193,25 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
return authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId()); return authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
} }
@Override
public Policy manageGroupMembershipPermission() {
ResourceServer server = root.realmResourceServer();
return authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
}
@Override
public Policy mapRolesPermission() {
ResourceServer server = root.realmResourceServer();
return authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
}
@Override
public Policy impersonatePermission() {
ResourceServer server = root.realmResourceServer();
return authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
}
/** /**
@ -170,25 +229,26 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
*/ */
@Override @Override
public boolean canManage() { public boolean canManage() {
if (canManageDefault()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canManageDefault(); return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return canManageDefault(); if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
if (resource == null) return canManageDefault(); if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId()); Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
if (policy == null) { if (policy == null) {
return canManageDefault(); return false;
} }
Set<Policy> associatedPolicies = policy.getAssociatedPolicies(); Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior // if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) { if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return canManageDefault(); return false;
} }
Scope scope = root.realmManageScope(); Scope scope = root.realmManageScope();
@ -321,14 +381,15 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
*/ */
@Override @Override
public boolean canView() { public boolean canView() {
if (canViewDefault()) return true;
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return canViewDefault(); return false;
} }
return hasViewPermission() || canManage(); return hasViewPermission() || canManage();
} }
public boolean hasViewPermission() { private boolean hasViewPermission() {
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return canViewDefault(); if (server == null) return canViewDefault();
@ -382,7 +443,32 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
@Override @Override
public boolean canImpersonate(UserModel user) { public boolean canImpersonate(UserModel user) {
return root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE); if (root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE)) return true;
if (!root.isAdminSameRealm()) {
return false;
}
ResourceServer server = root.realmResourceServer();
if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
if (policy == null) {
return false;
}
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return false;
}
Scope scope = root.realmScope(IMPERSONATE_SCOPE);
return root.evaluatePermission(resource, scope, server);
} }
@Override @Override
@ -397,9 +483,90 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
Map<String, Boolean> map = new HashMap<>(); Map<String, Boolean> map = new HashMap<>();
map.put("view", canView(user)); map.put("view", canView(user));
map.put("manage", canManage(user)); map.put("manage", canManage(user));
map.put("mapRoles", canMapRoles(user));
map.put("manageGroupMembership", canManageGroupMembership(user));
map.put("impersonate", canImpersonate(user));
return map; return map;
} }
@Override
public boolean canMapRoles(UserModel user) {
if (canManage(user)) return true;
if (!root.isAdminSameRealm()) {
return false;
}
ResourceServer server = root.realmResourceServer();
if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
if (policy == null) {
return false;
}
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return false;
}
Scope scope = root.realmScope(MAP_ROLES_SCOPE);
return root.evaluatePermission(resource, scope, server);
}
@Override
public void requireMapRoles(UserModel user) {
if (!canMapRoles(user)) {
throw new ForbiddenException();
}
}
@Override
public boolean canManageGroupMembership(UserModel user) {
if (canManage(user)) return true;
if (!root.isAdminSameRealm()) {
return false;
}
ResourceServer server = root.realmResourceServer();
if (server == null) return false;
Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
if (resource == null) return false;
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
if (policy == null) {
return false;
}
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
// if no policies attached to permission then just do default behavior
if (associatedPolicies == null || associatedPolicies.isEmpty()) {
return false;
}
Scope scope = root.realmScope(MANAGE_GROUP_MEMBERSHIP_SCOPE);
return root.evaluatePermission(resource, scope, server);
}
@Override
public void requireManageGroupMembership(UserModel user) {
if (!canManageGroupMembership(user)) {
throw new ForbiddenException();
}
}

View file

@ -66,6 +66,43 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
testRealmRep.setEnabled(true); testRealmRep.setEnabled(true);
testRealms.add(testRealmRep); testRealms.add(testRealmRep);
} }
public static void setupDemo(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
ClientModel client = realm.addClient("sales-pipeline-application");
RoleModel clientAdmin = client.addRole("admin");
client.addRole("leader-creator");
client.addRole("viewLeads");
ClientModel client2 = realm.addClient("market-analysis-application");
RoleModel client2Admin = client2.addRole("admin");
client2.addRole("market-manager");
client2.addRole("viewMarkets");
GroupModel sales = realm.createGroup("sales");
RoleModel salesAppsAdminRole = realm.addRole("sales-apps-admin");
salesAppsAdminRole.addCompositeRole(clientAdmin);
salesAppsAdminRole.addCompositeRole(client2Admin);
UserModel admin = session.users().addUser(realm, "salesManager");
admin.setEnabled(true);
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
admin = session.users().addUser(realm, "sales-group-admin");
admin.setEnabled(true);
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
admin = session.users().addUser(realm, "sales-it");
admin.setEnabled(true);
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
admin = session.users().addUser(realm, "sales-pipeline-admin");
admin.setEnabled(true);
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
UserModel user = session.users().addUser(realm, "salesman");
user.setEnabled(true);
user.joinGroup(sales);
user = session.users().addUser(realm, "saleswoman");
user.setEnabled(true);
}
public static void setupPolices(KeycloakSession session) { public static void setupPolices(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST); RealmModel realm = session.realms().getRealmByName(TEST);
@ -304,9 +341,14 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
protected boolean isImportAfterEachMethod() { protected boolean isImportAfterEachMethod() {
return true; return true;
} }
//@Test
public void testDemo() throws Exception {
testingClient.server().run(FineGrainAdminUnitTest::setupDemo);
Thread.sleep(1000000000);
}
@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);

View file

@ -717,7 +717,7 @@ public class PermissionsTest extends AbstractKeycloakTest {
public void invoke(RealmResource realm) { public void invoke(RealmResource realm) {
realm.clientTemplates().findAll(); realm.clientTemplates().findAll();
} }
}, Resource.CLIENT, false); }, Resource.CLIENT, false, true);
invoke(new InvocationWithResponse() { invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) { public void invoke(RealmResource realm, AtomicReference<Response> response) {
ClientTemplateRepresentation template = new ClientTemplateRepresentation(); ClientTemplateRepresentation template = new ClientTemplateRepresentation();

View file

@ -29,7 +29,7 @@ log4j.appender.testsuite.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%C{1}]
keycloak.logging.level=info keycloak.logging.level=info
log4j.logger.org.keycloak=${keycloak.logging.level} log4j.logger.org.keycloak=${keycloak.logging.level}
log4j.logger.org.jboss.resteasy.resteasy_jaxrs.i18n=off #log4j.logger.org.jboss.resteasy.resteasy_jaxrs.i18n=off
#log4j.logger.org.keycloak.keys.DefaultKeyManager=trace #log4j.logger.org.keycloak.keys.DefaultKeyManager=trace
#log4j.logger.org.keycloak.services.managers.AuthenticationManager=trace #log4j.logger.org.keycloak.services.managers.AuthenticationManager=trace
@ -62,7 +62,7 @@ log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=de
log4j.logger.org.xnio=off log4j.logger.org.xnio=off
log4j.logger.org.hibernate=off log4j.logger.org.hibernate=off
log4j.logger.org.jboss.resteasy=warn log4j.logger.org.jboss.resteasy=info
log4j.logger.org.apache.directory.api=warn log4j.logger.org.apache.directory.api=warn
log4j.logger.org.apache.directory.server.core=warn log4j.logger.org.apache.directory.server.core=warn

View file

@ -2394,6 +2394,7 @@ module.controller('ClientRolePermissionsCtrl', function($scope, $http, $route, $
$scope.permissions = data; $scope.permissions = data;
}); });
$scope.setEnabled = function() { $scope.setEnabled = function() {
console.log('perssions enabled: ' + $scope.permissions.enabled);
var param = { enabled: $scope.permissions.enabled}; var param = { enabled: $scope.permissions.enabled};
$scope.permissions = RoleManagementPermissions.update({realm: realm.realm, role:role.id}, param); $scope.permissions = RoleManagementPermissions.update({realm: realm.realm, role:role.id}, param);
}; };

View file

@ -6,7 +6,7 @@
<kc-tabs-group></kc-tabs-group> <kc-tabs-group></kc-tabs-group>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageUsers"> <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!group.access.manage">
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <tr>
@ -29,7 +29,7 @@
</tbody> </tbody>
</table> </table>
<div class="form-group" data-ng-show="access.manageUsers"> <div class="form-group" data-ng-show="group.access.manage">
<div class="col-md-12"> <div class="col-md-12">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button> <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>

View file

@ -16,7 +16,7 @@
</div> </div>
</fieldset> </fieldset>
<div class="form-group" data-ng-show="access.manageUsers"> <div class="form-group" data-ng-show="group.access.manage">
<div class="col-md-10 col-md-offset-2"> <div class="col-md-10 col-md-offset-2">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button> <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>

View file

@ -7,7 +7,7 @@
<kc-tabs-group></kc-tabs-group> <kc-tabs-group></kc-tabs-group>
<form class="form-horizontal" name="realmForm" novalidate> <form class="form-horizontal" name="realmForm" novalidate>
<div class="form-group" kc-read-only="!access.manageUsers"> <div class="form-group" kc-read-only="!group.access.manage">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label> <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10"> <div class="col-md-10">
@ -54,7 +54,7 @@
<span>{{:: 'client-roles' | translate}}</span> <span>{{:: 'client-roles' | translate}}</span>
<select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select> <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select>
</label> </label>
<div class="col-md-10" kc-read-only="!access.manageUsers"> <div class="col-md-10" kc-read-only="!group.access.manage">
<div class="row" data-ng-hide="targetClient"> <div class="row" data-ng-hide="targetClient">
<div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div> <div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-user></kc-tabs-user> <kc-tabs-user></kc-tabs-user>
<form class="form-horizontal" name="realmForm" novalidate> <form class="form-horizontal" name="realmForm" novalidate>
<div class="form-group" kc-read-only="!access.manageUsers"> <div class="form-group" kc-read-only="!user.access.mapRoles">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label> <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10"> <div class="col-md-10">
@ -54,7 +54,7 @@
<span>{{:: 'client-roles' | translate}}</span> <span>{{:: 'client-roles' | translate}}</span>
<select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select> <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select>
</label> </label>
<div class="col-md-10" kc-read-only="!access.manageUsers"> <div class="col-md-10" kc-read-only="!user.access.mapRoles">
<div class="row" data-ng-hide="targetClient"> <div class="row" data-ng-hide="targetClient">
<div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div> <div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div>
</div> </div>

View file

@ -138,7 +138,7 @@
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button> <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div> </div>
<div class="col-md-10 col-md-offset-2" data-ng-show="!create && !user.access.manage"> <div class="col-md-10 col-md-offset-2" data-ng-show="!create && user.access.manage">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button> <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-user></kc-tabs-user> <kc-tabs-user></kc-tabs-user>
<form class="form-horizontal" name="realmForm" novalidate> <form class="form-horizontal" name="realmForm" novalidate>
<div class="form-group" kc-read-only="!access.manageUsers"> <div class="form-group" kc-read-only="!user.access.manageGroupMembership">
<label class="col-md-1 control-label" class="control-label"></label> <label class="col-md-1 control-label" class="control-label"></label>
<div class="col-md-8" > <div class="col-md-8" >
@ -21,7 +21,7 @@
<label class="control-label">{{:: 'group-membership' | translate}}</label> <label class="control-label">{{:: 'group-membership' | translate}}</label>
<kc-tooltip>{{:: 'group-membership.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'group-membership.tooltip' | translate}}</kc-tooltip>
<div class="pull-right" data-ng-show="access.manageUsers"> <div class="pull-right" data-ng-show="user.access.manageGroupMembership">
<button id="leaveGroups" class="btn btn-default" ng-click="leaveGroup()">{{:: 'leave' | translate}}</button> <button id="leaveGroups" class="btn btn-default" ng-click="leaveGroup()">{{:: 'leave' | translate}}</button>
</div> </div>
</div> </div>
@ -53,7 +53,7 @@
<label class="control-label">{{:: 'available-groups' | translate}}</label> <label class="control-label">{{:: 'available-groups' | translate}}</label>
<kc-tooltip>{{:: 'membership.available-groups.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'membership.available-groups.tooltip' | translate}}</kc-tooltip>
<div class="pull-right" data-ng-show="access.manageUsers"> <div class="pull-right" data-ng-show="user.access.manageGroupMembership">
<button id="joinGroup" class="btn btn-default" ng-click="joinGroup()">{{:: 'join' | translate}}</button> <button id="joinGroup" class="btn btn-default" ng-click="joinGroup()">{{:: 'join' | translate}}</button>
</div> </div>
</div> </div>