Skip to content

Commit

Permalink
Merge branch 'post-3.7-fixes'
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jan 29, 2018
2 parents 3d6de13 + 2106948 commit 6c811b2
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 8 deletions.
Expand Up @@ -1489,16 +1489,14 @@ private <F extends ObjectType,O extends ObjectType> void authorizeAssignmentRequ
if (focusAssignmentDelta == null) {
return;
}
Collection<PrismContainerValue<AssignmentType>> changedAssignmentValues = focusAssignmentDelta.getValueChanges(plusMinusZero);
Collection<PrismContainerValue<AssignmentType>> changedAssignmentValues = determineChangedAssignmentValues(context.getFocusContext(), focusAssignmentDelta, plusMinusZero);
for (PrismContainerValue<AssignmentType> changedAssignmentValue: changedAssignmentValues) {
AssignmentType changedAssignment = changedAssignmentValue.getRealValue();
ObjectReferenceType targetRef = changedAssignment.getTargetRef();
if (targetRef == null || targetRef.getOid() == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("{} of non-target assignment not allowed",
assignActionUrl.substring(assignActionUrl.lastIndexOf('#') + 1));
}
securityEnforcer.failAuthorization("with assignment", getRequestAuthorizationPhase(context), AuthorizationParameters.Builder.buildObject(object), result);
String operationDesc = assignActionUrl.substring(assignActionUrl.lastIndexOf('#') + 1);
LOGGER.debug("{} of non-target assignment not allowed", operationDesc);
securityEnforcer.failAuthorization(operationDesc, getRequestAuthorizationPhase(context), AuthorizationParameters.Builder.buildObject(object), result);
assert false; // just to keep static checkers happy
}
// We do not worry about performance here too much. The target was already evaluated. This will be retrieved from repo cache anyway.
Expand Down Expand Up @@ -1552,6 +1550,30 @@ private <F extends ObjectType,O extends ObjectType> void authorizeAssignmentRequ
}
}

private <F extends ObjectType> Collection<PrismContainerValue<AssignmentType>> determineChangedAssignmentValues(LensFocusContext<F> focusContext,
ContainerDelta<AssignmentType> assignmentDelta, PlusMinusZero plusMinusZero) {
Collection<PrismContainerValue<AssignmentType>> changedAssignmentValues = assignmentDelta.getValueChanges(plusMinusZero);
if (plusMinusZero == PlusMinusZero.PLUS) {
return changedAssignmentValues;
}
Collection<PrismContainerValue<AssignmentType>> processedChangedAssignmentValues = new ArrayList<>(changedAssignmentValues.size());
PrismObject<F> existingObject = focusContext.getObjectCurrentOrOld();
PrismContainer<AssignmentType> existingAssignmentContainer = existingObject.findContainer(FocusType.F_ASSIGNMENT);
for (PrismContainerValue<AssignmentType> changedAssignmentValue : changedAssignmentValues) {
if (changedAssignmentValue.isIdOnly()) {
if (existingAssignmentContainer != null) {
PrismContainerValue<AssignmentType> existingAssignmentValue = existingAssignmentContainer.findValue(changedAssignmentValue.getId());
if (existingAssignmentValue != null) {
processedChangedAssignmentValues.add(existingAssignmentValue);
}
}
} else {
processedChangedAssignmentValues.add(changedAssignmentValue);
}
}
return processedChangedAssignmentValues;
}

private <F extends ObjectType> void reclaimSequences(LensContext<F> context, Task task, OperationResult result) throws SchemaException {
Map<String, Long> sequenceMap = context.getSequences();
LOGGER.trace("Context sequence map: {}", sequenceMap);
Expand Down
Expand Up @@ -341,6 +341,9 @@ public abstract class AbstractSecurityTest extends AbstractInitializedModelInteg

protected static final File ROLE_ASSIGN_SELF_REQUESTABLE_ANY_APPROVER_FILE = new File(TEST_DIR, "role-assign-self-requestable-any-approver.xml");
protected static final String ROLE_ASSIGN_SELF_REQUESTABLE_ANY_APPROVER_OID = "d3e83cce-bb25-11e7-ae7c-b73d2208bf2a";

protected static final File ROLE_UNASSIGN_SELF_REQUESTABLE_FILE = new File(TEST_DIR, "role-unassign-self-requestable.xml");
protected static final String ROLE_UNASSIGN_SELF_REQUESTABLE_OID = "7c903f28-04ed-11e8-bb7a-df31e8679d27";

protected static final File ORG_REQUESTABLE_FILE = new File(TEST_DIR,"org-requestable.xml");
protected static final String ORG_REQUESTABLE_OID = "8f2bd344-a46c-4c0b-aa34-db08b7d7f7f2";
Expand Down Expand Up @@ -381,7 +384,7 @@ public abstract class AbstractSecurityTest extends AbstractInitializedModelInteg
protected static final XMLGregorianCalendar JACK_VALID_TO_LONG_AGEAD = XmlTypeConverter.createXMLGregorianCalendar(10000000000000L);

protected static final int NUMBER_OF_ALL_USERS = 11;
protected static final int NUMBER_OF_IMPORTED_ROLES = 69;
protected static final int NUMBER_OF_IMPORTED_ROLES = 70;
protected static final int NUMBER_OF_ALL_ORGS = 11;

protected String userRumRogersOid;
Expand Down Expand Up @@ -465,6 +468,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
repoAddObjectFromFile(ROLE_ATTORNEY_MANAGER_WORKITEMS_FILE, initResult);
repoAddObjectFromFile(ROLE_APPROVER_FILE, initResult);
repoAddObjectFromFile(ROLE_ASSIGN_SELF_REQUESTABLE_ANY_APPROVER_FILE, initResult);
repoAddObjectFromFile(ROLE_UNASSIGN_SELF_REQUESTABLE_FILE, initResult);

repoAddObjectFromFile(ORG_REQUESTABLE_FILE, initResult);
repoAddObjectFromFile(ORG_INDIRECT_PIRATE_FILE, initResult);
Expand Down
Expand Up @@ -1742,6 +1742,155 @@ public void test250AssignRequestableSelfOtherApporver() throws Exception {
assertGlobalStateUntouched();
}

/**
* MID-4204
*/
@Test
public void test252AssignRequestableSelfOtherApporverEmptyDelta() throws Exception {
final String TEST_NAME = "test252AssignRequestableSelfOtherApporverEmptyDelta";
displayTestTitle(TEST_NAME);
// GIVEN
cleanupAutzTest(USER_JACK_OID);
assignRole(USER_JACK_OID, ROLE_ASSIGN_SELF_REQUESTABLE_ANY_APPROVER_OID);

cleanupUnassign(userRumRogersOid, ROLE_APPROVER_OID);
cleanupUnassign(USER_BARBOSSA_OID, ROLE_PROP_READ_SOME_MODIFY_SOME_OID);

login(USER_JACK_USERNAME);

// WHEN
displayWhen(TEST_NAME);

assertReadAllow();
assertAddDeny();
assertModifyDeny();
assertDeleteDeny();

final PrismObject<UserType> user1 = getUser(USER_JACK_OID);
assertAssignments(user1, 1);
assertAssignedRole(user1, ROLE_ASSIGN_SELF_REQUESTABLE_ANY_APPROVER_OID);

assertAllow("assign business role to jack",
(task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, task, result));

final PrismObject<UserType> user2 = getUser(USER_JACK_OID);
assertAssignments(user2, 2);
assertAssignedRole(user2, ROLE_BUSINESS_1_OID);

// default relation, non-requestable role
assertDeny("assign application role to jack",
(task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_2_OID, task, result));

assertAllow("unassign business role from jack",
(task, result) -> deleteFocusAssignmentEmptyDelta(user2, ROLE_BUSINESS_1_OID, task, result));

// wrong relation
assertDeny("assign business role to jack (manager)",
(task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, SchemaConstants.ORG_MANAGER, task, result));

// requestable role, but assign to a different user
assertDeny("assign application role to barbossa",
(task, result) -> assignRole(USER_BARBOSSA_OID, ROLE_BUSINESS_1_OID, task, result));

assertAllow("assign business role to barbossa (approver)",
(task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, SchemaConstants.ORG_APPROVER, task, result));

assertAllow("unassign business role to barbossa (approver)",
(task, result) -> unassignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, SchemaConstants.ORG_APPROVER, task, result));

assertAllow("assign business role to barbossa (owner)",
(task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_2_OID, SchemaConstants.ORG_OWNER, task, result));

final PrismObject<UserType> user3 = getUser(USER_JACK_OID);
assertAssignments(user3, 2);
assertAssignedRole(user3, ROLE_BUSINESS_2_OID);

assertAllow("unassign business role to barbossa (owner)",
(task, result) -> deleteFocusAssignmentEmptyDelta(user3, ROLE_BUSINESS_2_OID, SchemaConstants.ORG_OWNER, task, result));

final PrismObject<UserType> user4 = getUser(USER_JACK_OID);
assertAssignments(user4, 1);

PrismObject<UserType> userBarbossa = getUser(USER_BARBOSSA_OID);
assertAssignments(userBarbossa, 0);

assertGlobalStateUntouched();
}

@Test
public void test254AssignUnassignRequestableSelf() throws Exception {
final String TEST_NAME = "test254AssignUnassignRequestableSelf";
displayTestTitle(TEST_NAME);
// GIVENds
cleanupAutzTest(USER_JACK_OID);
assignRole(USER_JACK_OID, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);
assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID);

login(USER_JACK_USERNAME);

// WHEN
displayWhen(TEST_NAME);

assertReadAllow();
assertAddDeny();
assertModifyDeny();
assertDeleteDeny();

PrismObject<UserType> user = getUser(USER_JACK_OID);
assertAssignments(user, 2);
assertAssignedRole(user, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);
assertAssignedRole(user, ROLE_BUSINESS_1_OID);

assertAllow("unassign business role from jack",
(task, result) -> unassignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, task, result));

user = getUser(USER_JACK_OID);
assertAssignments(user, 1);
assertAssignedRole(user, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);

assertDeny("unassign ROLE_UNASSIGN_SELF_REQUESTABLE role from jack",
(task, result) -> unassignRole(USER_JACK_OID, ROLE_UNASSIGN_SELF_REQUESTABLE_OID, task, result));

assertGlobalStateUntouched();
}

@Test
public void test256AssignUnassignRequestableSelfEmptyDelta() throws Exception {
final String TEST_NAME = "test256AssignUnassignRequestableSelfEmptyDelta";
displayTestTitle(TEST_NAME);
// GIVENds
cleanupAutzTest(USER_JACK_OID);
assignRole(USER_JACK_OID, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);
assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID);

login(USER_JACK_USERNAME);

// WHEN
displayWhen(TEST_NAME);

assertReadAllow();
assertAddDeny();
assertModifyDeny();
assertDeleteDeny();

final PrismObject<UserType> user1 = getUser(USER_JACK_OID);
assertAssignments(user1, 2);
assertAssignedRole(user1, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);
assertAssignedRole(user1, ROLE_BUSINESS_1_OID);

assertAllow("unassign business role from jack",
(task, result) -> deleteFocusAssignmentEmptyDelta(user1, ROLE_BUSINESS_1_OID, task, result));

final PrismObject<UserType> user2 = getUser(USER_JACK_OID);
assertAssignments(user2, 1);
assertAssignedRole(user2, ROLE_UNASSIGN_SELF_REQUESTABLE_OID);

assertDeny("unassign ROLE_UNASSIGN_SELF_REQUESTABLE role from jack",
(task, result) -> deleteFocusAssignmentEmptyDelta(user2, ROLE_UNASSIGN_SELF_REQUESTABLE_OID, task, result));

assertGlobalStateUntouched();
}

@Test
public void test260AutzJackLimitedRoleAdministrator() throws Exception {
final String TEST_NAME = "test260AutzJackLimitedRoleAdministrator";
Expand Down
@@ -0,0 +1,47 @@
<!--
~ Copyright (c) 2014-2018 Evolveum
~
~ 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.
-->
<role oid="7c903f28-04ed-11e8-bb7a-df31e8679d27"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3">
<name>Unassign self requestable</name>
<description>Unassign any requestable roles assigned to myself</description>
<authorization>
<action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
</authorization>
<authorization>
<name>unassign-self-requestable</name>
<action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#unassign</action>
<phase>request</phase>
<object>
<special>self</special>
</object>
<target>
<type>RoleType</type>
<filter>
<q:equal>
<q:path>requestable</q:path>
<q:value>true</q:value>
</q:equal>
</filter>
</target>
</authorization>
<authorization>
<action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
<phase>execution</phase>
</authorization>
</role>
Expand Up @@ -1038,6 +1038,24 @@ protected <F extends FocusType> void modifyFocusAssignment(Class<F> focusClass,
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(focusDelta);
modelService.executeChanges(deltas, options, task, result);
}

protected <F extends FocusType> void deleteFocusAssignmentEmptyDelta(PrismObject<F> existingFocus, String targetOid, Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException {
deleteFocusAssignmentEmptyDelta(existingFocus, targetOid, null, null, task, result);
}

protected <F extends FocusType> void deleteFocusAssignmentEmptyDelta(PrismObject<F> existingFocus, String targetOid, QName relation, Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException {
deleteFocusAssignmentEmptyDelta(existingFocus, targetOid, relation, null, task, result);
}

protected <F extends FocusType> void deleteFocusAssignmentEmptyDelta(PrismObject<F> existingFocus, String targetOid, QName relation,
ModelExecuteOptions options, Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException {
ObjectDelta<F> focusDelta = createAssignmentFocusEmptyDeleteDelta(existingFocus, targetOid, relation);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(focusDelta);
modelService.executeChanges(deltas, options, task, result);
}

protected <F extends FocusType> void unassign(Class<F> focusClass, String focusOid, AssignmentType currentAssignment, ModelExecuteOptions options, Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException {
Expand Down Expand Up @@ -1120,7 +1138,7 @@ protected ContainerDelta<AssignmentType> createAssignmentModification(String rol
}
return assignmentDelta;
}

protected ContainerDelta<AssignmentType> createAssignmentModification(long id, boolean add) throws SchemaException {
ContainerDelta<AssignmentType> assignmentDelta = ContainerDelta.createDelta(UserType.F_ASSIGNMENT, getUserDefinition());
PrismContainerValue<AssignmentType> cval = new PrismContainerValue<AssignmentType>(prismContext);
Expand All @@ -1132,6 +1150,38 @@ protected ContainerDelta<AssignmentType> createAssignmentModification(long id, b
}
return assignmentDelta;
}

protected <F extends FocusType> ContainerDelta<AssignmentType> createAssignmentEmptyDeleteModification(PrismObject<F> existingFocus, String roleOid, QName relation) throws SchemaException {
AssignmentType existingAssignment = findAssignment(existingFocus, roleOid, relation);
return createAssignmentModification(existingAssignment.getId(), false);
}

protected <F extends FocusType> AssignmentType findAssignment(PrismObject<F> existingFocus, String targetOid, QName relation) {
for (AssignmentType assignmentType : existingFocus.asObjectable().getAssignment()) {
if (assignmentMatches(assignmentType, targetOid, relation)) {
return assignmentType;
}
}
return null;
}

protected boolean assignmentMatches(AssignmentType assignmentType, String targetOid, QName relation) {
ObjectReferenceType targetRef = assignmentType.getTargetRef();
if (targetRef == null) {
return false;
}
return referenceMatches(targetRef, targetOid, relation);
}

private boolean referenceMatches(ObjectReferenceType ref, String targetOid, QName relation) {
if (targetOid != null && !targetOid.equals(ref.getOid())) {
return false;
}
if (relation != null && !QNameUtil.match(relation, ref.getRelation())) {
return false;
}
return true;
}

protected ObjectDelta<UserType> createAssignmentUserDelta(String userOid, String roleOid, QName refType, QName relation,
PrismContainer<?> extension, ActivationType activationType, boolean add) throws SchemaException {
Expand Down Expand Up @@ -1160,6 +1210,12 @@ protected <F extends FocusType> ObjectDelta<F> createAssignmentFocusDelta(Class<
return ObjectDelta.createModifyDelta(userOid, modifications, focusClass, prismContext);
}

protected <F extends FocusType> ObjectDelta<F> createAssignmentFocusEmptyDeleteDelta(PrismObject<F> existingFocus, String roleOid, QName relation) throws SchemaException {
Collection<ItemDelta<?,?>> modifications = new ArrayList<>();
modifications.add((createAssignmentEmptyDeleteModification(existingFocus, roleOid, relation)));
return ObjectDelta.createModifyDelta(existingFocus.getOid(), modifications, existingFocus.getCompileTimeClass(), prismContext);
}

protected ContainerDelta<AssignmentType> createAccountAssignmentModification(String resourceOid, String intent, boolean add) throws SchemaException {
return createAssignmentModification(resourceOid, ShadowKindType.ACCOUNT, intent, add);
}
Expand Down

0 comments on commit 6c811b2

Please sign in to comment.