OrgSync Story Test

Last modified 07 Dec 2022 14:12 +01:00
Story tests

MidPoint contains a set of "story tests". Such tests implement almost complete midPoint deployment scenarios with all the configuration, resources and policies. These tests have a configuration that is almost real-world but the individual resources and data are simplified so we are able to automatically execute them as integration tests. This helps to make sure that midPoint works in situations that are very close to reality.

As the story tests contain almost complete sophisticated scenarios they are not only interesting to developers but also to system engineers. The configuration used in story tests can be used as an inspiration for midPoint configuration in similar real-world scenarios. Therefore pages like this one document the story tests. Each page describes the basic idea of the test and the most important part of the configuration that is used in the test.

Basic Idea

The tests demonstrates the synchronization of organizational structure and groups. The primary authoritative source is HR resource. The HR provides information about employees, organizational structure and "work responsibilities". MidPoint is using the data from HR to create an image of the corporate structures in LDAP server. Employees are synchronized to LDAP accounts that are placed into an organizational structure replicated from HR. The "responsibilities" from the HR are used to dynamically create midPoint roles and LDAP groups.

This test includes following features and policies:

  • Create user records from the HR employee records (basic inbound synchronization).

  • Create LDAP accounts (basic outbound provisioning).

  • Use the HR organizational structure information to create midPoint Orgs on demand and therefore opportunistically synchronize organizational structure from HR to midPoint.

  • Replicate midPoint organizational structure to LDAP organizational structure (generic synchronization).

  • Assign users to appropriate organizational units.

  • The assignment of users to organizational units is used to determine the LDAP organizationalUnit in which the user should be placed.

  • Use of object template and meta-role as a configuration of organizational structure generic synchronization policy.

  • The definition of "responsibilities" from the HR system is used to create midPoint roles dynamically.

  • LDAP groups are created automatically from midPoint roles.

  • LDAP accounts are added to the LDAP groups where they belong.

This configuration is using a "flat" strings from the HR system in the form "Kitchen/Scumm Bar/Ministry of Rum" to create LDAP structure such as:

  • dc=example,dc=com

    • ou=Ministry of Rum

      • ou=Scumm Bar

        • ou=Kitchen

          • uid=cook

          • uid=cookie

          • uid=monkey

This configuration also manages flat groups, therefore an LDAP group should be created for each HR responsibility in the ou=groups,dc=example,dc=com subtree.

Resources

Resource Type Definition Description

HR

Dummy

resource-dummy-hr.xml

Authoritative source.

OpenDJ

LDAP

resource-opendj.xml

Target Resource

HR

Authoritative source. It contains employee records, organizational structure and responsibilities. It contains:

Resource Objects kind intent Description

employee records

account

default

OpenDJ

Target resource. It contains "corporate directory" and it also somehow mimics the usual use of Active Directory in corporate environment.

TODO: structure

Resource Objects kind intent Description

user accounts

account

default

LDAP groups

entitlement

ldapGroup

Example of LDAP structure:

  • dc=example,dc=com

    • ou=Ministry of Rum

      • *ou=Scumm Bar*(organizational units created from "orgpath" data from HR)

        • ou=Kitchen

          • uid=cook

          • uid=cookie

          • uid=monkey

      • ou=Freelance

        • *uid=guybrush*(these accounts are place where they belong according to the HR)

    • ou=Ministry of Offense

      • ou=Department of Mischief

        • uid=otis*(these accounts are place where they belong according to the HR)
          *

        • *ou=Violence Section*(organizational units created from "orgpath" data from HR)

          • ou=Brute Office

            • uid=largo

    • ou=People

      • *uid=lemonhead*(accounts that are NOT in any organizational unit in HR. kind of catch-all ou)

      • uid=jack

    • ou=Groups

      • *cn=R_canibalism*(LDAP groups - based on responsibilities from HR)

      • cn=R_piracy

      • *cn=admins*(ordinary LDAP groups, manually managed, midPoint should not touch them)

Scenarios

Following sections describe some of the most important scenarios in this test. The designed outcome is described step-by-step. The entire scenario may look very complex at the first sight. But it is composed from several simple parts that are invoked one from another (and also recursively). This approach is used to a great advantage: we can use just a handful of simple mappings to support very complex scenarios. Just have a look at the configuration files. Each of them is quite simple. Yet they combine together to create something very powerful - and almost beautiful.

New HR Employee Record: Org

  1. New employee record appears in HR resource, e.g.:
    name: guybrush
    firstame: Guybrush
    lastname: Threepwood
    orgpath: Freelance/Ministry of Rum

  2. This record is picked up by livesync configured for HR resource. The synchronization part of HR resource definition. The reaction is addFocus therefore a new user is created.

  3. The account data are copied to the new user by inbound mappings on HR resource. Note that orgpath attribute from HR account is copied to custom orgpath property in user extension.

  4. User template takes over (object-template-user.xml)

    1. The first mapping computes user’s full name (this information is not stored in HR)

    2. The "Org mapping" is trying to look up an Org into which the user should belong. It is using a query inside assignmentTargetSearch expression to do so. The expression inside the query is using the first segment of the orgpath as a value, e.g. in this case it would be "Freelance".

    3. The query finds no matching Org. The expression is set to createOnDemand therefore it will try to create the Org. A new empty Org object is created in memory. Then the populateItem expressions are used to fill in this object. Please note how the orgpath value is copied from the user extension to the extension of the new Org object. Then midPoint calls itself internally to create a new Org object.

      1. Org object template (object-template-org.xml) takes over the processing of the new Org object.

      2. The "Org-org mapping" in object template tries to locate the parent for the new Org object. Similarly to the previous case assignmentTargetSearch expression with a query is used. Second segment of orgpath value is used (segment with index 1). E.g. "Ministry of Rum" in this case.

      3. The query finds nothing. The createOnDemand is set to true therefore midPoint will try to create such object. It will use populateItem expressions to fill it in and it will call itself to create new Org.

        1. …​ and the Org object template starts again recursivelly until all segments of orgpath are processed, all corresponding Org objects are created and correctly assigned to each other.

      4. The Org object template has another mapping. This mapping assigns a meta-role (role-meta-replicated-org.xml) to each created orgstruct. This meta-role contains inducement which specifies that a new ou resource object should be created as a projection for each Org.

        1. The projections are computed for an LDAP resource. The projections have a form of LDAP organizationalUnit objects. This is defined in the schema handling part of LDAP resource definition. The inducement specifies a (kind, intent) tuple which is used to locate a matching definition in the schemaHandling.

        2. The outbound mappings are used to compute a correct DN for the new "ou" object in LDAP. The orgpath property is once again used to compute a correct DN.

        3. LDAP organizationalUnit object is created.

        4. Note: midPoint Orgs are created in a correct order (from top to bottom) because of recursion in the org object template. MidPoint tries to complete the creation of each Org object before returning. This means that corresponding LDAP organizationalUnit is created before midPoint returns and completes the creation of lower Org object. This also means that LDAP organiazationalUnit objects are created in the correct order (top-to-bottom).

      5. Org object is now created in MidPoint. Also all its parents are (recursivelly) created. And as they all have the meta-role, corresponding LDAP organizationalUnit projection is created for each of them.

      6. Note: the user is not yet assigned to this org structure. The user does not even exists yet. All of this was just a "side-effect" of the mapping in a user template. But now we are getting back to the user …​

    4. We are back in the processing of user template. We have processed first two mappings and we are going to process the rest of them.

    5. The "basic role" mapping in user template is processed. This just assigns the "Basic User" role (role-basic.xml) . This is a simple RBAC role that assigns an LDAP account to the user.

    6. The last mapping is not used. User has no "responsibilities" in this case.

    7. User template processing finishes. The user now has a full name and two assignments:

      1. Assignment to the "Freelance" Org.

      2. Assignment of the "Basic User" role.

  5. The assignments are now computed.

    1. User is placed in the "Freelance" Org.

    2. The "Basic Role" assigns an LDAP account to the user. But does not specify anything else. The outbound mappings from the OpenDJ resource definition are used to fill in account attribute values.

      1. The outbound mappings are used especially to construct the DN of the account. The orgpath value is used once again to do that. The DN is constructed in such a way that the account is placed into a correct organizationalUnit object.

  6. Now we have everything to create the user in the repository and to create his LDAP account.

  7. Synchronization reaction is finished. Everything returns to normal. The liveSync task periodically checks for any new changes …​.

New HR Employee Record: Responsibility

  1. New employee record appears in HR resource, e.g.:
    name: lemonhead
    firstame: Lemonhead
    lastname: Canibal
    responsibilities: canibalism

  2. This record is picked up by livesync configured for HR resource. The synchronization part of HR resource definition. The reaction is addFocus therefore a new user is created.
    The account data are copied to the new user by inbound mappings on HR resource. Note that responsibilities attribute from HR account is copied to custom multi-valued property responsibility in user extension.

  3. User template takes over (object-template-user.xml)

    1. The first mapping computes user’s full name (this information is not stored in HR)

    2. The "Org mapping" is not used as there is no orgpath in this case.

    3. The "basic role" mapping in user template is processed. This just assigns the "Basic User" role (role-basic.xml) . This is a simple RBAC role that assigns an LDAP account to the user.

    4. The "responsibility role assignment" mapping is processed.

      1. The mapping is trying to look up a Role which the user should have assigned. It is using a query inside assignmentTargetSearch expression to do so. The expression inside the query is using the value of responsibility property from user extension to look up the role. The query is constructed in a such a way that this value should match with the value of responsibility property in role extension. Note that there are two properties that should match: the (multi-valued) responsibility in user extension and the (single-valued) responsibility in role extension. The mapping is smart enough to take care of handling multiple values of the property if they are present.

      2. The query finds no matching Role. The expression is set to createOnDemand therefore it will try to create the role. A new empty role object is created in memory. Then the populateItem expressions are used to fill in this object. Please note how the responsibility value is used to construct a name of the new role. The R_ prefix is used to avoid collistion with other roles in the system.

      3. When the role is populated then midPoint calls itself internally to store the new object in the repository.

        1. Role object template (object-template-role.xml) takes over the processing of the new role object before it is actually stored.

        2. The role object template has only one mapping which assigns a meta-role role-meta-responsibility.xml to the newly created role.

        3. The meta-role contains an inducement which specifies that a projection should be created for the role on the LDAP resource. The projection should be a group entitlement. This is specified by (kind, intent) tuple which points to the schema handling part of LDAP resource definition.

        4. The outbound mappings are used to compute a correct DN for the new group object in LDAP.

        5. New LDAP group is created.

        6. The meta-role also contains a second-order inducement. This is ignored right now. It will be interesting a little while later.

        7. Role provisioning is finished. The role is created in midPoint repository. A group is created on LDAP as a projection of that role: cn=R_canibalism,ou=groups,dc=example,dc=com. The group is empty for now.

      4. The processing of "responsibility role assignment" mapping in user template is finished.

    5. …​ and also the whole user template is finished. The user now has a full name and two assignments:

      1. Assignment of the "Basic User" role.

      2. Assignment of new "R_canibalism" role.

  4. The assignments are now computed. +

    1. The "Basic Role" assigns an LDAP account to the user. But does not specify anything else. The outbound mappings from the OpenDJ resource definition are used to fill in account attribute values.

      1. The outbound mappings are used especially to construct the DN of the account. There in orgpath value therefore a default DN with "ou=people" is used instead.

    2. The "R_canibalism" role is processed. The role itself only contains assignment to the meta-role. This would normally be ignored at this stage because the role already has a projection. But in this case there is a second-order inducement in the meta-role. This means that the inducement is not applied to the meta-role (as all inducements) and it is also not applied to the role. It goes "one level deeper" than usual and the inducement is applied to the user which has the "R_canibalism" role. This is our case.

    3. The second-order inducement includes an interesting expression: associationFromLink expression. This kind of expression is used to associate the user account (which is still to be created) and the entitlement which is linked to the role (it is a projection of the role). The use of this expression is associating the two resource objects dynamically, without any need to specify their OIDs or names. MidPoint already has all the information it needs. It is hidden in the labyrinth of assignments and links. The associationFromLink expression is using that information to construct the correct association. This association will place account in the correct group where it naturally belongs.

  5. Now we have everything to create the user in the repository and to create his LDAP account.

    1. A new LDAP object is created for user account. This is simple operation.

    2. However, adding account to a group is tricky. In LDAP this means modification of the group and not the account. Fortunately midPoint has a smart entitlements mechanism. The schema handling part of LDAP resource definition contains a definition of association between account and group which defines that the actual direction of the association is the other way around. MidPoint is quietly using that definition to automatically modify the group object right after the account is created.

  6. We are done. New role is created for "canibalism" responsibility. A new LDAP group is created as a projection of the role. New midPoint user is created and assigned to the canibalisitic role. And an LDAP account is created for the user which is automatically added as member of the canibalistic LDAP group. Almost like a magic.

  7. Synchronization reaction is finished. Everything returns to normal. The liveSync task periodically checks for any new changes …​.

Why?

All of this may seems a bit confusing for engineers that are used to traditional identity management systems. And actually midPoint can be configured exactly as a traditional identity management system if you choose to do so. Therefore the whole configuration could be made more "straightforward", using scripts and loops instead of recursion, using templates to copy information everywhere instead of using meta-roles and so on. However we usually choose not to do so. MidPoint can do better than that. Much much better.

E.g. traditional way is to copy the assignments/inducements to every new Org or role using an object templates. This works fine when the IDM solution is deployed. But things tend to change. Especially things related to organizational structure and job responsibilities. If an assignment/inducement is copied to thousand organizational units then it is quite difficult to change - and not to forget something. It is also difficult to roll back in case something goes wrong. This is the traditional way. Slow, expensive and risky.

We prefer to use meta-roles, expressions and higher-order inducements in midPoint deployments. In this case the policy is stored in the minimal number of places - ideally just one place. This means that the policy is consistent: it is applied everywhere where it should be applied. It is also easy to change and easy to roll back the change if needed. These mechanism can model even a very complex configurations as there is no theoretical limit to the depth of abstraction. Therefore you can have roles, meta-roles, meta-meta-roles, …​.

Was this page helpful?
YES NO
Thanks for your feedback