<policyRule>
<policyConstraints>
<or>
<modification>
<item>name</item>
</modification>
<modification>
<item>fullName</item>
</modification>
</or>
</policyConstraints>
<policyActions>
<scriptExecution>
<object>
<linkTarget>
<archetypeRef oid="........"/>
</linkTarget>
</object>
<executeScript>
<s:recompute/>
</executeScript>
</scriptExecution>
</policyActions>
</policyRule>
Linked Objects
Linked objects feature
This page describes configuration of Linked objects midPoint feature.
Please see the feature page for more details.
|
Since 4.2
This functionality is available since version 4.2.
|
Introduction
MidPoint objects do not live in isolation. Often they need to take data from related objects. And so if an object changes, the change needs to be cascaded to related objects.
This page introduces the topic theoretically. For code samples, see:
Links between objects
There are many kinds of links among objects. They are differentiated by the relation attribute of a particular object reference. (For more information on relations, see Relation and Relation Configuration.)
These are typical situations when two objects are linked:
Situation | Link source | Link target | Relation | Note |
---|---|---|---|---|
User A has a role R. |
User A |
Role R |
org:default |
|
User A is a member of org O. |
User A |
Org O |
org:default |
|
User A is a manager of org O. |
User A |
Org O |
org:manager |
|
User A is an owner of token T. |
User A |
Service T (archetyped as token) |
org:default |
(Or org:owner.) |
User A is a child of user B. |
User A |
User B |
custom:child |
Currently unsupported. The only user-user assignments we support are delegation assignments. |
Role R has a metarole M. |
Role R |
Role M |
org:default |
(Or org:meta.) |
User A is an approver for role R. |
User A |
Role R |
org:approver |
Assignments vs. links
A link between two objects can be:
Type of link | Stored in | Note |
---|---|---|
prescribed |
|
|
actual |
|
Besides roles, |
So the link between two objects (A → B) can be in one of the following states:
Prescribed | Actual | Description |
---|---|---|
Yes |
Yes |
The usual case.
There is an assignment from A to B. The assignment is valid and effective, so the information is in |
Yes |
No |
There is an assignment from A to B. But it is either invalid (from the activation point of view) or not effective (from the conditions point of view), so there is no record in |
No |
Yes |
There is no direct assignment from A to B, but the link was created indirectly, e.g., via an inducement, such as from A to B, where B induces C. So A → C is not prescribed but actual. |
No |
No |
A and B have no link altogether, or there is an indirect assignment that is not valid or not effective. |
Navigating links
Each link has two participants:
Participant | Meaning |
---|---|
Link source |
Object that has something linked. Usually it is the holder (owner) of the respective assignment. |
Link target |
Something that is linked to the object. |
In mappings we can use the following methods to find the other side of our links:
Method | To be invoked on | Meaning | Search criteria | Version returning single object |
---|---|---|---|---|
|
link source |
Returns all linked objects matching specified criteria. |
object type, archetype (experimental: link type name) |
|
|
link target |
Returns all objects that have the current one as link target. |
object type (experimental: link type name) |
|
Note that findLinkedTargets
should be used only after assignments are processed as it needs fresh information from assignment evaluation.
Therefore:
-
You cannot use
findLinkedTargets
in inbound mappings. -
If you use
findLinkedTargets
in object templates, you need to specify theevaluationPhase
ofafterAssignments
. -
You can use
findLinkedTargets
in assigned/induced focus mappings or resource outbound mappings.
On the other hand, findLinkedSources
has no such limitation.
For examples, see individual scenarios for linked objects.
The On the other hand, |
Cascading the changes
We often need to recompute one side of the link when relevant parts of an object on the other side (or the link itself) change.
We usually use a policy rule with a scriptExecution
policy action for this.
Selecting objects to be recomputed
The scriptExecution
policy action has an option to specify objects to which the given midPoint script (action) should be applied.
This option is called object
and has the following values:
Option | Cardinality | Action is run on | Option value type | Note |
---|---|---|---|---|
|
single |
The current focus object. This is the default if nothing is specified. |
|
|
|
multiple |
Objects that are targets of links coming from this object (i.e. results of assignments of this objects) are recomputed. |
|
|
|
multiple |
Objects that are sources of links coming to this objects (i.e. objects that have assignments to this object) are recomputed. |
|
|
|
multiple |
A shortcut for |
|
Experimental. May be removed. |
|
multiple |
A shortcut for |
|
Experimental. May be removed. |
Object sets coming from individual options and also from individual values of these options are added together.
The values of the above options are used to select what specific link targets or sources to use; and under what conditions the current object is to be selected. You can use these filters (and-ed together when present in a single value):
Filter | Meaning | ObjectSelectorType | LinkTargetObjectSelectorType | LinkSourceObjectSelectorType |
---|---|---|---|---|
|
Type of the object. |
yes |
yes |
yes |
|
Subtype of the object. |
yes |
yes |
yes |
|
Archetype of the object. |
yes |
yes |
yes |
|
Top node of an organizational hierarchy. This node and all of its subnodes (transitively, unlimited depth) are considered matching. |
yes |
yes |
yes |
|
Filter that an object must match to be considered selected. This filter MUST NOT contain organization unit clauses. It may only contain property clauses, logical operations and so on. |
yes |
yes |
yes |
|
Link matches if it has any of the relations specified. (If no relation is specified, all relations match.) |
yes |
yes |
|
|
Name of the declared link type. (Experimental) |
yes |
yes |
|
|
Filters objects to which policy actions apply based on how links to those objects have changed. See the available values. |
yes |
||
|
The link target is related to the assignment that brought this policy rule to the focus object.
This setting can eliminate the need to specify linked targets, e.g., via archetype, if the archetype itself brings this policy rule to the object. |
yes |
||
|
The link target was matched by a policy constraint in this rule (e.g., an assignment modification constraint has a target object equal to the assignment target).
This setting can eliminate the need to specify linked targets, e.g., by using archetypes. |
yes |
Possible values of the changeSituation
filter are:
Value | Meaning | Old existence | New existence |
---|---|---|---|
|
Always matches (default), even if the link was removed. |
any (X) |
any (Y) |
|
Matches only if the link has been added. |
false |
true |
|
Matches only if the link has been removed. |
true |
false |
|
Matches if the link exists in the new state. |
any (X) |
true |
|
Matches if the link exists in the old state. |
true |
any (X) |
|
Matches if the state of the link’s existence has changed, i.e., if it has been added or removed. |
any (X) |
not X |
|
Matches if the state of the link’s existence has not changed. |
any (X) |
X |
This rule triggers a recomputation of all linked objects with specified archetype when the name
or fullName
of the current object is modified.
For more information on object recomputation, see recompute.
Asynchronous execution
In situations where there are many objects to be recomputed, you can specify asynchronous execution, i.e., execution of the recomputation in the context of a background task.
This is done using the asynchronousExecution
item containing the following options:
Option | Meaning | Example |
---|---|---|
|
Mode of asynchronous script execution. |
|
|
Reference to the task template, i.e., the task that is used as a template (prototype) of the actual task being created. |
|
|
An expression that takes a task and customizes its content. |
Asynchronous execution modes
The following modes are available:
Execution mode | Meaning | Note |
---|---|---|
|
Uses an iterative scripting handler, i.e., an object query with a script that processes every object found. |
This is the default and recommended option. |
|
Uses a single-run scripting action. Input for this action contains references to objects that should serve as action inputs. |
To be used only in complex and advanced cases.
When in doubt, use |
|
Uses single-run scripting action without any explicit input. |
Task templates
The task template can contain any options you want to be present in the final task.
Its state should be waiting
or closed
to avoid being run independently.
The following items are set for the final task (so overwriting the items present in the template):
Item | Meaning | Value set |
---|---|---|
|
Task name |
Name of the task template (or Execute script if no template is specified) plus a random number suffix. |
|
Task owner |
Currently logged-in user, or the user specified in |
|
Task execution status |
|
archetype assignment |
Task archetype |
|
taskTemplateRef
can contain an object filter, even with expressions.
Those expressions can refer to the focus
, policyAction
, policyRule
and configuration
. variables.
<asynchronousExecution>
<executionMode>iterative</executionMode>
<taskTemplateRef>
<filter>
<q:text>
. inOid ```
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType
focus instanceof OrgType ? '9c50ac7e-73c0-45cf-85e7-9a94959242f9' : '9107b8a4-0a0a-4e82-a4c6-9d84034f9d6e'
```
</q:text>
</filter>
</taskTemplateRef>
...
</asynchronousExecution>
Task customizer
You can specify any other task properties (or delete any pre-set ones) using a special expression that expects preparedTask
as its input and should return a modified task object.
The returned object can be the one that was received as input (with necessary modifications).
<asynchronousExecution>
<taskCustomizer>
<script>
<!-- This script assumes the existence of the `memberRecomputationWorkerThreads` integer property in the `ModelExecutionOptionsType` extension.
It uses the value of this option to set worker threads (mext:workerThreads task property) for given task. -->
<code>
log.info('Task being prepared = {}', preparedTask.asPrismObject().debugDump())
preparedTask.description = 'Hello there'
workerThreads = midpoint.getExtensionOptionRealValue('memberRecomputationWorkerThreads')
basic.setTaskWorkerThreads(preparedTask, workerThreads)
preparedTask
</code>
</script>
</taskCustomizer>
</asynchronousExecution>
Delaying recomputation using triggers
There are situations when you want to delay the recomputation. A typical case is when you want to recompute members of abstract roles that are (potentially) changed on a larger scale. For example, when they are synchronized from a resource. Or if they are modified using an action. Or if it is simply expected that users are going to edit more roles via GUI in a short period of time (relative to the time needed to recompute members of those roles).
In such cases you can set a recompute trigger on the relevant objects instead of recomputing them immediately. The trigger can be set either unconditionally, or for a given time in the future. The latter option optimizes even the creation of the triggers by skipping triggers that are known to be redundant. See recompute for more details.
Note: Triggers can be set synchronously or asynchronously. The asynchronous option is suitable for roles with lots of members.
Enabling/disabling the change propagation
To enable/disable change propagation directly when submitting operations, e.g., via GUI, midPoint uses the concept of ModelExecuteOptions
extension items. You can define these using the standard extension mechanism, for example:
<xsd:schema elementFormDefault="qualified"
targetNamespace="http://midpoint.evolveum.com/xml/ns/samples/linked"
xmlns:tns="http://midpoint.evolveum.com/xml/ns/samples/linked"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:a="http://prism.evolveum.com/xml/ns/public/annotation-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="ModelExecutionOptionsTypeExtensionType">
<xsd:annotation>
<xsd:appinfo>
<a:extension ref="c:ModelExecuteOptionsType"/>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="tns:recomputeMembers" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="recomputeMembers" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation>
Enables or disables recomputation of members - for abstract roles or their archetypes
that look at this extension property.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>
And then you could check for this option in conditions related to the particular policy rules, for example:
<inducement>
<policyRule>
<documentation>
When department cost center changes, members must be recomputed
(unless explicitly disabled in execution options).
</documentation>
<policyConstraints>
<modification>
<item>costCenter</item>
</modification>
</policyConstraints>
<policyActions>
<scriptExecution>
<object>
<linkSource/>
</object>
<executeScript>
<s:recompute/>
</executeScript>
<asynchronousExecution/>
</scriptExecution>
</policyActions>
</policyRule>
<condition>
<expression>
<script>
<code>midpoint.extensionOptionIsNotFalse('recomputeMembers')</code>
</script>
</expression>
</condition>
</inducement>
The specific options cannot be (now) set via GUI. However, they can be specified in actions, synchronization reactions, or anywhere where the model API is called from a Java or Groovy code. In the future we will also implement support for REST calls.
TODO
Authorizations should be checked when processing execution options. Currently they are not. |
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
<executeOptions>
<extension>
<linked:recomputeMembers>false</linked:recomputeMembers>
</extension>
</executeOptions>
</reaction>
Security aspects
-
The
midpoint.findLinkedSources
andfindLinkedTargets
methods use the model API to retrieve objects, so they are executed under privileges of the currently logged-in user. You can use therunAsRef
mechanism in expressions to define a different user, if needed. -
Scripts (actions) in scripting policy rules also execute under privileges of the currently logged-in user. You can use
scriptExecution.runAsRef
to define a different user.
There is one exception, though: to increase performance, the search for relevant objects (linked sources or targets) is done directly via the repository. So the security is not being applied there. This might change in the future.
Performance considerations
There are many topics related to performance to consider, including the following:
-
Should change propagation be processed in the foreground or background?
If there are only a few linked objects, and if their recomputation is fast, it can be done on the foreground. If you only want to trigger the recomputation via triggers, it can be also done in the foreground (even for a slightly larger sets of linked objects). But for all other cases, background processing is preferred. And, if processing more focus objects with potentially overlapping sets of linked objects, using triggers is strongly advised to avoid repeated recomputation. -
Where should you use change propagation policy rules?
For example, in the user device scenario (Linked objects scenario 2: Devices owned by users), policy rule that causes the recomputation of linked devices can be put either into the user archetype (with order 1 inducement) or the device archetype (with order 2 inducement).
The advantage of the latter case is that it is applied to the user only if the user has at least one device (so sparing some processing time.) The disadvantage is that if a user has multiple devices, the policy rule is present multiple times: once for each device. And here comes the distinction: if the rule recomputes all devices, this would lead to their repeated recomputation. So, if you have a rule that recomputes all linked objects of a kind, then it should be induced only once, i.e. assigned to the user from the user archetype. If the rule recomputes only relevant devices (using thematchesRuleAssignment
ormatchesConstraint
clause) or it is expected that there is at most one matching linked object, it can be attached to target’s archetype. -
Looking for sources and targets in the
midpoint.findLinkedSource
andmidpoint.findLinkedSource
methods.
The former uses a traditional repository query, as it has no hints of who the sources could be. It can be fast or slow, depending on the complexity of the query and the number of objects returned. Fortunately, the result should be cached (locally or globally), so the repo cost will be incurred only once. When looking for targets, the candidate set of objects is taken from assignments and preliminarily filtered on object type. However, further filtering requires fetching these objects by their OID. In extreme cases, that might present hundreds of objects. The repo calls should be cached. However, in both cases, the objects pass the modelgetObject
/searchObjects
methods, so all the model processing (security, template, post read hooks) is applied. And as it is not treated by cache, it is applied each time those methods are used. If this is an issue, you need to write your own (optimized) versions of these methods or, providing that a platform subscription is in place, request such changes from Evolveum.
Compliance
This feature is related to the following compliance frameworks: