This tutorial describes the synchronization of groups (roles) from Active Directory / LDAP into IdM and how to customize it. From IdM 16 the logic lives in a Groovy synchronization script; up to IdM 15 it was a BPMN workflow. Both editions behave the same and are driven by the same application properties. After customizing it, the synchronization of groups can:
From IdM 16 the synchronization logic is no longer a BPMN workflow but a Groovy synchronization action script. Activiti was removed in IdM 16, so the former syncRoleLdap workflow was rewritten as the script syncRoleLdap (name Synchronization - Roles from LDAP, category SYNCHRONIZATION). The script ships in the acc module and can be edited directly in the Scripts agenda - no Eclipse or Activiti tooling is needed anymore.
To use it, set the script as the action script of the synchronization for the same three situations the old workflow handled:
The script is executed instead of the standard situation action - it calls the standard action itself through defaultSynchronizationService and then adds the extra behaviour (catalogue, role mapping, membership, automatic roles). A string returned by the script is appended to the synchronization item log.
The four workflow Data Objects are now hardcoded constants at the top of the main flow of the script. Change them directly in the script body when you need different values:
STRUCTURE_FORM_ATTRIBUTE (default `null`) - code of the tree node EAV used to look up an organization node by the role name (automatic role by organization structure). When it is `null`, the organization structure step is skipped.CODE_OF_TYPE_STRUCTURE (default `ORGANIZATIONS`) - code of the tree type whose organization structure is searched for the automatic role.AUTO_ROLE_ORG_STRUCTURE_ENABLED (default `false`) - enables creating automatic roles by organization structure.AUTO_ROLE_ATTRIBUTES_ENABLED (default `false`) - enables creating automatic roles by attributes.STRUCTURE_FORM_ATTRIBUTE = null; CODE_OF_TYPE_STRUCTURE = "ORGANIZATIONS"; AUTO_ROLE_ORG_STRUCTURE_ENABLED = false; AUTO_ROLE_ATTRIBUTES_ENABLED = false;
Everything else is externalized to idm.pub.acc.syncRole.* application properties, which the script reads once in taskGetAttributesFromProperties() (see Set application properties below).
The main flow of the script mirrors the flow of the original workflow. For a normal element it runs, in this order:
taskGetAttributesFromProperties() - reads all idm.pub.acc.syncRole.* properties once into script variables.taskSetAttributes() - reads the role name from the IC attribute `name` and the distinguishedName from the IC attribute named by attributeNameOfRoleIdentificator. It also builds transformationScript as the distinguished name wrapped in quotes - the successor of the former TRANSFORMATION_SCRIPT workflow variable.taskSetAutomaticRoleByOrgStructure() - resolves organizationTreeNode via treeTypeService.getByCode(CODE_OF_TYPE_STRUCTURE) and formService.findOwners(IdmTreeNodeDto.class, STRUCTURE_FORM_ATTRIBUTE, name, null). It is skipped when STRUCTURE_FORM_ATTRIBUTE is `null`.taskSetAutomaticRoleByAttributes() - builds the automaticAttributes array. The shipped body is only an example meant to be customized for your data.resolveCatalogue(distinguishedName) - sets catalogueId. It is skipped when the distinguished name is `null` or isResolveCatalogEnabled is `false`. When createAllRolesToOneCatalogue is `null`, a folder tree is built from the OUs of the distinguished name; otherwise all roles go into a single folder named by that property.taskResolveMembership() - assigns the role to the member identities.
The MISSING_ACCOUNT situation is handled first and returns early - it only calls defaultSynchronizationService.resolveMissingAccountSituation(…) and none of the steps above run.
The other three situations delegate to the standard action and then run the auto-roles-and-catalogue task:
MISSING_ENTITY - defaultSynchronizationService.resolveMissingEntitySituation(…), then taskCreateAutoRolesAndCatalog(), but only for actionType CREATE_ENTITY.LINKED - defaultSynchronizationService.resolveLinkedSituation(…), then taskUpdateAutoRolesAndCatalog(), but only for actionType UPDATE_ENTITY or LINK_AND_UPDATE_ENTITY.UNLINKED - defaultSynchronizationService.resolveUnlinkedSituation(…), then taskUpdateAutoRolesAndCatalog(), but only for actionType UPDATE_ENTITY or LINK_AND_UPDATE_ENTITY.
Both auto-roles-and-catalogue tasks set the canBeRequested flag on the role, add the role to the catalogue (addCatalogueForCreate / addCatalogueForUpdate), create the automatic roles (only if the constants above enable them) and call addResource(…). addResource(…) creates the memberOf mapping attribute (with the built transformationScript as the transformation) on the identity provisioning system, but only when systemCodeForRoleMapping (property idm.pub.acc.syncRole.provisioningOfIdentities.system.code) is set; otherwise it does nothing.
Finally, taskResolveMembership() assigns the role to the identities listed in the member attribute (the attribute named by idm.pub.acc.syncRole.roles.attributeNameOfMembership). Members are matched to identities by the EAV configured in idm.pub.acc.syncRole.identity.eav.externalIdentifier.code, and the role is assigned through a role request that is executed immediately. This runs for actionType CREATE_ENTITY, or in any situation when idm.pub.acc.syncRole.update.resolveMembership is `true`.
Two things are worth knowing when reading or customizing the script:
removeLastItemFromCatalogue() is now an empty stub. The old workflow logic that removed the previous catalogue folder when a role was moved to a different catalogue is gone; the method only resets the catalogue variable to `null`.scriptEvaluator binding variable (provided to every synchronization action script) is not used by this script.Both the script (IdM 16 and newer) and the workflow (up to IdM 15) are configured purely by application properties, so you can just add the properties below without changing the script or workflow file itself. Application properties are set in the Settings agenda, Configuration tab (like you can see on the picture below).
With the Add button you can add any of the properties described below and configure the synchronization.
Following properties are used, when the workflow is used for creating roles that manage group membership of accounts in a connected system:
Managing group membership of account - more special options for the roles:
idm.pub.acc.syncRole.roles.nameOfRoles.doNotSentValueOnExclusion and unset to all other AD roles.The workflow enables loading group membership from the system. That means, if the group in AD have some members and you want to assign roles to identities IdM based on that, you can use this workflow to do it. Typically, you would do it only as an initial loading. Necessary properties:
idm.pub.acc.syncRole.identity.eav.externalIdentifier.code above.Settings of the created role - properties connected to the requesting of roles and the role approval:
The workflow can create the folders in the role catalogue. It can be either one folder, or the tree structure of folders based on the DNs of the roles:
Since Extras version 1.8.0 you can use two new options which will help with following use case: I have more then 1 AD system connected as group source. Now the workflow has "global" configuration via application properties so I am not able to run scheduled synchronization and put group from one AD to catalog "one" and from second AD to catalog "two" and similar issue is with mapped systems. This changes are backward compatible because if you don't set these new properties the WF behavior is same as in previous version. If you set this property then the new behavior will be turned on.
In this tutorial we will be using Eclipse and the Activiti framework.
For synchronization of groups from AD, we have prepared the workflow syncRoleLdap.bpmn20.xml.
The workflow has these actions modified:
The workflow is divided into 9 activities, but only the first four activities are mainly to be modified.
First of all it is crucial to set the data objects in the Data Objects tab.
STRUCTURE_FORM_ATTRIBUTE - code of the EAV of an organization tree node. It is used to add an automatic role by organization structure. Every organization tree node should have an EAV with some value that determines which role gets an automatic role on which tree node.CODE_OF_TYPE_STRUCTURE - code of the structure; it defines which organization tree is used for searching/creating automatic roles by organization structure. The default value means the default organization tree.AUTO_ROLE_ORG_STRUCTURE_ENABLED - if false, automatic roles by organization structure are skipped.AUTO_ROLE_ATTRIBUTES_ENABLED - if false, automatic roles by attributes are skipped.
This activity gets some attributes from icAttributes, such as name and distinguished name. You can get others if they are needed in the following activities. This variable is also set:
execution.setVariable("TRANSFORMATION_SCRIPT", "\""+distinguishedName+"\"");
The value of this variable is used as the transformation script (it is used for provisioning the member attribute of identities).
In this script it is crucial to find, for a role, the tree node (organization) used to create the automatic role by organization structure, and to set it to a variable like:
execution.setVariable("organizationTreeNode", pomList.get(0));
This script can be slightly changed to work fine. In the default state it searches for a tree node that has the name of the role in an EAV. In a previous activity we can get another attribute and, using a substring, it should be enough.
This part creates the attributes for an automatic role. There can be more attributes, but only for identity/contract attributes or identity/contract EAVs. You should create the attributes (by the default algorithm), put them into the field and lastly into the "automaticAttributes" variable.
This part is about the role catalogue. There are two methods. The first method creates the catalogue based on the distinguished name of the role: the rightmost OU value is the root of the catalogue, the other OUs from the right become folders, and roles are assigned in the leftmost OU/catalogue.
The other method is for removing folders of a catalogue: if a role is transferred to another catalogue, it finds the old one and sets it in the "catalogue" variable, and it is erased.