[midPoint] Assignment Mapping Inconsistency in change deltas

Brandon Powers brandon at exclamationlabs.com
Mon Nov 19 23:25:56 CET 2018


Hi all,

There seems to be a bug with the way template object assignment mappings
are processed (specifically how deltas are established for assignments:
plus set, minus set, and zero set).
(This functioned correctly when our implementation was on MidPoint version
3.6.1, but since has experienced the issue below after upgrading to
MidPoint 3.8 and 3.9)

Given the following:
- A defined user template mapping used for automatic assignment of an
organization to a user using `assignmentTargetSearch`
- Assignment is based on multiple sources where a source element can and is
expected to be null occasionally (does/should not affect resulting
assignment, additional attribute is used solely for parametric assignment
attributes)
- Assignment is authoritative
- A range is specified so that assignments can be automatically removed
when they no longer apply according to the mapping
- User attributes are set via inbound mappings from a source-of-truth
resource (HR system) (not necessary to reproduce error, same issue will
surface when changes originate using midpoint GUI)

During normal execution, all source elements are accounted for and used to
execute the mapping expression. The resulting organization found by the
`assignmentTargetSearch` is assigned to the user.

An additional source element (in this example, a user schema extension
attribute named transfer_date) for the mapping is used to determine
assignment activation dates if the source element is present.  If not
present, no activation date is applied to the assignment (note, this
particular example uses the additional source element for activation dates,
but the problem exists in all scenarios with source elements - in fact, a
source element need not even be used in the mapping expression otherwise)

Scenarios:
1. A User transfer date is NOT specified.
Expectation: Assignment mapping assigns the Department Organization
(without an activation date)
Reality: Matches Expectation

2. A User Transfer date is specified
Expectation: Assignment mapping removes the Department Organization
assignment (without an activation date), and replaces it with a Department
Organization assignment with an activation date)
Reality: Matches Expectation

3.  A user Transfer date is removed
Expectation: Assignment mapping removes the Department Organization
assignment with an activation date, and replaces it with a Department
Organization assignment (without an activation date)
Reality: On initial user template mapping processing (via import from
resource or otherwise), the assignment mapping only removes the Department
Organization assignment with an activation date.  It does NOT replace it
with a Department Organization assignment (without an activation date).
Later reconciliation of the user results in assignment of the Department
Organization accordingly.  However, this results in a brief period of time
where the assignment on the user does not exist, which triggers account
changes on all resources that the assignment influences.

Upon further investigation and debugging, I found that the delta being
created for this assignment mapping in scenario 3 does not contain a plus
set delta to add the new assignment, but rather, only a minus set delta
removing the old assignment.

This issue does not surface when the transfer date source element simply
changes value (for instance date change from 11/29/18 to 11/28/18 (or from
NULL to 11/27/18), but only when a source element changes from having a
value to NULL)

Below is the mapping trace indicating the reality during scenario 3:
2018-11-19 17:07:36,052 [] [http-nio-8080-exec-113] INFO
(com.evolveum.midpoint.model.common.mapping.MappingImpl): Mapping trace:
---[ MAPPING 'Job Department Org mapping'  in template mapping 'Job
Department Org mapping' in
objectTemplate:6350aab5-a943-4d61-a934-ac20517084e3(Default User
Template)]---------------------------
Stregth: STRONG
Source department:
  old: PP({http://example.com/xml/ns/mySchema}department):[PPV(String:154 -
South Berkeley)]
  delta: null
  new: PP({http://example.com/xml/ns/mySchema}department):[PPV(String:154 -
South Berkeley)]
Source transfer_date:
  old: PP({
http://example.com/xml/ns/mySchema}transfer_date):[PPV(XMLGregorianCalendarImpl:2018-11-28T00:00:00.000-05:00
)]
  delta: PropertyDelta(extension / transfer_date, REPLACE)
