Search in sources :

Example 1 with OrderConstraintsType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType in project midpoint by Evolveum.

the class ClockworkAuthorizationHelper method authorizeAssignmentRequest.

private <F extends ObjectType, O extends ObjectType> void authorizeAssignmentRequest(LensContext<F> context, String operationUrl, String assignActionUrl, ItemName assignmentElementQName, PrismObject<O> object, OwnerResolver ownerResolver, ObjectSecurityConstraints securityConstraints, PlusMinusZero plusMinusZero, boolean prohibitPolicies, Task task, OperationResult result) throws SecurityViolationException, SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException {
    // This is *request* authorization. Therefore we care only about primary delta.
    ObjectDelta<F> focusPrimaryDelta = context.getFocusContext().getPrimaryDelta();
    if (focusPrimaryDelta == null) {
        return;
    }
    ContainerDelta<AssignmentType> focusAssignmentDelta = focusPrimaryDelta.findContainerDelta(assignmentElementQName);
    if (focusAssignmentDelta == null) {
        return;
    }
    String operationDesc = assignActionUrl.substring(assignActionUrl.lastIndexOf('#') + 1);
    Collection<PrismContainerValue<AssignmentType>> changedAssignmentValues = determineChangedAssignmentValues(context.getFocusContext(), assignmentElementQName, focusAssignmentDelta, plusMinusZero);
    for (PrismContainerValue<AssignmentType> changedAssignmentValue : changedAssignmentValues) {
        AssignmentType changedAssignment = changedAssignmentValue.getRealValue();
        ObjectReferenceType targetRef = changedAssignment.getTargetRef();
        if (targetRef == null || targetRef.getOid() == null) {
            // This may still be allowed by #add and #modify authorizations. We have already checked these, but there may be combinations of
            // assignments, one of the assignments allowed by #assign, other allowed by #modify (e.g. MID-4517).
            // Therefore check the items again. This is not very efficient to check it twice. But this is not a common case
            // so there should not be any big harm in suffering this inefficiency.
            AccessDecision subitemDecision = securityEnforcer.determineSubitemDecision(securityConstraints, changedAssignmentValue, operationUrl, getRequestAuthorizationPhase(context), null, plusMinusZero, operationDesc);
            if (subitemDecision == AccessDecision.ALLOW) {
                LOGGER.debug("{} of policy {} to {} allowed with {} authorization", operationDesc, assignmentElementQName.getLocalPart(), object, operationUrl);
                continue;
            } else {
                LOGGER.debug("{} of non-target {} not allowed", operationDesc, assignmentElementQName.getLocalPart());
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Denied request for object {}: {} of non-target {} not allowed", object, operationDesc, assignmentElementQName.getLocalPart());
                }
                securityEnforcer.failAuthorization(operationDesc, getRequestAuthorizationPhase(context), AuthorizationParameters.Builder.buildObject(object), result);
            }
        }
        PrismObject<ObjectType> target;
        try {
            // We do not worry about performance here too much. The target was already evaluated. This will be retrieved from repo cache anyway.
            target = objectResolver.resolve(targetRef.asReferenceValue(), "resolving " + assignmentElementQName.getLocalPart() + " target", task, result);
        } catch (ObjectNotFoundException e) {
            LOGGER.warn("Object {} referenced as {} target in {} was not found", targetRef.asReferenceValue().getOid(), assignmentElementQName.getLocalPart(), object);
            target = null;
        }
        ObjectDelta<O> assignmentObjectDelta = object.createModifyDelta();
        ContainerDelta<AssignmentType> assignmentDelta = assignmentObjectDelta.createContainerModification(assignmentElementQName);
        // We do not care if this is add or delete. All that matters for authorization is that it is in a delta.
        assignmentDelta.addValuesToAdd(changedAssignment.asPrismContainerValue().clone());
        QName relation = targetRef.getRelation();
        if (relation == null) {
            relation = prismContext.getDefaultRelation();
        }
        List<OrderConstraintsType> orderConstraints = determineOrderConstraints(assignmentElementQName, changedAssignment);
        AuthorizationParameters<O, ObjectType> autzParams = new AuthorizationParameters.Builder<O, ObjectType>().oldObject(object).delta(assignmentObjectDelta).target(target).relation(relation).orderConstraints(orderConstraints).build();
        if (prohibitPolicies) {
            if (changedAssignment.getPolicyRule() != null || !changedAssignment.getPolicyException().isEmpty() || !changedAssignment.getPolicySituation().isEmpty() || !changedAssignment.getTriggeredPolicyRule().isEmpty()) {
                // This may still be allowed by #add and #modify authorizations. We have already checked these, but there may be combinations of
                // assignments, one of the assignments allowed by #assign, other allowed by #modify (e.g. MID-4517).
                // Therefore check the items again. This is not very efficient to check it twice. But this is not a common case
                // so there should not be any big harm in suffering this inefficiency.
                AccessDecision subitemDecision = securityEnforcer.determineSubitemDecision(securityConstraints, changedAssignmentValue, operationUrl, getRequestAuthorizationPhase(context), null, plusMinusZero, operationDesc);
                if (subitemDecision == AccessDecision.ALLOW) {
                    LOGGER.debug("{} of policy assignment to {} allowed with {} authorization", operationDesc, object, operationUrl);
                    continue;
                } else {
                    securityEnforcer.failAuthorization("with assignment because of policies in the assignment", getRequestAuthorizationPhase(context), autzParams, result);
                }
            }
        }
        if (securityEnforcer.isAuthorized(assignActionUrl, getRequestAuthorizationPhase(context), autzParams, ownerResolver, task, result)) {
            LOGGER.debug("{} of target {} to {} allowed with {} authorization", operationDesc, target, object, assignActionUrl);
            continue;
        }
        if (relationRegistry.isDelegation(relation)) {
            if (securityEnforcer.isAuthorized(ModelAuthorizationAction.DELEGATE.getUrl(), getRequestAuthorizationPhase(context), autzParams, ownerResolver, task, result)) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("{} of target {} to {} allowed with {} authorization", operationDesc, target, object, ModelAuthorizationAction.DELEGATE.getUrl());
                }
                continue;
            }
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("{} of target {} to {} denied", operationDesc, target, object);
        }
        securityEnforcer.failAuthorization("with " + assignmentElementQName.getLocalPart(), getRequestAuthorizationPhase(context), autzParams, result);
    }
}
Also used : PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) QName(javax.xml.namespace.QName) OrderConstraintsType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType) ObjectType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType) ObjectReferenceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType) AssignmentType(com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType) AccessDecision(com.evolveum.midpoint.schema.AccessDecision) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException)

Example 2 with OrderConstraintsType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType in project midpoint by Evolveum.

the class TargetInducementEvaluation method computeOrderAdjustment.

/**
 * Tries to compute correct evaluation order after application of an inducement. Terrible method.
 * For some background please see comments at the end of {@link AssignmentPathSegmentImpl} class.
 */
private OrderAdjustment computeOrderAdjustment() {
    EvaluationOrder currentOrder = segment.getEvaluationOrder();
    EvaluationOrder currentTargetOrder = segment.getEvaluationOrderForTarget();
    List<OrderConstraintsType> constraints = new ArrayList<>(inducement.getOrderConstraint());
    Integer order = inducement.getOrder();
    if (constraints.isEmpty()) {
        if (order == null || order == 1) {
            return new OrderAdjustment(currentOrder, currentTargetOrder);
        } else if (order <= 0) {
            throw new IllegalStateException("Wrong inducement order: it must be positive but it is " + order + " instead");
        }
        // converting legacy -> new specification
        int currentSummary = currentOrder.getSummaryOrder();
        if (order > currentSummary) {
            LOGGER.trace("order of the inducement ({}) is greater than the current evaluation order ({}), marking as undefined", order, currentOrder);
            return OrderAdjustment.undefined();
        } else {
            // i.e. currentOrder >= order, i.e. currentOrder > order-1
            int newOrder = currentSummary - (order - 1);
            assert newOrder > 0;
            constraints.add(new OrderConstraintsType(ctx.ae.prismContext).order(order).resetOrder(newOrder));
        }
    }
    OrderConstraintsType summaryConstraints = getConstraintWithoutRelation(constraints);
    Integer resetSummaryTo = summaryConstraints != null && summaryConstraints.getResetOrder() != null ? summaryConstraints.getResetOrder() : null;
    OrderAdjustment adjustment;
    if (resetSummaryTo != null) {
        adjustment = applyResetSummary(currentOrder, currentTargetOrder, constraints, resetSummaryTo);
    } else {
        adjustment = applyResetForRelations(currentOrder, currentTargetOrder, constraints);
    }
    if (!adjustment.evaluationOrder.isDefined()) {
        return adjustment;
    }
    if (adjustment.evaluationOrder.getSummaryOrder() <= 0) {
        return OrderAdjustment.undefined();
    }
    if (!adjustment.evaluationOrder.isValid()) {
        throw new AssertionError("Resulting evaluation order path is invalid: " + adjustment.evaluationOrder);
    }
    if (adjustment.targetEvaluationOrder.isValid()) {
        return adjustment;
    } else {
        // some extreme cases like the one described in TestAssignmentProcessor2.test520
        return new OrderAdjustment(adjustment.evaluationOrder, EvaluationOrderImpl.UNDEFINED, adjustment.lastEqualOrderSegmentIndex);
    }
}
Also used : OrderConstraintsType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType) EvaluationOrder(com.evolveum.midpoint.model.api.context.EvaluationOrder) ArrayList(java.util.ArrayList)

