Skip to content

Commit

Permalink
Improvements for role mining functionality
Browse files Browse the repository at this point in the history
1. Adding basic structures needed for role-mining analysis.
2. Adding the initial functions needed to analyze role-mining in terms of permissions.
  • Loading branch information
tchrapovic committed Dec 22, 2022
1 parent 4a1d664 commit dbf2d9f
Show file tree
Hide file tree
Showing 17 changed files with 2,131 additions and 274 deletions.
37 changes: 37 additions & 0 deletions gui/admin-gui/src/frontend/scss/midpoint.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
@import "rounded-icon";
@import "tiles";
@import "tables";
@import "role-mining-rotated-header";
@import "role-mining-static-header";
@import "role-mining-static-header-name";
@import "role-mining-static-row-header";

body.custom-hold-transition {
.content-wrapper,
Expand Down Expand Up @@ -1773,6 +1777,39 @@ th.debug-list-buttons {
}
}

.role-mining-rotated-header{
display:flex; display:flex;
justify-content:center; justify-content:center;
align-items:center; align-items:center;
transform: rotate(180deg); transform: rotate(180deg);
writing-mode: vertical-lr; writing-mode: vertical-lr;
width: 40px; width: 40px;
height: 150px; height: 150px;
border: 1px solid #f4f4f4; border: 1px solid #f4f4f4;
}


.role-mining-static-header {
width: 40px;
height: 150px;
}

.role-mining-static-header-name {
display: flex;
justify-content: center;
align-items: center;
transform: rotate(180deg);
writing-mode: revert;
width: 40px;
height: 150px;
border: 1px solid #f4f4f4;
}

.role-mining-static-row-header {
width: 150px;
height: 150px;
}