*  new: PP({http://example.com/xml/ns/mySchema}transfer_date):[]
<http://example.com/xml/ns/mySchema}transfer_date):[]>*
Source transfer_department:
  old: null
  delta: null
  new: null
Target: PCD:{.../common/common-3}assignment
{.../common/common-3}AssignmentType[0,-1],RAM
Expression: assignmentExpression
Condition: true -> true
*Result: removed: id=null: 4 items*
------------------------------------------------------

Does anyone have a method to get around this issue or might there be a bug
fix in the works for this already? I've spent considerable time debugging
the ObjectTemplateProcessor and related code, but am having trouble getting
closer to the root of the problem.

Below is the example Object Template (attached for reference as well):

<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Default User Template
-->

<objectTemplate xmlns="
http://midpoint.evolveum.com/xml/ns/public/common/common-3"
                xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
                xmlns:c="
http://midpoint.evolveum.com/xml/ns/public/common/common-3"
                xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
                xmlns:org="
http://midpoint.evolveum.com/xml/ns/public/common/org-3"
                xmlns:icfs="
http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3
"
                xmlns:ri="
http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                oid="6350aab5-a943-4d61-a934-ac20517084e3"
                version="18">
    <name>Default User Template</name>
    <description>
        User Template Object
    </description>

    <mapping>
        <name>Job Department Org mapping</name>
        <trace>true</trace>
        <description>
            Look for appropriate Org objects by using the user's department
property
            as the name of the org object. When no such object is found we
want to create it on
            demand. We want to populate new Org object with a name derived
from the user.
        </description>
        <authoritative>true</authoritative>
        <strength>strong</strength>
        <source>
            <name>department</name>
            <c:path>extension/department</c:path>
        </source>
        <source>
            <name>transfer_date</name>
            <c:path>extension/transfer_date</c:path>
        </source>
        <expression>
            <assignmentTargetSearch
xsi:type="c:SearchObjectRefExpressionEvaluatorType">
                <targetType>c:OrgType</targetType>
                <filter>
                    <q:equal>
                        <q:path>c:name</q:path>
                        <expression>
                            <path>$user/extension/department</path>
                        </expression>
                    </q:equal>
                </filter>

                <!-- Populate assignment fields -->
                <populate>
                    <populateItem>
                        <expression>
                            <script>
                                <code><![CDATA[
                                    if (transfer_date != null) {
                                        return transfer_date
                                    }
                                ]]></code>
                            </script>
                        </expression>
                        <target>
                            <path>activation/validTo</path>
                        </target>
                    </populateItem>
                    <populateItem>
                        <target>
                            <path>description</path>
                        </target>
                        <expression>
                            <value>Department</value>
                        </expression>
                    </populateItem>
                    <populateItem>
                        <target>
                            <path>extension/assignmentType</path>
                        </target>
                        <expression>
                            <value>DEPARTMENT</value>
                        </expression>
                    </populateItem>
                </populate>

                <createOnDemand>true</createOnDemand>
                <!-- Populate organization fields -->
                <populateObject>
                    <populateItem>
                        <expression>
                            <c:path
xsi:type="t:ItemPathType">$user/extension/department</c:path>
                        </expression>
                        <target>
                            <c:path>name</c:path>
                        </target>
                    </populateItem>
                    <populateItem>
                        <expression>
                            <value>Job Department</value>
                        </expression>
                        <target>
                            <c:path>orgType</c:path>
                        </target>
                    </populateItem>
                    <populateItem>
                        <expression>
                            <assignmentTargetSearch
xsi:type="c:SearchObjectRefExpressionEvaluatorType">
                                <targetType>c:OrgType</targetType>
                                <filter>
                                    <q:equal>
                                        <q:path>c:name</q:path>
                                        <expression>
                                            <value>Job Department</value>
                                        </expression>
                                    </q:equal>
                                </filter>
                            </assignmentTargetSearch>
                        </expression>
                        <target>
                            <c:path>assignment</c:path>
                        </target>
                    </populateItem>
                </populateObject>
            </assignmentTargetSearch>
        </expression>
        <condition>
            <script>
                <code>
                    department != null
                </code>
            </script>
        </condition>
        <target>
            <c:path>assignment</c:path>
            <set>
                <condition>
                    <script>
                        <code><![CDATA[
                            import javax.xml.namespace.QName;

                            // Get Assignment Extension attributes
                            def ext = input.getExtension()
                            if (ext == null) return false;

                            // Get Extension Attribute "assignmentType"
                            ASSIGNMENT_TYPE_QNAME = new QName("
http://example.com/xml/ns/mySchema", "assignmentType");
                            def assignmentType =
ext.asPrismContainerValue().findProperty(ASSIGNMENT_TYPE_QNAME);
                            if( assignmentType == null) return false;

                            log.info("DEPARTMENT CONDITION - ASSIGNMENT
TYPE: {}", assignmentType.getValue().getValue() );
                            log.info("DEPARTMENT CONDITION - ASSIGNMENT
TYPE MATCH: {}", assignmentType.getValue().getValue() == "DEPARTMENT" );
                            return assignmentType.getValue().getValue() ==
"DEPARTMENT"

                        ]]></code>
                    </script>
                </condition>
            </set>
        </target>
    </mapping>

</objectTemplate>


Brandon Powers
Exclamation Labs
300 Washington Street
Cumberland, MD 21502
888.545.5008 or 301.722.5008 ext 144
fax 301.722.2183
brandon at exclamationlabs.com
www.exclamationlabs.com <brandon at exclamationlabs.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.evolveum.com/pipermail/midpoint/attachments/20181119/0d9d6b0e/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: example-department-mapping.xml
Type: text/xml
Size: 6852 bytes
Desc: not available
URL: <https://lists.evolveum.com/pipermail/midpoint/attachments/20181119/0d9d6b0e/attachment.xml>


More information about the midPoint mailing list