Example 3 with OrderConstraintsType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType in project midpoint by Evolveum.

the class FocusTypeUtil method dumpInducementConstraints.

public static String dumpInducementConstraints(AssignmentType assignmentType) {
    if (assignmentType.getOrder() != null) {
        return assignmentType.getOrder().toString();
    }
    if (assignmentType.getOrderConstraint().isEmpty()) {
        return "1";
    }
    StringBuilder sb = new StringBuilder();
    for (OrderConstraintsType orderConstraint : assignmentType.getOrderConstraint()) {
        if (orderConstraint.getRelation() != null) {
            sb.append(orderConstraint.getRelation().getLocalPart());
        } else {
            sb.append("null");
        }
        sb.append(":");
        if (orderConstraint.getOrder() != null) {
            sb.append(orderConstraint.getOrder());
        } else {
            sb.append(orderConstraint.getOrderMin());
            sb.append("-");
            sb.append(orderConstraint.getOrderMax());
        }
        sb.append(",");
    }
    sb.setLength(sb.length() - 1);
    return sb.toString();
}
Also used : OrderConstraintsType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType)

Example 4 with OrderConstraintsType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType in project midpoint by Evolveum.

the class ClockworkAuthorizationHelper method determineOrderConstraints.

private List<OrderConstraintsType> determineOrderConstraints(QName assignmentElementQName, AssignmentType changedAssignment) {
    OrderConstraintsType orderConstraints = new OrderConstraintsType();
    if (FocusType.F_ASSIGNMENT.equals(assignmentElementQName)) {
        orderConstraints.setOrder(0);
    } else {
        List<OrderConstraintsType> assignmentOrderConstraints = changedAssignment.getOrderConstraint();
        if (!assignmentOrderConstraints.isEmpty()) {
            return assignmentOrderConstraints;
        }
        Integer assignmentOrder = changedAssignment.getOrder();
        if (assignmentOrder == null) {
            orderConstraints.setOrder(1);
        } else {
            orderConstraints.setOrder(assignmentOrder);
        }
    }
    List<OrderConstraintsType> orderConstraintsList = new ArrayList<>(1);
    orderConstraintsList.add(orderConstraints);
    return orderConstraintsList;
}
Also used : OrderConstraintsType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType) ArrayList(java.util.ArrayList)

Example 5 with OrderConstraintsType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType in project midpoint by Evolveum.

the class TargetInducementEvaluation method applyResetSummary.

private OrderAdjustment applyResetSummary(EvaluationOrder currentOrder, EvaluationOrder currentTargetOrder, List<OrderConstraintsType> constraints, Integer resetSummaryTo) {
    OrderAdjustment adjustment;
    int summaryBackwards = currentOrder.getSummaryOrder() - resetSummaryTo;
    if (summaryBackwards < 0) {
        // or should we throw an exception?
        LOGGER.warn("Cannot move summary order backwards to a negative value ({}). Current order: {}, requested order: {}", summaryBackwards, currentOrder.getSummaryOrder(), resetSummaryTo);
        return OrderAdjustment.undefined();
    } else if (summaryBackwards > 0) {
        int assignmentsSeen = 0;
        int i = ctx.assignmentPath.size() - 1;
        while (assignmentsSeen < summaryBackwards) {
            if (i < 0) {
                LOGGER.trace("Cannot move summary order backwards by {}; only {} assignments segment seen: {}", summaryBackwards, assignmentsSeen, ctx.assignmentPath);
                return OrderAdjustment.undefined();
            }
            AssignmentPathSegmentImpl segment = ctx.assignmentPath.getSegments().get(i);
            if (segment.isAssignment()) {
                if (!ctx.ae.relationRegistry.isDelegation(segment.relation)) {
                    assignmentsSeen++;
                    LOGGER.trace("Going back {}: relation at assignment -{} (position -{}): {}", summaryBackwards, assignmentsSeen, ctx.assignmentPath.size() - i, segment.relation);
                }
            } else {
                // for i>0 returns value regardless of evaluateOld
                AssignmentType inducement = segment.getAssignment(ctx.evaluateOld);
                for (OrderConstraintsType constraint : inducement.getOrderConstraint()) {
                    if (constraint.getResetOrder() != null && constraint.getRelation() != null) {
                        LOGGER.debug("Going back {}: an inducement with non-summary resetting constraint found" + " in the chain (at position -{}): {} in {}", summaryBackwards, ctx.assignmentPath.size() - i, constraint, segment);
                        return OrderAdjustment.undefined();
                    }
                }
                if (segment.getLastEqualOrderSegmentIndex() != null) {
                    i = segment.getLastEqualOrderSegmentIndex();
                    continue;
                }
            }
            i--;
        }
        adjustment = new OrderAdjustment(ctx.assignmentPath.getSegments().get(i).getEvaluationOrder(), ctx.assignmentPath.getSegments().get(i).getEvaluationOrderForTarget(), i);
    } else {
        // summaryBackwards is 0 - nothing to change
        adjustment = new OrderAdjustment(currentOrder, currentTargetOrder);
    }
    if (adjustment.evaluationOrder.isDefined()) {
        for (OrderConstraintsType constraint : constraints) {
            if (constraint.getRelation() != null && constraint.getResetOrder() != null) {
                LOGGER.warn("Ignoring resetOrder (with a value of {} for {}) because summary order was already moved backwards by {} to {}: {}", constraint.getResetOrder(), constraint.getRelation(), summaryBackwards, adjustment.evaluationOrder.getSummaryOrder(), constraint);
            }
        }
    }
    return adjustment;
}
Also used : OrderConstraintsType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType) AssignmentType(com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType)

Aggregations

OrderConstraintsType (com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType)8 QName (javax.xml.namespace.QName)3 EvaluationOrder (com.evolveum.midpoint.model.api.context.EvaluationOrder)2 AssignmentType (com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType)2 ArrayList (java.util.ArrayList)2 EvaluatedExclusionTrigger (com.evolveum.midpoint.model.api.context.EvaluatedExclusionTrigger)1 EvaluatedAssignmentTargetImpl (com.evolveum.midpoint.model.impl.lens.assignments.EvaluatedAssignmentTargetImpl)1 AssignmentPolicyRuleEvaluationContext (com.evolveum.midpoint.model.impl.lens.projector.policy.AssignmentPolicyRuleEvaluationContext)1 PrismContainerValue (com.evolveum.midpoint.prism.PrismContainerValue)1 AccessDecision (com.evolveum.midpoint.schema.AccessDecision)1 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1 ObjectReferenceType (com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType)1 ObjectType (com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType)1