From c97e31dc41dc8dd0049e1787088f79e8b8ef66e3 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 8 Jun 2023 16:01:34 +0200 Subject: [PATCH] Start implementing new governance authorizations The authorizations like #readOwnCertificationDecisions are now deprecated. To allow smooth transition, their up-to-date equivalents will be provided on the fly by AuthorizationMigrator class. Other changes: - Implemented "assignee" clause for certification cases and work items. - Changed the semantics of "assignee" clause to cover not only assignees of open work items, but all assignees of all work items. - MidPointPrincipal#getAuthorities now returns unmodifiable collection (because of safety reasons). --- .../evolveum/midpoint/init/DataImport.java | 16 +-- .../schema/selector/spec/AssigneeClause.java | 56 +++++---- .../schema/util/CertCampaignTypeUtil.java | 17 ++- .../schema/util/cases/CaseTypeUtil.java | 8 ++ .../TestAbstractAuthenticationEvaluator.java | 6 +- .../impl/CertificationManagerImpl.java | 12 +- .../test/TestRoleInducementCertification.java | 113 +++++++++--------- .../model/api/AccessCertificationService.java | 25 ++-- .../model/api/ModelAuthorizationAction.java | 20 +++- .../api/context/EvaluatedAssignment.java | 2 +- .../midpoint/model/impl/ModelBeans.java | 3 + .../impl/controller/ModelController.java | 42 ++++--- .../ModelInteractionServiceImpl.java | 16 --- .../model/impl/lens/AssignmentCollector.java | 10 -- .../lens/assignments/AssignmentEvaluator.java | 91 ++------------ .../assignments/EvaluatedAssignmentImpl.java | 13 +- .../assignments/TargetPayloadEvaluation.java | 31 +++-- .../lens/assignments/TargetsEvaluation.java | 4 +- .../projector/focus/AssignmentProcessor.java | 10 -- .../impl/security/AuthorizationMigrator.java | 79 ++++++++++++ .../impl/security/GuiProfileCompiler.java | 43 ++++--- .../GuiProfiledPrincipalManagerImpl.java | 12 +- .../lens/AbstractAssignmentEvaluatorTest.java | 9 -- .../impl/lens/TestAssignmentProcessor2.java | 10 -- .../intest/security/TestSecurityBasic.java | 16 +-- .../src/test/resources/security/case-4.xml | 2 +- .../test/AbstractModelIntegrationTest.java | 19 +-- .../repo/sqale/SqaleRepoBaseTest.java | 5 +- .../sqale/func/SimulationsBaselineTest.java | 13 +- .../midpoint/security/api/Authorization.java | 6 + .../security/api/MidPointPrincipal.java | 22 ++-- .../midpoint/security/api/SecurityUtil.java | 6 + .../AuthorizationLimitationsCollector.java | 6 +- .../impl/SecurityContextManagerImpl.java | 11 +- .../impl/MidPointPrincipalManagerMock.java | 6 +- 35 files changed, 405 insertions(+), 355 deletions(-) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/AuthorizationMigrator.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/init/DataImport.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/init/DataImport.java index ab66ea52493..c446b87c570 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/init/DataImport.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/init/DataImport.java @@ -8,7 +8,6 @@ import java.io.File; import java.util.Arrays; -import java.util.Collection; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; @@ -23,16 +22,18 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.security.api.Authorization; -import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.security.api.MidPointPrincipal; +import com.evolveum.midpoint.security.api.SecurityUtil; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.InternalsConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringNormalizerConfigurationType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; @@ -83,12 +84,7 @@ protected SecurityContext provideFakeSecurityContext() throws SchemaException { prismContext.adopt(userAdministrator); userAdministrator.setName(new PolyStringType(new PolyString("initAdmin", "initAdmin"))); MidPointPrincipal principal = new MidPointPrincipal(userAdministrator); - AuthorizationType superAutzType = new AuthorizationType(); - prismContext.adopt(superAutzType, RoleType.class, RoleType.F_AUTHORIZATION); - superAutzType.getAction().add(AuthorizationConstants.AUTZ_ALL_URL); - Authorization superAutz = new Authorization(superAutzType); - Collection authorities = principal.getAuthorities(); - authorities.add(superAutz); + principal.addAuthorization(SecurityUtil.createPrivilegedAuthorization()); Authentication authentication = new PreAuthenticatedAuthenticationToken(principal, null); securityContext.setAuthentication(authentication); return securityContext; diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/selector/spec/AssigneeClause.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/selector/spec/AssigneeClause.java index 51a90c38bb9..52f1dd21218 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/selector/spec/AssigneeClause.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/selector/spec/AssigneeClause.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.schema.selector.eval.ClauseFilteringContext; import com.evolveum.midpoint.schema.selector.eval.ClauseMatchingContext; import com.evolveum.midpoint.schema.selector.eval.SubjectedEvaluationContext.Delegation; +import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; import com.evolveum.midpoint.schema.util.cases.CaseTypeUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.*; @@ -50,18 +51,15 @@ public boolean matches(@NotNull PrismValue value, @NotNull ClauseMatchingContext traceNotApplicable(ctx, "has no real value"); return false; } - List> assignees = getAssignees(realValue, ctx); - if (assignees.isEmpty()) { - traceNotApplicable(ctx, "there are no assignees"); - return false; - } - ClauseMatchingContext nextCtx = ctx.next(Delegation.ASSIGNEE, "a", "assignee"); - for (PrismObject assignee : assignees) { - assert assignee != null; - // FIXME we need to provide enhanced "self" set here - if (selector.matches(assignee.getValue(), nextCtx)) { - traceApplicable(ctx, "assignee matches: %s", assignee); - return true; + var assignees = getAssignees(realValue, ctx); + if (!assignees.isEmpty()) { + ClauseMatchingContext nextCtx = ctx.next(Delegation.ASSIGNEE, "a", "assignee"); + for (PrismObject assignee : assignees) { + assert assignee != null; + if (selector.matches(assignee.getValue(), nextCtx)) { + traceApplicable(ctx, "assignee matches: %s", assignee); + return true; + } } } traceNotApplicable(ctx, "no assignee matches (assignees=%s)", assignees); @@ -71,13 +69,13 @@ public boolean matches(@NotNull PrismValue value, @NotNull ClauseMatchingContext @NotNull private List> getAssignees(Object object, @NotNull ClauseMatchingContext ctx) { List assigneeRefs; - if (object instanceof CaseType) { - CaseType aCase = (CaseType) object; - assigneeRefs = CaseTypeUtil.getAllCurrentAssignees(aCase); - } else if (object instanceof AbstractWorkItemType) { - assigneeRefs = ((AbstractWorkItemType) object).getAssigneeRef(); + if (object instanceof CaseType aCase) { + assigneeRefs = CaseTypeUtil.getAllAssignees(aCase); + } else if (object instanceof AccessCertificationCaseType aCase) { + assigneeRefs = CertCampaignTypeUtil.getAllAssignees(aCase); + } else if (object instanceof AbstractWorkItemType workItem) { + assigneeRefs = workItem.getAssigneeRef(); } else { - // TODO e.g. cert case assigneeRefs = List.of(); } @@ -99,8 +97,18 @@ public boolean applyFilter(@NotNull ClauseFilteringContext ctx) { PrismContext.get().queryFor(CaseType.class) .exists(CaseType.F_WORK_ITEM) .block() - .item(CaseWorkItemType.F_CLOSE_TIMESTAMP).isNull() - .and().item(CaseWorkItemType.F_ASSIGNEE_REF) + .item(CaseWorkItemType.F_ASSIGNEE_REF) + .ref(ctx.getSelfOidsArray(Delegation.ASSIGNEE)) + .endBlock() + .buildFilter()); + return true; + } else if (AccessCertificationCaseType.class.isAssignableFrom(type)) { + addConjunct( + ctx, + PrismContext.get().queryFor(AccessCertificationCaseType.class) + .exists(CaseType.F_WORK_ITEM) + .block() + .item(AccessCertificationWorkItemType.F_ASSIGNEE_REF) .ref(ctx.getSelfOidsArray(Delegation.ASSIGNEE)) .endBlock() .buildFilter()); @@ -113,6 +121,14 @@ public boolean applyFilter(@NotNull ClauseFilteringContext ctx) { .ref(ctx.getSelfOidsArray(Delegation.ASSIGNEE)) .buildFilter()); return true; + } else if (AccessCertificationWorkItemType.class.isAssignableFrom(type)) { + addConjunct( + ctx, + PrismContext.get().queryFor(AccessCertificationWorkItemType.class) + .item(AccessCertificationWorkItemType.F_ASSIGNEE_REF) + .ref(ctx.getSelfOidsArray(Delegation.ASSIGNEE)) + .buildFilter()); + return true; } else { traceNotApplicable(ctx, "when searching, this clause applies only to cases and work items"); return false; diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java index e6b3b1a7d3a..525678a0fe7 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java @@ -349,14 +349,17 @@ private static boolean hasNoResponse(AccessCertificationWorkItemType workItem) { } // TODO use this also from GUI and maybe notifications - @SuppressWarnings("unused") // used by certification cases report + @SuppressWarnings("unused") // used by certification cases report public static List getCurrentlyAssignedReviewers(PrismContainerValue pcv) { - AccessCertificationCaseType aCase = pcv.asContainerable(); + return getCurrentlyAssignedReviewers(pcv.asContainerable()); + } + + public @NotNull static List getCurrentlyAssignedReviewers(@NotNull AccessCertificationCaseType aCase) { List rv = new ArrayList<>(); for (AccessCertificationWorkItemType workItem : aCase.getWorkItem()) { for (ObjectReferenceType assigneeRef : workItem.getAssigneeRef()) { if (workItem.getCloseTimestamp() == null - && java.util.Objects.equals(workItem.getStageNumber(), aCase.getStageNumber())) { + && Objects.equals(workItem.getStageNumber(), aCase.getStageNumber())) { rv.add(assigneeRef); } } @@ -364,6 +367,14 @@ public static List getCurrentlyAssignedReviewers(PrismConta return rv; } + public @NotNull static List getAllAssignees(@NotNull AccessCertificationCaseType aCase) { + List rv = new ArrayList<>(); + for (AccessCertificationWorkItemType workItem : aCase.getWorkItem()) { + rv.addAll(workItem.getAssigneeRef()); + } + return rv; + } + @SuppressWarnings("unused") // used by certification cases report public static Date getLastReviewedOn(PrismContainerValue pcv) { return getReviewedTimestamp(pcv.asContainerable().getWorkItem()); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/cases/CaseTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/cases/CaseTypeUtil.java index a119370209c..573adf2e8f5 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/cases/CaseTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/cases/CaseTypeUtil.java @@ -94,6 +94,14 @@ public static List getAllCurrentAssignees(CaseType aCase) { return rv; } + public static List getAllAssignees(@NotNull CaseType aCase) { + List rv = new ArrayList<>(); + for (CaseWorkItemType workItem : aCase.getWorkItem()) { + rv.addAll(workItem.getAssigneeRef()); + } + return rv; + } + public static boolean approvalSchemaExists(CaseType aCase) { return aCase != null && aCase.getApprovalContext() != null diff --git a/model/authentication-impl/src/test/java/com/evolveum/midpoint/authentication/evaluator/TestAbstractAuthenticationEvaluator.java b/model/authentication-impl/src/test/java/com/evolveum/midpoint/authentication/evaluator/TestAbstractAuthenticationEvaluator.java index 548a2d982c9..cdb895d89c1 100644 --- a/model/authentication-impl/src/test/java/com/evolveum/midpoint/authentication/evaluator/TestAbstractAuthenticationEvaluator.java +++ b/model/authentication-impl/src/test/java/com/evolveum/midpoint/authentication/evaluator/TestAbstractAuthenticationEvaluator.java @@ -1205,9 +1205,9 @@ private void addFakeAuthorization(MidPointPrincipal principal) { return; } if (principal.getAuthorities().isEmpty()) { - AuthorizationType authorizationBean = new AuthorizationType(); - authorizationBean.getAction().add("FAKE"); - principal.getAuthorities().add(new Authorization(authorizationBean)); + principal.addAuthorization( + new Authorization( + new AuthorizationType().action("FAKE"))); } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java index b2609e605c2..b3d64928473 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java @@ -336,9 +336,15 @@ public void startRemediation(String campaignOid, Task task, OperationResult pare } @Override - public List searchOpenWorkItems(ObjectQuery baseWorkItemsQuery, boolean notDecidedOnly, - boolean allItems, Collection> options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + public List searchOpenWorkItems( + ObjectQuery baseWorkItemsQuery, + boolean notDecidedOnly, + boolean allItems, + Collection> options, + Task task, + OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, SecurityViolationException, ExpressionEvaluationException, + CommunicationException, ConfigurationException { OperationResult result = parentResult.createSubresult(OPERATION_SEARCH_OPEN_WORK_ITEMS); try { diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestRoleInducementCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestRoleInducementCertification.java index 2de2535e2f0..e563ab49d41 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestRoleInducementCertification.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestRoleInducementCertification.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.certification.test; +import com.evolveum.midpoint.cases.api.util.QueryUtils; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.constants.SchemaConstants; @@ -15,13 +16,16 @@ import com.evolveum.midpoint.security.api.SecurityUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; import java.util.*; +import java.util.function.Consumer; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractWorkItemType.F_CLOSE_TIMESTAMP; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.CLOSED; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REMEDIATION; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.*; @@ -211,81 +215,76 @@ public void test030SearchAllCases() throws Exception { public void test050SearchDecisionsAdministrator() throws Exception { // GIVEN login(userAdministrator.asPrismObject()); + + // Expected cases - phase 1: + // + // COO-Dummy: administrator + // COO-DummyBlack: administrator + // COO-Superuser: administrator + + executeWorkItemsSearchTest(workItems -> { + display("workItems", workItems); + assertEquals("Wrong number of certification work items", 3, workItems.size()); + checkWorkItemSanity(workItems, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo); + checkWorkItemSanity(workItems, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo); + checkWorkItemSanity(workItems, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo); + }); + } + + private void executeWorkItemsSearchTest(Consumer> workItemsChecker) + throws CommonException { Task task = getTestTask(); OperationResult result = task.getResult(); - // WHEN - when(); + when("searching for work items via certification service"); List workItems = - queryHelper.searchOpenWorkItems(null, SecurityUtil.getPrincipal(), false, null, result); - - /* Expected cases - phase 1: - - COO-Dummy: administrator - COO-DummyBlack: administrator - COO-Superuser: administrator - */ - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - display("workItems", workItems); - assertEquals("Wrong number of certification work items", 3, workItems.size()); - checkWorkItemSanity(workItems, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo); - checkWorkItemSanity(workItems, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo); - checkWorkItemSanity(workItems, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo); + certificationService.searchOpenWorkItems(null, false, null, task, result); + + then("result is OK"); + assertSuccess(result); + workItemsChecker.accept(workItems); + + when("searching for work items via model API"); + List workItems2 = + modelService.searchContainers( + AccessCertificationWorkItemType.class, + QueryUtils.filterForCertificationAssignees( + prismContext.queryFor(AccessCertificationWorkItemType.class), + SecurityUtil.getPrincipalRequired()) + .and().item(F_CLOSE_TIMESTAMP).isNull() + .build(), + null, task, result); + + then("result is OK"); + result.recomputeStatus(); + assertSuccess(result); + workItemsChecker.accept(workItems2); } @Test public void test051SearchDecisionsElaine() throws Exception { - // GIVEN login(userElaine.asPrismObject()); - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - List workItems = - queryHelper.searchOpenWorkItems(null, SecurityUtil.getPrincipal(), false, null, result); - - /* Expected cases - phase 1: - CEO-Dummy: elaine - */ - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); + // Expected cases - phase 1: + // + // CEO-Dummy: elaine - display("caseList", workItems); - assertEquals("Wrong number of work items", 1, workItems.size()); - checkWorkItemSanity(workItems, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo); + executeWorkItemsSearchTest(workItems -> { + display("workItems", workItems); + assertEquals("Wrong number of work items", 1, workItems.size()); + checkWorkItemSanity(workItems, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo); }); } @Test public void test052SearchDecisionsJack() throws Exception { - // GIVEN login(userJack.asPrismObject()); - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - List workItems = - queryHelper.searchOpenWorkItems(null, SecurityUtil.getPrincipal(), false, null, result); - /* Expected cases - phase 1: NONE */ - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); + // Expected cases - phase 1: NONE - display("workItems", workItems); - assertEquals("Wrong number of certification work items", 0, workItems.size()); + executeWorkItemsSearchTest(workItems -> { + display("workItems", workItems); + assertEquals("Wrong number of certification work items", 0, workItems.size()); + }); } /* diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/AccessCertificationService.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/AccessCertificationService.java index c6a3ca0146c..b3ce9dc0d16 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/AccessCertificationService.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/AccessCertificationService.java @@ -123,13 +123,24 @@ AccessCertificationCampaignType createCampaign(String definitionOid, Task task, * @return A list of relevant certification cases. * */ - List searchOpenWorkItems(ObjectQuery baseWorkItemsQuery, boolean notDecidedOnly, boolean allItems, - Collection> options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException, ExpressionEvaluationException; - - default List searchOpenWorkItems(ObjectQuery baseWorkItemsQuery, boolean notDecidedOnly, - Collection> options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException, ExpressionEvaluationException { + List searchOpenWorkItems( + ObjectQuery baseWorkItemsQuery, + boolean notDecidedOnly, + boolean allItems, + Collection> options, + Task task, + OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, + CommunicationException, ExpressionEvaluationException; + + default List searchOpenWorkItems( + ObjectQuery baseWorkItemsQuery, + boolean notDecidedOnly, + Collection> options, + Task task, + OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, + CommunicationException, ExpressionEvaluationException { return searchOpenWorkItems(baseWorkItemsQuery, notDecidedOnly, false, options, task, parentResult); } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelAuthorizationAction.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelAuthorizationAction.java index d0d98eb2480..cf5b808afaf 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelAuthorizationAction.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelAuthorizationAction.java @@ -56,19 +56,37 @@ public enum ModelAuthorizationAction implements DisplayableValue { READ_THREADS("readThreads", "Read threads", "READ_THREADS_HELP"), + /** Ability to complete a work item (case- or certification- related). */ + COMPLETE_WORK_ITEM("completeWorkItem", "Complete work item", "COMPLETE_WORK_ITEM_HELP"), + + /** Ability to delegate a work item (case- or certification- related). */ + DELEGATE_WORK_ITEM("delegateWorkItem", "Delegate work item", "DELEGATE_WORK_ITEM_HELP"), + CREATE_CERTIFICATION_CAMPAIGN("createCertificationCampaign", "Create a certification campaign", "CREATE_CERTIFICATION_CAMPAIGN_HELP"), OPEN_CERTIFICATION_CAMPAIGN_REVIEW_STAGE("openCertificationCampaignReviewStage", "Open access certification campaign review stage", "OPEN_CERTIFICATION_CAMPAIGN_REVIEW_STAGE_HELP"), CLOSE_CERTIFICATION_CAMPAIGN_REVIEW_STAGE("closeCertificationCampaignReviewStage", "Close access certification campaign review stage", "CLOSE_CERTIFICATION_CAMPAIGN_REVIEW_STAGE_HELP"), START_CERTIFICATION_REMEDIATION("startCertificationRemediation", "Start certification campaign results remediation", "START_CERTIFICATION_REMEDIATION_HELP"), CLOSE_CERTIFICATION_CAMPAIGN("closeCertificationCampaign", "Close certification campaign", "CLOSE_CERTIFICATION_CAMPAIGN_HELP"), REITERATE_CERTIFICATION_CAMPAIGN("reiterateCertificationCampaign", "Reiterate certification campaign", "REITERATE_CERTIFICATION_CAMPAIGN_HELP"), + + @Deprecated // use READ instead READ_OWN_CERTIFICATION_DECISIONS("readOwnCertificationDecisions", "Read own access certification decisions", "READ_OWN_CERTIFICATION_DECISIONS_HELP"), + + @Deprecated // use DELEGATE_WORK_ITEM instead RECORD_CERTIFICATION_DECISION("recordCertificationDecision", "Record access certification decision", "RECORD_CERTIFICATION_DECISION_HELP"), + @Deprecated // use COMPLETE_WORK_ITEM instead COMPLETE_ALL_WORK_ITEMS("completeAllWorkItems", "Complete all work items", "COMPLETE_ALL_WORK_ITEMS_HELP"), + + @Deprecated // use DELEGATE_WORK_ITEM instead DELEGATE_ALL_WORK_ITEMS("delegateAllWorkItems", "Delegate all work items", "DELEGATE_ALL_WORK_ITEMS_HELP"), + + @Deprecated // use DELEGATE_WORK_ITEM instead DELEGATE_OWN_WORK_ITEMS("delegateOwnWorkItems", "Delegate own work items", "DELEGATE_OWN_WORK_ITEMS_HELP"), - READ_ALL_WORK_ITEMS("readAllWorkItems", "Read all work items", "READ_ALL_WORK_ITEMS_HELP"), // currently not implemented seriously + + @Deprecated // use READ instead (actually, this one was not used at all) + READ_ALL_WORK_ITEMS("readAllWorkItems", "Read all work items", "READ_ALL_WORK_ITEMS_HELP"), + STOP_APPROVAL_PROCESS_INSTANCE("stopApprovalProcessInstance", "Stop approval process instance", "STOP_APPROVAL_PROCESS_INSTANCE_HELP"), CLEANUP_PROCESS_INSTANCES("cleanupProcessInstances", "Cleanup process instances", "CLEANUP_PROCESS_INSTANCES_HELP"), CANCEL_CASE("cancelCase", "Cancel case", "CANCEL_CASE_HELP"), diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java index 401b5fb8263..90f5110fec8 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java @@ -43,7 +43,7 @@ default AssignmentType getAssignmentType(boolean old) { Long getAssignmentId(); - Collection getAuthorizations(); + @NotNull Collection getAuthorizations(); Collection getAdminGuiConfigurations(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelBeans.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelBeans.java index de2d8eeeeff..6657013dc7a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelBeans.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelBeans.java @@ -7,6 +7,8 @@ package com.evolveum.midpoint.model.impl; +import com.evolveum.midpoint.model.impl.security.AuthorizationMigrator; + import jakarta.annotation.PostConstruct; import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyRuleProcessor; @@ -142,4 +144,5 @@ public static ModelBeans get() { @Autowired public ModelController modelController; @Autowired public SimulationResultManagerImpl simulationResultManager; @Autowired public MarkManager markManager; + @Autowired public AuthorizationMigrator authorizationMigrator; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java index 95dde32fd33..3771ee4dab8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java @@ -642,13 +642,9 @@ private void applyProvisioningDefinition( } private class ContainerSearchLikeOpContext { - final boolean isCertCase; - final boolean isCaseMgmtWorkItem; - final boolean isOperationExecution; - final boolean isProcessedObject; final ObjectManager manager; final ObjectQuery securityRestrictedQuery; - private final boolean isAssignment; + private final boolean skipSecurityPostProcessing; // TODO: task and result here are ugly and probably wrong ContainerSearchLikeOpContext( @@ -656,19 +652,24 @@ private class ContainerSearchLikeOpContext { throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException { - isCertCase = AccessCertificationCaseType.class.equals(type); - isCaseMgmtWorkItem = CaseWorkItemType.class.equals(type); - isOperationExecution = OperationExecutionType.class.equals(type); - isAssignment = AssignmentType.class.equals(type); - isProcessedObject = SimulationResultProcessedObjectType.class.equals(type); - - if (!isCertCase && !isCaseMgmtWorkItem && !isOperationExecution && !isAssignment && !isProcessedObject) { - throw new UnsupportedOperationException("searchContainers/countContainers methods are currently supported only " - + "for AccessCertificationCaseType, CaseWorkItemType, SimulationResultProcessedObjectType and AssignmentType classes"); + var isAssignment = AssignmentType.class.equals(type); + var isProcessedObject = SimulationResultProcessedObjectType.class.equals(type); + + if (!AccessCertificationCaseType.class.equals(type) + && !AccessCertificationWorkItemType.class.equals(type) + && !CaseWorkItemType.class.equals(type) + && !OperationExecutionType.class.equals(type) + && !isAssignment + && !isProcessedObject) { + throw new UnsupportedOperationException( + "searchContainers/countContainers methods are currently supported only for AccessCertificationCaseType," + + " AccessCertificationWorkItemType, CaseWorkItemType, OperationExecutionType, AssignmentType," + + " and SimulationResultProcessedObjectType objects"); } manager = ObjectManager.REPOSITORY; securityRestrictedQuery = preProcessQuerySecurity(type, origQuery, options.getRootOptions(), task, result); + skipSecurityPostProcessing = isAssignment || isProcessedObject; } } @@ -737,8 +738,8 @@ public SearchResultList searchContainers( } finally { exitModelMethod(); } - if (ctx.isAssignment) { - LOGGER.debug("Assignments do not have security constraints applied yet"); + if (ctx.skipSecurityPostProcessing) { + LOGGER.debug("Objects of type '{}' do not have security constraints applied yet", type.getSimpleName()); } else { schemaTransformer.applySchemasAndSecurityToContainerValues(list, parsedOptions, task, result); } @@ -2217,8 +2218,13 @@ public void recordDecision(String campaignOid, long caseId, long workItemId, Acc } @Override - public List searchOpenWorkItems(ObjectQuery baseWorkItemsQuery, boolean notDecidedOnly, - boolean allItems, Collection> rawOptions, Task task, OperationResult parentResult) + public List searchOpenWorkItems( + ObjectQuery baseWorkItemsQuery, + boolean notDecidedOnly, + boolean allItems, + Collection> rawOptions, + Task task, + OperationResult parentResult) throws ObjectNotFoundException, SchemaException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { Collection> options = diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java index 1eae4a6bcdb..165ef76c20b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java @@ -49,7 +49,6 @@ import com.evolveum.midpoint.model.api.visualizer.ModelContextVisualization; import com.evolveum.midpoint.model.api.visualizer.Visualization; import com.evolveum.midpoint.model.common.archetypes.ArchetypeManager; -import com.evolveum.midpoint.model.common.mapping.MappingFactory; import com.evolveum.midpoint.model.common.mapping.metadata.MetadataItemProcessingSpecImpl; import com.evolveum.midpoint.model.common.stringpolicy.*; import com.evolveum.midpoint.model.impl.ModelBeans; @@ -58,8 +57,6 @@ import com.evolveum.midpoint.model.impl.lens.*; import com.evolveum.midpoint.model.impl.lens.assignments.AssignmentEvaluator; import com.evolveum.midpoint.model.impl.lens.projector.AssignmentOrigin; -import com.evolveum.midpoint.model.impl.lens.projector.loader.ContextLoader; -import com.evolveum.midpoint.model.impl.lens.projector.mappings.MappingEvaluator; import com.evolveum.midpoint.model.impl.schema.transform.TransformableContainerDefinition; import com.evolveum.midpoint.model.impl.schema.transform.TransformableObjectDefinition; import com.evolveum.midpoint.model.impl.schema.transform.TransformableReferenceDefinition; @@ -152,8 +149,6 @@ public class ModelInteractionServiceImpl implements ModelInteractionService { @Autowired private ModelService modelService; @Autowired private ModelCrudService modelCrudService; @Autowired private SecurityHelper securityHelper; - @Autowired private MappingFactory mappingFactory; - @Autowired private MappingEvaluator mappingEvaluator; @Autowired private ActivationComputer activationComputer; @Autowired private Clock clock; @Autowired private GuiProfiledPrincipalManager guiProfiledPrincipalManager; @@ -163,7 +158,6 @@ public class ModelInteractionServiceImpl implements ModelInteractionService { @Autowired private CollectionProcessor collectionProcessor; @Autowired private CacheConfigurationManager cacheConfigurationManager; @Autowired private ClusterwideUserSessionManager clusterwideUserSessionManager; - @Autowired private ContextLoader contextLoader; @Autowired private ModelAuditService modelAuditService; @Autowired private TaskManager taskManager; @Autowired private SimulationResultManager simulationResultManager; @@ -1575,16 +1569,6 @@ private boolean determineDeputyValidity(PrismObject potentialDeputy, L new AssignmentEvaluator.Builder() .referenceResolver(referenceResolver) .focusOdo(new ObjectDeltaObject<>(potentialDeputy, null, potentialDeputy, potentialDeputy.getDefinition())) - .channel(null) - .modelBeans(modelBeans) - .objectResolver(objectResolver) - .systemObjectCache(systemObjectCache) - .relationRegistry(relationRegistry) - .prismContext(prismContext) - .mappingFactory(mappingFactory) - .mappingEvaluator(mappingEvaluator) - .contextLoader(contextLoader) - .activationComputer(activationComputer) .now(clock.currentTimeXMLGregorianCalendar()) .loginMode(true) // We do not have real lens context here. But the push methods in ModelExpressionThreadLocalHolder diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java index fcee09fe523..6fe72ee57e1 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java @@ -92,16 +92,6 @@ public Collection collect new AssignmentEvaluator.Builder() .referenceResolver(referenceResolver) .focusOdo(new ObjectDeltaObject<>(focus, null, focus, focus.getDefinition())) - .channel(null) - .modelBeans(modelBeans) - .objectResolver(objectResolver) - .systemObjectCache(systemObjectCache) - .relationRegistry(relationRegistry) - .prismContext(prismContext) - .mappingFactory(mappingFactory) - .mappingEvaluator(mappingEvaluator) - .contextLoader(contextLoader) - .activationComputer(activationComputer) .now(clock.currentTimeXMLGregorianCalendar()) // We do need only authorizations + gui config. Therefore we not need to evaluate // constructions and the like, so switching it off makes the evaluation run faster. diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/AssignmentEvaluator.java index 22bfba22726..5aae8f60f9c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/AssignmentEvaluator.java @@ -13,14 +13,12 @@ import com.evolveum.midpoint.common.ActivationComputer; import com.evolveum.midpoint.model.api.context.EvaluationOrder; import com.evolveum.midpoint.model.api.util.ReferenceResolver; -import com.evolveum.midpoint.repo.common.SystemObjectCache; import com.evolveum.midpoint.model.common.mapping.MappingFactory; import com.evolveum.midpoint.model.impl.ModelBeans; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.model.impl.lens.LensFocusContext; import com.evolveum.midpoint.model.impl.lens.LensUtil; import com.evolveum.midpoint.model.impl.lens.projector.AssignmentOrigin; -import com.evolveum.midpoint.model.impl.lens.projector.loader.ContextLoader; import com.evolveum.midpoint.model.impl.lens.projector.mappings.MappingEvaluator; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -31,10 +29,10 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.util.ItemDeltaItem; import com.evolveum.midpoint.prism.util.ObjectDeltaObject; -import com.evolveum.midpoint.repo.common.ObjectResolver; -import com.evolveum.midpoint.schema.expression.VariablesMap; import com.evolveum.midpoint.schema.RelationRegistry; +import com.evolveum.midpoint.schema.SchemaService; import com.evolveum.midpoint.schema.constants.ExpressionConstants; +import com.evolveum.midpoint.schema.expression.VariablesMap; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.*; @@ -65,7 +63,6 @@ public class AssignmentEvaluator { final ObjectDeltaObject focusOdoAbsolute; final ObjectDeltaObject focusOdoRelative; final LifecycleStateModelType focusStateModel; - final String channel; final XMLGregorianCalendar now; final PrismObject systemConfiguration; /** @@ -76,16 +73,12 @@ public class AssignmentEvaluator { // Spring beans and bean-like objects used - final ModelBeans beans; final ReferenceResolver referenceResolver; - final ObjectResolver objectResolver; - final SystemObjectCache systemObjectCache; - final RelationRegistry relationRegistry; - final PrismContext prismContext; - final MappingFactory mappingFactory; - final ActivationComputer activationComputer; - final MappingEvaluator mappingEvaluator; - final ContextLoader contextLoader; + final RelationRegistry relationRegistry = SchemaService.get().relationRegistry(); + final PrismContext prismContext = PrismContext.get(); + final MappingFactory mappingFactory = ModelBeans.get().mappingFactory; + final ActivationComputer activationComputer = ModelBeans.get().activationComputer; + final MappingEvaluator mappingEvaluator = ModelBeans.get().mappingEvaluator; // Evaluation state @@ -97,19 +90,9 @@ private AssignmentEvaluator(Builder builder) { focusOdoAbsolute = builder.focusOdoAbsolute; focusOdoRelative = builder.focusOdoRelative; lensContext = builder.lensContext; - channel = builder.channel; - beans = builder.modelBeans; - objectResolver = builder.objectResolver; - systemObjectCache = builder.systemObjectCache; - relationRegistry = builder.relationRegistry; - prismContext = builder.prismContext; - mappingFactory = builder.mappingFactory; - activationComputer = builder.activationComputer; now = builder.now; - contextLoader = builder.contextLoader; loginMode = builder.loginMode; systemConfiguration = builder.systemConfiguration; - mappingEvaluator = builder.mappingEvaluator; evaluatedAssignmentTargetCache = new EvaluatedAssignmentTargetCache(); memberOfEngine = new MemberOfEngine(); @@ -261,19 +244,9 @@ public static final class Builder { private ObjectDeltaObject focusOdoAbsolute; private ObjectDeltaObject focusOdoRelative; private LensContext lensContext; - private String channel; - private ModelBeans modelBeans; - private ObjectResolver objectResolver; - private SystemObjectCache systemObjectCache; - private RelationRegistry relationRegistry; - private PrismContext prismContext; - private MappingFactory mappingFactory; - private ActivationComputer activationComputer; private XMLGregorianCalendar now; - private ContextLoader contextLoader; private boolean loginMode = false; private PrismObject systemConfiguration; - private MappingEvaluator mappingEvaluator; public Builder() { } @@ -304,56 +277,11 @@ public Builder lensContext(LensContext val) { return this; } - public Builder channel(String val) { - channel = val; - return this; - } - - public Builder objectResolver(ObjectResolver val) { - objectResolver = val; - return this; - } - - public Builder modelBeans(ModelBeans val) { - modelBeans = val; - return this; - } - - public Builder systemObjectCache(SystemObjectCache val) { - systemObjectCache = val; - return this; - } - - public Builder relationRegistry(RelationRegistry val) { - relationRegistry = val; - return this; - } - - public Builder prismContext(PrismContext val) { - prismContext = val; - return this; - } - - public Builder mappingFactory(MappingFactory val) { - mappingFactory = val; - return this; - } - - public Builder activationComputer(ActivationComputer val) { - activationComputer = val; - return this; - } - public Builder now(XMLGregorianCalendar val) { now = val; return this; } - public Builder contextLoader(ContextLoader val) { - contextLoader = val; - return this; - } - public Builder loginMode(boolean val) { loginMode = val; return this; @@ -364,11 +292,6 @@ public Builder systemConfiguration(PrismObject val) return this; } - public Builder mappingEvaluator(MappingEvaluator val) { - mappingEvaluator = val; - return this; - } - public AssignmentEvaluator build() { return new AssignmentEvaluator<>(this); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/EvaluatedAssignmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/EvaluatedAssignmentImpl.java index fff7e44f140..aebf41dc9a0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/EvaluatedAssignmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/EvaluatedAssignmentImpl.java @@ -312,14 +312,15 @@ void setTenantOid(String tenantOid) { this.tenantOid = tenantOid; } - @NotNull @Override - public Collection getAuthorizations() { + public @NotNull Collection getAuthorizations() { return authorizations; } - void addAuthorization(Authorization authorization) { - authorizations.add(authorization); + void addAuthorization(@NotNull Authorization authorization) { + if (!authorizations.contains(authorization)) { + authorizations.add(authorization); + } } @Override @@ -329,7 +330,9 @@ public Collection getAdminGuiConfigurations() { } void addAdminGuiConfiguration(AdminGuiConfigurationType adminGuiConfiguration) { - adminGuiConfigurations.add(adminGuiConfiguration); + if (!adminGuiConfigurations.contains(adminGuiConfiguration)) { + adminGuiConfigurations.add(adminGuiConfiguration); + } } @Override diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetPayloadEvaluation.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetPayloadEvaluation.java index 4bf9a2c98c7..493197a2f3d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetPayloadEvaluation.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetPayloadEvaluation.java @@ -7,6 +7,8 @@ package com.evolveum.midpoint.model.impl.lens.assignments; +import com.evolveum.midpoint.model.impl.ModelBeans; + import org.jetbrains.annotations.NotNull; import com.evolveum.midpoint.security.api.Authorization; @@ -39,32 +41,27 @@ public void evaluate() { assert targetOverallConditionState.isNotAllFalse(); checkIfAlreadyEvaluated(); - ObjectType target = segment.getTarget(); - if (target instanceof AbstractRoleType) { + if (segment.getTarget() instanceof AbstractRoleType target) { if (!segment.isMatchingOrder) { - LOGGER.trace("Not collecting payload from target of {} as it is of not matching order: {}", segment, segment.getEvaluationOrder()); + LOGGER.trace("Not collecting payload from target of {} as it is of not matching order: {}", + segment, segment.getEvaluationOrder()); } else if (targetOverallConditionState.isNewFalse()) { - LOGGER.trace("Not collecting payload from target of {} as the target relativity mode is not non-negative: {}", segment, targetOverallConditionState); + LOGGER.trace("Not collecting payload from target of {} as the target relativity mode is not non-negative: {}", + segment, targetOverallConditionState); } else { - for (AuthorizationType authorizationBean : ((AbstractRoleType) target).getAuthorization()) { - Authorization authorization = createAuthorization(authorizationBean, target.toString()); - if (!ctx.evalAssignment.getAuthorizations().contains(authorization)) { - ctx.evalAssignment.addAuthorization(authorization); + for (AuthorizationType authorizationBean : target.getAuthorization()) { + var migratedBeans = ModelBeans.get().authorizationMigrator.migrate(authorizationBean); + for (AuthorizationType migratedBean : migratedBeans) { + ctx.evalAssignment.addAuthorization( + Authorization.create(migratedBean, target.toString())); } } - AdminGuiConfigurationType adminGuiConfiguration = ((AbstractRoleType) target).getAdminGuiConfiguration(); + AdminGuiConfigurationType adminGuiConfiguration = target.getAdminGuiConfiguration(); ctx.evalAssignment.addAdminGuiDependency(target.getOid()); - if (adminGuiConfiguration != null && - !ctx.evalAssignment.getAdminGuiConfigurations().contains(adminGuiConfiguration)) { + if (adminGuiConfiguration != null) { ctx.evalAssignment.addAdminGuiConfiguration(adminGuiConfiguration); } } } } - - private Authorization createAuthorization(@NotNull AuthorizationType authorizationBean, String sourceDesc) { - Authorization authorization = new Authorization(authorizationBean); - authorization.setSourceDescription(sourceDesc); - return authorization; - } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetsEvaluation.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetsEvaluation.java index 6503ce050b4..44d2a4ef46e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetsEvaluation.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/assignments/TargetsEvaluation.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.model.api.util.ReferenceResolver; import com.evolveum.midpoint.model.common.expression.ModelExpressionEnvironment; +import com.evolveum.midpoint.model.impl.ModelBeans; import com.evolveum.midpoint.repo.common.expression.ExpressionEnvironmentThreadLocalHolder; import com.evolveum.midpoint.util.MiscUtil; @@ -252,7 +253,8 @@ private ReferenceResolver.FilterEvaluator createFilterEvaluator(AssignmentPathSe @NotNull private VariablesMap createVariables(AssignmentPathSegmentImpl segment, EvaluationContext ctx, OperationResult result) throws SchemaException { - PrismObject systemConfiguration = ctx.ae.systemObjectCache.getSystemConfiguration(result); + PrismObject systemConfiguration = + ModelBeans.get().systemObjectCache.getSystemConfiguration(result); VariablesMap variables = ModelImplUtils.getDefaultVariablesMap( segment.source, null, null, asObjectable(systemConfiguration)); variables.put(ExpressionConstants.VAR_SOURCE, segment.source, ObjectType.class); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java index b6302ef1ff1..b9559035b8b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java @@ -1312,16 +1312,6 @@ private AssignmentEvaluator createAssignment .focusOdoAbsolute(context.getFocusContext().getObjectDeltaObjectAbsolute()) .focusOdoRelative(context.getFocusContext().getObjectDeltaObjectRelative()) .lensContext(context) - .channel(context.getChannel()) - .modelBeans(beans) - .objectResolver(objectResolver) - .systemObjectCache(systemObjectCache) - .relationRegistry(relationRegistry) - .prismContext(prismContext) - .mappingFactory(mappingFactory) - .mappingEvaluator(mappingEvaluator) - .contextLoader(contextLoader) - .activationComputer(activationComputer) .now(now) .systemConfiguration(context.getSystemConfiguration()) .build(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/AuthorizationMigrator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/AuthorizationMigrator.java new file mode 100644 index 00000000000..261c2370d42 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/AuthorizationMigrator.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010-2023 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.model.impl.security; + +import com.evolveum.midpoint.model.api.ModelAuthorizationAction; +import com.evolveum.midpoint.prism.util.CloneUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Migrates authorizations from a legacy format into a new one. + * + * For example, when going from 4.4/4.7 to 4.8, `#readOwnCertificationDecisions` + * is replaced by `#read` on `AccessCertificationWorkItemType` objects. + */ +@Component +public class AuthorizationMigrator { + + @SuppressWarnings("deprecation") + public @NotNull Collection migrate(@NotNull AuthorizationType original) { + List migrated = new ArrayList<>(); + migrated.add(original); + + var origName = original.getName(); + var origDecision = original.getDecision(); + var origPhase = original.getPhase(); + var limitations = original.getLimitations(); + + List actions = original.getAction(); + if (actions.contains(ModelAuthorizationAction.READ_OWN_CERTIFICATION_DECISIONS.getUrl())) { + migrated.add(new AuthorizationType() + .decision(origDecision) + .phase(origPhase) + .name(newName(origName)) + .action(ModelAuthorizationAction.READ.getUrl()) + .limitations(CloneUtil.clone(limitations)) + .object(new AuthorizationObjectSelectorType() + .type(AccessCertificationWorkItemType.COMPLEX_TYPE) + .assignee(self()))); + if (origDecision != AuthorizationDecisionType.DENY) { + migrated.add(new AuthorizationType() + .phase(origPhase) + .name(newName(origName)) + .action(ModelAuthorizationAction.READ.getUrl()) + .limitations(CloneUtil.clone(limitations)) + .object(new AuthorizationObjectSelectorType() + .type(AccessCertificationCaseType.COMPLEX_TYPE) + .assignee(self())) + .exceptItem(AccessCertificationCaseType.F_WORK_ITEM.toBean())); + } + } + + return migrated; + } + + private SubjectedObjectSelectorType self() { + return new SubjectedObjectSelectorType() + .special(SpecialObjectSpecificationType.SELF); + } + + private String newName(String name) { + if (name == null) { + return "migrated"; + } else { + return name + " (migrated)"; + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfileCompiler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfileCompiler.java index 119cf6f701c..4f8a70385ae 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfileCompiler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfileCompiler.java @@ -12,11 +12,13 @@ import com.evolveum.midpoint.model.impl.util.ModelImplUtils; +import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -47,6 +49,8 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import static com.evolveum.midpoint.util.MiscUtil.emptyIfNull; + /** * Compiles user interface profile for a particular user. The profile contains essential information needed to efficiently render * user interface pages for specified user. @@ -80,7 +84,12 @@ public class GuiProfileCompiler { private static final String STATISTIC_WIDGET_PANEL_TYPE = "statisticWidget"; - public void compileFocusProfile(GuiProfiledPrincipal principal, PrismObject systemConfiguration, AuthorizationTransformer authorizationTransformer, Task task, OperationResult result) + void compileFocusProfile( + GuiProfiledPrincipal principal, + PrismObject systemConfiguration, + AuthorizationTransformer authorizationTransformer, + Task task, + OperationResult result) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, ObjectNotFoundException { LOGGER.debug("Going to compile focus profile for {}", principal.getName()); @@ -105,21 +114,28 @@ public void compileFocusProfile(GuiProfiledPrincipal principal, PrismObject adminGuiConfigurations, Set consideredOids, GuiProfiledPrincipal principal, AuthorizationTransformer authorizationTransformer, Task task, OperationResult result) throws SchemaException { + private void collect( + List adminGuiConfigurations, + Set consideredOids, + GuiProfiledPrincipal principal, + AuthorizationTransformer authorizationTransformer, + Task task, + OperationResult result) throws SchemaException { FocusType focusType = principal.getFocus(); - Collection evaluatedAssignments = assignmentCollector.collect(focusType.asPrismObject(), true, task, result); - Collection authorizations = principal.getAuthorities(); + Collection evaluatedAssignments = + assignmentCollector.collect(focusType.asPrismObject(), true, task, result); for (EvaluatedAssignment assignment : evaluatedAssignments) { if (assignment.isValid()) { // TODO: Should we add also invalid assignments? consideredOids.addAll(assignment.getAdminGuiDependencies()); - addAuthorizations(authorizations, assignment.getAuthorizations(), authorizationTransformer); + addAuthorizations(principal, assignment.getAuthorizations(), authorizationTransformer); adminGuiConfigurations.addAll(assignment.getAdminGuiConfigurations()); } for (EvaluatedAssignmentTarget target : assignment.getRoles().getNonNegativeValues()) { // MID-6403 - if (target.isValid() && target.getTarget().asObjectable() instanceof UserType + if (target.isValid() + && target.getTarget().asObjectable() instanceof UserType && DeputyUtils.isDelegationPath(target.getAssignmentPath(), relationRegistry)) { principal.addDelegatorWithOtherPrivilegesLimitations( new DelegatorWithOtherPrivilegesLimitations( @@ -137,17 +153,16 @@ private void collect(List adminGuiConfigurations, Set } } - private void addAuthorizations(Collection targetCollection, Collection sourceCollection, AuthorizationTransformer authorizationTransformer) { - if (sourceCollection == null) { - return; - } + private void addAuthorizations( + @NotNull MidPointPrincipal principal, + @NotNull Collection sourceCollection, + @Nullable AuthorizationTransformer authorizationTransformer) { for (Authorization autz : sourceCollection) { if (authorizationTransformer == null) { - targetCollection.add(autz.clone()); + principal.addAuthorization(autz.clone()); } else { - Collection transformedAutzs = authorizationTransformer.transform(autz); - if (transformedAutzs != null) { - targetCollection.addAll(transformedAutzs); + for (Authorization transformedAutz : emptyIfNull(authorizationTransformer.transform(autz))) { + principal.addAuthorization(transformedAutz); } } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfiledPrincipalManagerImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfiledPrincipalManagerImpl.java index 95ffbab3b5c..f5535fa42f7 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfiledPrincipalManagerImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/GuiProfiledPrincipalManagerImpl.java @@ -179,7 +179,10 @@ public GuiProfiledPrincipal getPrincipal(PrismObject focus) } @Override - public GuiProfiledPrincipal getPrincipal(PrismObject focus, AuthorizationTransformer authorizationTransformer, OperationResult result) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + public GuiProfiledPrincipal getPrincipal( + PrismObject focus, AuthorizationTransformer authorizationTransformer, OperationResult result) + throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, + ExpressionEvaluationException { if (focus == null) { return null; } @@ -313,7 +316,10 @@ private PrismObject searchFocus(Class clazz, Obj return list.get(0); } - private void initializePrincipalFromAssignments(GuiProfiledPrincipal principal, PrismObject systemConfiguration, AuthorizationTransformer authorizationTransformer) { + private void initializePrincipalFromAssignments( + GuiProfiledPrincipal principal, + PrismObject systemConfiguration, + AuthorizationTransformer authorizationTransformer) { Task task = taskManager.createTaskInstance(GuiProfiledPrincipalManagerImpl.class.getName() + ".initializePrincipalFromAssignments"); OperationResult result = task.getResult(); try { @@ -476,7 +482,7 @@ public void invalidate(Class type, String oid, boolean PrismObject systemConfiguration = getSystemConfiguration(result); LifecycleStateModelType lifecycleModel = getLifecycleModel(focus, systemConfiguration); focusComputer.recompute(focus, lifecycleModel); - principal.getAuthorities().clear(); + principal.clearAuthorizations(); initializePrincipalFromAssignments(principal, systemConfiguration, null); return principal.getCompiledGuiProfile(); } finally { diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractAssignmentEvaluatorTest.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractAssignmentEvaluatorTest.java index 444fa1b9040..1bfe5493bfc 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractAssignmentEvaluatorTest.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractAssignmentEvaluatorTest.java @@ -911,16 +911,7 @@ protected AssignmentEvaluator createAssignmentEvaluator(ObjectDeltaObj return new AssignmentEvaluator.Builder() .referenceResolver(referenceResolver) .focusOdo(focusOdo) - .modelBeans(modelBeans) - .objectResolver(objectResolver) - .systemObjectCache(systemObjectCache) - .relationRegistry(relationRegistry) - .prismContext(prismContext) - .activationComputer(activationComputer) .now(clock.currentTimeXMLGregorianCalendar()) - .mappingFactory(mappingFactory) - .mappingEvaluator(mappingEvaluator) - .contextLoader(contextLoader) .lensContext(lensContext) .build(); } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java index a77f5bbc3fa..239f69411a8 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java @@ -540,16 +540,6 @@ public void test062JackDeputyOfGuybrushDeputyOfBarbossaInLoginMode() throws Exce .referenceResolver(referenceResolver) .focusOdo(new ObjectDeltaObject<>(jack, null, jack, jack.getDefinition())) .lensContext(context) - .channel(context.getChannel()) - .modelBeans(modelBeans) - .objectResolver(objectResolver) - .systemObjectCache(systemObjectCache) - .relationRegistry(relationRegistry) - .prismContext(prismContext) - .mappingFactory(mappingFactory) - .mappingEvaluator(mappingEvaluator) - .contextLoader(contextLoader) - .activationComputer(activationComputer) .now(clock.currentTimeXMLGregorianCalendar()) .systemConfiguration(context.getSystemConfiguration()) .loginMode(true) diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java index eeb29777356..d8e978c8f4e 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java @@ -365,7 +365,7 @@ public void test204bAutzJackCaseAssigneeSelfRole() throws Exception { assertSearch(RoleType.class, null, 0); // The search with ResourceObjectClass is important. It is a very different case // than searching just for UserType - assertSearch(ObjectType.class, null, 2); // user + case2 + assertSearch(ObjectType.class, null, 3); // user + case3 + case4 (see below) assertGetDeny(RoleType.class, ROLE_ORDINARY.oid); assertGetDeny(RoleType.class, ROLE_PERSONA_ADMIN.oid); @@ -389,10 +389,10 @@ public void test204bAutzJackCaseAssigneeSelfRole() throws Exception { assertGetDeny(CaseType.class, CASE1.oid); assertGetDeny(CaseType.class, CASE2.oid); - assertGetAllow(CaseType.class, CASE3.oid); - assertGetDeny(CaseType.class, CASE4.oid); + assertGetAllow(CaseType.class, CASE3.oid); // jack is current assignee + assertGetAllow(CaseType.class, CASE4.oid); // jack is assignee whose work item was completed assertReadCertCasesDeny(); - assertSearchCases(CASE3.oid); + assertSearchCases(CASE3.oid, CASE4.oid); assertGlobalStateUntouched(); } @@ -424,7 +424,7 @@ public void test204cAutzJackCaseAssigneeSelfWithDelegatesRole() throws Exception assertSearch(RoleType.class, null, 0); // The search with ResourceObjectClass is important. It is a very different case // than searching just for UserType - assertSearch(ObjectType.class, null, 2); // user + case2 + assertSearch(ObjectType.class, null, 3); // user + case3 + case4 assertGetDeny(RoleType.class, ROLE_ORDINARY.oid); assertGetDeny(RoleType.class, ROLE_PERSONA_ADMIN.oid); @@ -453,13 +453,13 @@ public void test204cAutzJackCaseAssigneeSelfWithDelegatesRole() throws Exception assertGetDeny(CaseType.class, CASE1.oid); assertGetDeny(CaseType.class, CASE2.oid); assertGetAllow(CaseType.class, CASE3.oid); - assertGetDeny(CaseType.class, CASE4.oid); + assertGetAllow(CaseType.class, CASE4.oid); // see previous test assertReadCertCasesDeny(); - assertSearchCases(CASE3.oid); + assertSearchCases(CASE3.oid, CASE4.oid); assertGlobalStateUntouched(); } finally { - deleteObjectRepo(UserType.class, USER_DEPUTY_1.oid); // faster than attempting to do this in each cleanup; todo reconsider + deleteObjectRepo(UserType.class, USER_DEPUTY_1.oid); // faster than attempting to do this in each cleanup; todo reconsider } } diff --git a/model/model-intest/src/test/resources/security/case-4.xml b/model/model-intest/src/test/resources/security/case-4.xml index f05d60cf9e3..bf5448e6c7a 100644 --- a/model/model-intest/src/test/resources/security/case-4.xml +++ b/model/model-intest/src/test/resources/security/case-4.xml @@ -5,7 +5,7 @@ ~ and European Union Public License. See LICENSE file for details. --> - + user) throws SchemaException loginSuperUser(principal); } - protected void loginSuperUser(MidPointPrincipal principal) throws SchemaException { - AuthorizationType superAutzBean = new AuthorizationType(); - prismContext.adopt(superAutzBean, RoleType.class, RoleType.F_AUTHORIZATION); - superAutzBean.getAction().add(AuthorizationConstants.AUTZ_ALL_URL); - Authorization superAutz = new Authorization(superAutzBean); - Collection authorities = principal.getAuthorities(); - authorities.add(superAutz); + protected void loginSuperUser(MidPointPrincipal principal) { + principal.addAuthorization(SecurityUtil.createPrivilegedAuthorization()); SecurityContext securityContext = SecurityContextHolder.getContext(); Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null); securityContext.setAuthentication(createMpAuthentication(authentication)); @@ -4825,7 +4818,7 @@ protected void assertPrincipalAttorneyOid(MidPointPrincipal principal, String at assertEquals("Wrong attroney OID in principal", attotrneyOid, attorney.getOid()); } - protected Collection getSecurityContextAuthorizations() { + private Collection getSecurityContextAuthorizations() { MidPointPrincipal midPointPrincipal = getSecurityContextPrincipal(); if (midPointPrincipal == null) { return null; @@ -5306,7 +5299,7 @@ protected void assertNoAuthorizations(PrismObject user) } protected void assertNoAuthorizations(MidPointPrincipal principal) { - if (principal.getAuthorities() != null && !principal.getAuthorities().isEmpty()) { + if (!principal.getAuthorities().isEmpty()) { AssertJUnit.fail("Unexpected authorizations in " + principal + ": " + principal.getAuthorities()); } } diff --git a/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/SqaleRepoBaseTest.java b/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/SqaleRepoBaseTest.java index 51e8b7a4f78..73703677ec0 100644 --- a/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/SqaleRepoBaseTest.java +++ b/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/SqaleRepoBaseTest.java @@ -538,11 +538,12 @@ protected SearchResultList searchContainerTest( then(typeName + "(s) " + description + " are returned"); assertThatOperationResult(operationResult).isSuccess(); - if (!AssignmentType.class.isAssignableFrom(type)) { + if (!AssignmentType.class.isAssignableFrom(type) + && !SimulationResultProcessedObjectType.class.isAssignableFrom(type)) { and("all have their owning objects"); getRootsForContainerables(result); // checks the owners } else { - // This is not implemented for assignment search yet + // This is not implemented for assignment and processed object search yet } return result; diff --git a/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/func/SimulationsBaselineTest.java b/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/func/SimulationsBaselineTest.java index 7ef02e80b5f..b6d9717e042 100644 --- a/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/func/SimulationsBaselineTest.java +++ b/repo/repo-sqale/src/test/java/com/evolveum/midpoint/repo/sqale/func/SimulationsBaselineTest.java @@ -161,14 +161,13 @@ public void test100CreateSimulation() throws ObjectAlreadyExistsException, Schem when("processed objects are retrieved explicitly"); // And we search TEST_TAG_1 owned by created result - - ObjectQuery query = PrismContext.get().queryFor(SimulationResultProcessedObjectType.class) - .ownerId(simulationOid) - .and() - .item(SimulationResultProcessedObjectType.F_EVENT_MARK_REF).ref(TEST_TAG_1) - .build(); SearchResultList processedObjects = - repositoryService.searchContainers(SimulationResultProcessedObjectType.class, query, null, result); + searchContainerTest( + "by event mark", + SimulationResultProcessedObjectType.class, + f -> f.ownerId(simulationOid) + .and() + .item(SimulationResultProcessedObjectType.F_EVENT_MARK_REF).ref(TEST_TAG_1)); then("they are present"); assertNotNull(processedObjects); diff --git a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/Authorization.java b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/Authorization.java index eb6cfb3eff4..23fcf106778 100644 --- a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/Authorization.java +++ b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/Authorization.java @@ -44,6 +44,12 @@ public Authorization(@NotNull AuthorizationType authorizationBean) { exceptItems = parseItems(this.authorizationBean.getExceptItem()); } + public static Authorization create(@NotNull AuthorizationType authorizationBean, String sourceDescription) { + var autz = new Authorization(authorizationBean); + autz.setSourceDescription(sourceDescription); + return autz; + } + @Override public String getAuthority() { // this is complex authority. Just return null diff --git a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/MidPointPrincipal.java b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/MidPointPrincipal.java index bb39d2b75f2..d9659bdc2d8 100644 --- a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/MidPointPrincipal.java +++ b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/MidPointPrincipal.java @@ -6,9 +6,8 @@ */ package com.evolveum.midpoint.security.api; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Locale; +import java.io.Serial; +import java.util.*; import org.apache.commons.lang3.LocaleUtils; import org.apache.commons.lang3.Validate; @@ -31,12 +30,12 @@ * @author Radovan Semancik */ public class MidPointPrincipal implements UserDetails, DebugDumpable, ShortDumpable { - private static final long serialVersionUID = 8299738301872077768L; + @Serial private static final long serialVersionUID = 8299738301872077768L; // Focus should not be final in case of session refresh, we need new focus object. @NotNull private FocusType focus; private Locale preferredLocale; - @NotNull private Collection authorizations = new ArrayList<>(); + @NotNull private final List authorizations = new ArrayList<>(); private ActivationStatusType effectiveActivationStatus; private SecurityPolicyType applicableSecurityPolicy; // TODO: or a set? @@ -51,7 +50,15 @@ public MidPointPrincipal(@NotNull FocusType focus) { @Override public @NotNull Collection getAuthorities() { - return authorizations; + return Collections.unmodifiableList(authorizations); + } + + public void addAuthorization(@NotNull Authorization authorization) { + authorizations.add(authorization); + } + + public void clearAuthorizations() { + authorizations.clear(); } @Override @@ -174,6 +181,7 @@ public void addDelegatorWithOtherPrivilegesLimitations(DelegatorWithOtherPrivile /** * Semi-shallow clone. */ + @SuppressWarnings("MethodDoesntCallSuperMethod") @Override public MidPointPrincipal clone() { MidPointPrincipal clone = new MidPointPrincipal(this.focus); @@ -183,7 +191,7 @@ public MidPointPrincipal clone() { protected void copyValues(MidPointPrincipal clone) { clone.applicableSecurityPolicy = this.applicableSecurityPolicy; - clone.authorizations = new ArrayList<>(authorizations); + clone.authorizations.addAll(authorizations); clone.effectiveActivationStatus = this.effectiveActivationStatus; clone.delegatorWithOtherPrivilegesLimitationsCollection.addAll(this.delegatorWithOtherPrivilegesLimitationsCollection); } diff --git a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/SecurityUtil.java b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/SecurityUtil.java index 7098e33bdf8..2bcf31a90a4 100644 --- a/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/SecurityUtil.java +++ b/repo/security-api/src/main/java/com/evolveum/midpoint/security/api/SecurityUtil.java @@ -457,4 +457,10 @@ public static boolean isOverFailedLockoutAttempts(int failedLogins, CredentialPo return credentialsPolicy != null && credentialsPolicy.getLockoutMaxFailedAttempts() != null && credentialsPolicy.getLockoutMaxFailedAttempts() > 0 && failedLogins >= credentialsPolicy.getLockoutMaxFailedAttempts(); } + + public static @NotNull Authorization createPrivilegedAuthorization() { + AuthorizationType authorizationBean = new AuthorizationType(); + authorizationBean.getAction().add(AuthorizationConstants.AUTZ_ALL_URL); + return new Authorization(authorizationBean); + } } diff --git a/repo/security-enforcer-impl/src/main/java/com/evolveum/midpoint/security/enforcer/impl/AuthorizationLimitationsCollector.java b/repo/security-enforcer-impl/src/main/java/com/evolveum/midpoint/security/enforcer/impl/AuthorizationLimitationsCollector.java index fbd2f231c3b..f11687e43fa 100644 --- a/repo/security-enforcer-impl/src/main/java/com/evolveum/midpoint/security/enforcer/impl/AuthorizationLimitationsCollector.java +++ b/repo/security-enforcer-impl/src/main/java/com/evolveum/midpoint/security/enforcer/impl/AuthorizationLimitationsCollector.java @@ -29,7 +29,7 @@ public class AuthorizationLimitationsCollector implements Consumer limitActions = new ArrayList<>(); + private final List limitActions = new ArrayList<>(); /** * Parsing limitation from the authorization. @@ -58,7 +58,7 @@ public void accept(Authorization autz) { */ @Override public Collection transform(Authorization autz) { - if (unlimited || allActionsAlloved(autz)) { + if (unlimited || allActionsAllowed(autz)) { return Arrays.asList(autz); } Authorization limitedAutz = autz.clone(); @@ -75,7 +75,7 @@ public Collection transform(Authorization autz) { return Arrays.asList(limitedAutz); } - private boolean allActionsAlloved(Authorization autz) { + private boolean allActionsAllowed(Authorization autz) { for (String autzAction: autz.getAction()) { if (!limitActions.contains(autzAction)) { return false; diff --git a/repo/security-impl/src/main/java/com/evolveum/midpoint/security/impl/SecurityContextManagerImpl.java b/repo/security-impl/src/main/java/com/evolveum/midpoint/security/impl/SecurityContextManagerImpl.java index a2d9abb0342..535a7ba54c4 100644 --- a/repo/security-impl/src/main/java/com/evolveum/midpoint/security/impl/SecurityContextManagerImpl.java +++ b/repo/security-impl/src/main/java/com/evolveum/midpoint/security/impl/SecurityContextManagerImpl.java @@ -25,7 +25,6 @@ import com.evolveum.midpoint.util.Producer; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; /** @@ -142,7 +141,7 @@ public T runPrivileged(Producer producer) { // Try to reuse the original identity as much as possible. All we need to is add AUTZ_ALL // to the list of authorities - Authorization privilegedAuthorization = createPrivilegedAuthorization(); + Authorization privilegedAuthorization = SecurityUtil.createPrivilegedAuthorization(); Object newPrincipal = null; if (origAuthentication != null) { @@ -154,7 +153,7 @@ public T runPrivileged(Producer producer) { if (origPrincipal != null) { if (origPrincipal instanceof MidPointPrincipal) { MidPointPrincipal newMidPointPrincipal = ((MidPointPrincipal)origPrincipal).clone(); - newMidPointPrincipal.getAuthorities().add(privilegedAuthorization); + newMidPointPrincipal.addAuthorization(privilegedAuthorization); newPrincipal = newMidPointPrincipal; } } @@ -182,12 +181,6 @@ public T runPrivileged(Producer producer) { } - private Authorization createPrivilegedAuthorization() { - AuthorizationType authorizationBean = new AuthorizationType(); - authorizationBean.getAction().add(AuthorizationConstants.AUTZ_ALL_URL); - return new Authorization(authorizationBean); - } - @Override public void storeConnectionInformation(HttpConnectionInformation value) { connectionInformationThreadLocal.set(value); diff --git a/repo/security-impl/src/test/java/com/evolveum/midpoint/security/impl/MidPointPrincipalManagerMock.java b/repo/security-impl/src/test/java/com/evolveum/midpoint/security/impl/MidPointPrincipalManagerMock.java index 90ee59a6f16..4a8ab9380fe 100644 --- a/repo/security-impl/src/test/java/com/evolveum/midpoint/security/impl/MidPointPrincipalManagerMock.java +++ b/repo/security-impl/src/test/java/com/evolveum/midpoint/security/impl/MidPointPrincipalManagerMock.java @@ -149,9 +149,9 @@ private void initializePrincipalFromAssignments(MidPointPrincipal principal, Pri // principal.setAdminGuiConfiguration(systemConfiguration.asObjectable().getAdminGuiConfiguration()); // } - AuthorizationType authorizationBean = new AuthorizationType(); - authorizationBean.getAction().add("FAKE"); - principal.getAuthorities().add(new Authorization(authorizationBean)); + principal.addAuthorization( + new Authorization( + new AuthorizationType().action("FAKE"))); ActivationType activation = principal.getFocus().getActivation(); if (activation != null) {