@each $breakpoint in map-keys($grid-breakpoints) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@include media-breakpoint-up($breakpoint, $grid-breakpoints) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.gui.api.component.mining;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.web.component.util.Selectable;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class PAStructure extends Selectable<RoleMiningStructureList> implements Serializable {


public static final String F_NAME = "roleObject";
public static final String F_ROLE_MEMBERS_OID_LIST = "roleMembers";
public static final String F_TOTAL_RESULT = "objectTotalResult";
public static final String F_RESULT_ARRAY = "objectPartialResult";
public static final String F_STATIC_INDEX = "staticIndex";
public static final String F_AUTHORIZATION = "authorizationTypeList";

PrismObject<RoleType> roleObject;
List<AuthorizationType> authorizationTypeList;
List<PrismObject<UserType>> roleMembers;
double objectTotalResult;
ArrayList<Double> objectPartialResult;
int staticIndex;

public PAStructure(PrismObject<RoleType> roleObject, List<PrismObject<UserType>> roleMembers,
double objectTotalResult, ArrayList<Double> objectPartialResult,List<AuthorizationType> authorizationTypeList, int staticIndex) {
this.roleObject = roleObject;
this.roleMembers = roleMembers;
this.objectTotalResult = objectTotalResult;
this.objectPartialResult = objectPartialResult;
this.authorizationTypeList = authorizationTypeList;
this.staticIndex = staticIndex;
}

public PrismObject<RoleType> getRoleObject() {
return roleObject;
}

public void setRoleObject(PrismObject<RoleType> roleObject) {
this.roleObject = roleObject;
}

public List<PrismObject<UserType>> getRoleMembers() {
return roleMembers;
}

public void setRoleMembers(List<PrismObject<UserType>> roleMembers) {
this.roleMembers = roleMembers;
}

public double getObjectTotalResult() {
return objectTotalResult;
}

public void setObjectTotalResult(double objectTotalResult) {
this.objectTotalResult = objectTotalResult;
}

public ArrayList<Double> getObjectPartialResult() {
return objectPartialResult;
}

public void setObjectPartialResult(ArrayList<Double> objectPartialResult) {
this.objectPartialResult = objectPartialResult;
}

public int getStaticIndex() {
return staticIndex;
}

public void setStaticIndex(int staticIndex) {
this.staticIndex = staticIndex;
}

public List<AuthorizationType> getAuthorizationTypeList() {
return authorizationTypeList;
}

public void setAuthorizationTypeList(List<AuthorizationType> authorizationTypeList) {
this.authorizationTypeList = authorizationTypeList;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,81 @@
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

public class RoleAnalyseHelper implements Serializable {

//indicates the number of users who have all permissions corresponding to the selected role
public List<PrismObject<UserType>> authUserR(RoleType role, List<UPStructure> upStructures) {

List<AuthorizationType> rolePermission = new RoleMiningFilter().getAuthorization(role);

if (rolePermission == null || upStructures == null) {
return null;
}

List<PrismObject<UserType>> authUserList;

authUserList = upStructures.stream().filter(upStructure -> upStructure.getAssignPermission()
.containsAll(rolePermission)).map(UPStructure::getUserObject).collect(Collectors.toList());

return authUserList;
}

//indicates the percentage of users who have all permissions corresponding to the selected role
public double supportR(RoleType role, List<UPStructure> upStructures,
int userCount) {

List<AuthorizationType> rolePermission = new RoleMiningFilter().getAuthorization(role);
if (rolePermission == null || upStructures == null || userCount == 0) {
return 0;
}

List<PrismObject<UserType>> authUserList = authUserR(role, upStructures);
if (authUserList == null) {
return 0;
}

int authUserR = authUserList.size();
double supportR =(double) authUserR / userCount;

return (Math.round(supportR * 100.0) / 100.0);

}

//indicates the number of permissions of the selected role (?) \\TODO
public List<AuthorizationType> authPermsR(RoleType role) {
return new RoleMiningFilter().getAuthorization(role);
}

//indicates the number of permissions of the selected role (?) \\TODO
public int degreeR(RoleType role) {
return authPermsR(role).size();
}

public double confidenceR2R1(RoleType parent, RoleType child, List<UPStructure> upStructures,
int userCount) {

double confidenceR2R1 = supportR(parent, upStructures, userCount) / supportR(child, upStructures, userCount);
return (Math.round(confidenceR2R1 * 100.0) / 100.0);
}


public boolean logicParentCheck(RoleType parent, RoleType child, List<UPStructure> upStructures) {

List<PrismObject<UserType>> authUserParent = authUserR(parent, upStructures);
List<PrismObject<UserType>> authUserChild = authUserR(child, upStructures);
List<AuthorizationType> permParent = authPermsR(parent);
List<AuthorizationType> permChild = authPermsR(child);

//r1 -> parent
//r2 -> child
//r1 ≽ r2 = auth_users(r1) ⊆ auth_users(r2) ∧ auth_perms(r1) ⊇ auth_perms(r2).
return authUserChild.containsAll(authUserParent) && permParent.containsAll(permChild);
}

public List<PrismObject<RoleType>> jaccardGetRolesGroup(RoleMiningStructureList selectedData,
List<PrismObject<UserType>> jaccardUsersAnalysed,
Expand All @@ -27,7 +98,6 @@ public List<PrismObject<RoleType>> jaccardGetRolesGroup(RoleMiningStructureList
List<PrismObject<RoleType>> jaccardResultRoles = new ArrayList<>();
if (selectedData != null) {


List<ObjectReferenceType> rolesForCompare = new RoleMiningFilter().getRoleObjectReferenceTypes(selectedData.getUserObject().asObjectable());
for (PrismObject<UserType> userTypePrismObject : jaccardUsersAnalysed) {
rolesForCompare = roleIntersected(rolesForCompare,
Expand All @@ -45,7 +115,6 @@ public List<PrismObject<RoleType>> jaccardGetRolesGroup(RoleMiningStructureList
return jaccardResultRoles;
}


public List<PrismObject<UserType>> jaccardGetUserGroup(RoleMiningStructureList selectedData,
double jaccardThreshold,
List<PrismObject<UserType>> users) {
Expand All @@ -55,18 +124,14 @@ public List<PrismObject<UserType>> jaccardGetUserGroup(RoleMiningStructureList s
if (selectedData != null) {

for (int j = 0; j < selectedData.getObjectPartialResult().size(); j++) {
if (selectedData.getObjectPartialResult().get(j) > jaccardThreshold) {
if (selectedData.getObjectPartialResult().get(j) >= jaccardThreshold) {
jaccardUsersAnalysed.add(users.get(j));
}
}
}
return jaccardUsersAnalysed;
}





public double jaccardIndex(List<String> membersRoleA, List<String> membersRoleB, int minRolesCount) {
if (membersRoleA == null || membersRoleB == null) {
return 0.0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.stream.IntStream;

import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
Expand All @@ -27,17 +28,14 @@
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

public class RoleMiningDataGenerator {

int generateRolesGroupSize(int size) {
ProbabilityGenerator probabilityGenerator = new ProbabilityGenerator();
if (size > 5) {
if (size >= 8) {
probabilityGenerator.addGroupProbability(7, 0.2d);
probabilityGenerator.addGroupProbability(8, 0.3d);
probabilityGenerator.addGroupProbability(3, 0.4d);
Expand Down Expand Up @@ -164,13 +162,15 @@ public void assignRoles(List<PrismObject<UserType>> userList, List<PrismObject<R

if (getRoleObjectReferenceTypes(userTypePrismObject.asObjectable(), pageBase).size() == 0) {
int groupSize = generateRolesGroupSize(rolesList.size());
int startIndex = new Random().nextInt(rolesList.size() - 1 - groupSize);

int startIndex = new Random().nextInt(((rolesList.size() - groupSize)) + 1);

for (int i = 0; i < groupSize; i++) {
RoleType roleType = rolesList.get(startIndex + i).asObjectable();
UserType userType = userTypePrismObject.asObjectable();

try {

Task task = pageBase.createSimpleTask("Assign RoleType object");

ObjectDelta<UserType> objectDelta = pageBase.getPrismContext().deltaFor(UserType.class)
Expand All @@ -195,6 +195,59 @@ public void assignRoles(List<PrismObject<UserType>> userList, List<PrismObject<R
pageBase.showResult(result);
}

public void assignAuthorization(List<PrismObject<RoleType>> rolesList, PageBase pageBase) {
ArrayList<String> authorizationTemp = new ArrayList<>();
authorizationTemp.add("A");
authorizationTemp.add("B");
authorizationTemp.add("C");
authorizationTemp.add("D");
authorizationTemp.add("E");
authorizationTemp.add("F");
authorizationTemp.add("G");
authorizationTemp.add("H");
authorizationTemp.add("I");

OperationResult result = new OperationResult("Add authorization");

for (PrismObject<RoleType> role : rolesList) {
if (!role.getName().toString().equals("Superuser")) {
int authorizationCount = new RoleMiningFilter().getAuthorization(role.asObjectable()).size();


if (authorizationCount == 0) {
int groupSize = generateRolesGroupSize(authorizationTemp.size());


for (int i = 0; i < groupSize; i++) {
RoleType roleType = role.asObjectable();
AuthorizationType authorizationType = new AuthorizationType();
authorizationType.setName(authorizationTemp.get(i));

try {
Task task = pageBase.createSimpleTask("Add authorization");

ObjectDelta<RoleType> objectDelta = pageBase.getPrismContext().deltaFor(RoleType.class)
.item(RoleType.F_AUTHORIZATION).add(Containerable.asPrismContainerValue(authorizationType))
.asObjectDelta(roleType.getOid());

Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(objectDelta);
pageBase.getModelService().executeChanges(deltas, null, task, result);

} catch (Throwable e) {
System.out.println("something is wrong");
LOGGER.error("Error while adding authorization object {}, {}", roleType, e.getMessage(), e);
}

}
}
}
}

result.computeStatusComposite();
pageBase.showResult(result);
}


public void unassignRoles(PageBase pageBase, List<PrismObject<UserType>> userList) {
OperationResult result = new OperationResult("Unassign objects");

Expand Down

0 comments on commit dbf2d9f

Please sign in to comment.