FIM Data Modelling and Sync Design: Reference Attributes Versus String Attributes
A big part of a successful MIM (previously FIM) design comes down to how effectively you model your data, and define the MIM schema to represent your data model …
Background
For this article, consider the default Person object (which I will refer to as /Person to identify this as a MIM resource type) and some form of related meta data derived from their incumbent position(s).
When an HR feed can provide a position code attribute on a person, and you want to define MIM policy for provisioning group membership in AD based on this attribute, it is tempting to load this as a string attribute binding (say /Person.PositionCode) into MIM and define a set such as All People in position XXX using an xpath filter statement such as this:
/Person[PositionCode=’XXX’]
This does the job, right?
Well yes, in some cases maybe, but consider the following...
Scenario Variations
You have 100s or 1000s of positions and you want to automate the provisioning of a group per position with active incumbent employees, and the de-provisioning of a group when the last member (incumbent employee) is removed
A person can occupy more than one position at a time, and you wish to define groups or sets based on partial string matches on position code
You wish to define group or set membership based on some other property of a /Position (e.g. approval level, start/end date, reporting-to position)
You want to derive the manager reference based on reports-to-position
You want to define a “relative to resource” MPR “Managers can maintain selected attributes of their employees” based on the subordinates of a manager derived from the reports-to-position
In order to be able to satisfy ALL of the above requirements you will see that you are going to need to define a new /Position object, and assign bindings of its own (e.g. all of the above properties in #3 and some …) and then have a reference type binding on /Person, say Person.PositionID? What effort is involved in doing this, and is it worth the effort? I am going to show you that the answer is a resounding YES!!!
Working with string bindings
Let’s consider each of the above scenarios, firstly with the STRING binding model, using every ounce of lateral thinking I can muster ...
You can easily create a handful of groups by hand, but what about automating them? One approach might be to create a PowerShell script if you have access to an authoritative source of position codes. However, you will be introducing management inefficiency because you will not be able to intelligently trigger the ongoing running of this script to create new groups (or delete existing ones). So this requirement is potentially do-able with a string attribute, but not really manageable.
With a multi-valued string binding I can still define sets and groups with xpath like the above, however you cannot do partial searches like this:
/Person[starts-with(PositionCode,’XX’)].
Therefore you can define groups or sets based on full but not partial string matches. Without the partial search requirement, again this is do-able but not manageable … however it is impossible to meet this requirement in full. In some (but not all) HR systems you might find that a person cannot occupy more than one position concurrently … which would make this argument a moot point. However, if there is no problem with position, then can the same be said of other one-to-many possibilities, such as location or job role? Consider the scenario where an employee has ongoing work split over multiple locations … such as a teacher who is at school A from Monday to Wednesday, and school B from Thursday to Friday …
If all you have on the /Person object is a single-value string PositionCode, then you might think you’re just going to need additional attributes derived from /Position and bound to /Person. This works OK in some scenarios, but comes at a cost … consider the storage overhead for a large implementation (say 500K users) in storing not only Person.PositionCode, but also Person.PositionTitle, Person.PositionStartDate, Person.ReportsToPosition, etc. The real problems come when you need to support multiple positions … apart from not being able to do partial searches (like 2 above), you cannot store position data in this way and expect to be able to know which of the 3 position codes you have for a given person relates to which of the 3 position titles, start dates, reports-to-positions, etc. In a database design this would be tantamount to a design flaw, and you would traditionally approach the problem through Normalization – MIM is no different.
If you wanted to derive Person.Manager (a reference attribute) from Person.ReportsToPositionCode, then one way to do this might be to follow the inbound sync rule activity with some custom activities to (a) lookup and (b) store the result of a MIM query to return the manager … which could be returned by the xpath query: /Person[PositionCode = ‘[Target/ReportsToPositionCode’]. There is at least one problem I can see with this approach, however, and that is when the manager and their subordinate are being imported for the first time into MIM in the same sync cycle, whereby the lookup has the potential to fail depending on the sequence of the import … something that the sync engine overcomes by design. Far better, then, to derive the manager attribute as a reference attribute in the first place, as part of the inbound Sync Rule policy from your HR source
Similar to #4 above, but in the reverse, you want to derive Person.Subordinates from Person.ReportsToPositionCode, and again you could do this with custom activities but with the same draw-backs (timing). Again, far better to define a multi-value reference attribute as part of an inbound sync rule.
Working with reference bindings
OK, so let’s say we’ve bitten the bullet and decided to implement a new MIM resource type Position, and define reference attribute bindings as required, populated using inbound sync rules as appropriate. In saying this, let’s just ignore the fact that getting our HR source to present these reference attributes is non-trivial … unless your HR source happens to be an LDAP directory ...
Now let’s consider each of the above scenarios, and how you would approach this:
We can now provision both a /Group (default schema – but with a new reference binding of PositionID) and a /Position resource to MIM, together with a PositionID binding on /Person. What I have then done is the following (I won’t go into the detail here):
Define MIM policy such that a /Group is provisioned for any /Position for which there is at least one /Person object occupying that position.
When provisioning the /Group object to MIM (where there is at least one person occupying the corresponding Position), use the Function Evaluator activity to set the Filter attribute to the following xpath: /Person[PositionID=’<guid of Group.PositionID>’]
Define MIM policy such that any /Group with a PositionID for which there are no /Person object occupying that position is deleted (deprovisioned).
By making the PositionID binding on a /Person a multi-value reference attribute, persons can effectively occupy multiple positions at the same time. The following is then an example of a filter definition(s) for a set or group matching on partial position code:
Set A (all positions starting with XX):
/Position[starts-with(DisplayName,’XX’)]
Set/Group (all persons occupying a position starting with XX) B:
/Person[PositionID = /Set[ObjectID=’<guid of Set A>’]/ComputedMember]
Similar to #2 above, the following is then an example of a filter definition(s) for a set or group matching on a particular property of position:
Set A (all positions with approval level 1):
/Position[ApprovalLevel=’1’’]
Set/Group (all persons occupying a position with approval level 1) B:
/Person[PositionID = /Set[ObjectID=’<guid of Set A>’]/ComputedMember]
You use the reports-to-position relationship to derive a single-value reference attribute “manager” in the authoritative HR source and import this to MIM via a (direct) inbound sync rule. This binding then allows you additional flexibility in defining MIM policy, such as use of the “Relative To Resource” style MPR.
You use the reports-to-position relationship to derive a multi-value reference attribute “subordinates” in the authoritative HR source and import this to MIM via a (direct) inbound sync rule. Again, this binding then allows you additional flexibility in defining MIM policy, such as use of the “Relative To Resource” style MPR.
Bringing it all together
OK – so I’ve over-simplified the role of the HR MA in magically generating reference attributes to directly import your reference data into MIM. As I said above, it would be wonderful if your HR source was an LDAP or DSML compliant directory, and not the relational database application that they tend to be in 99 times out of 100. The MIM Sync engine is optimised to work with LDIF or DSML data sources, and invariably you need to start building your own Extensible Connectivity Management Agents (ECMAs or XMAs) to derive the necessary features you need in your HR MA (multiple object classes, multi-valued attributes, reference attributes, delta imports, bi-directional attribute flows, etc.)
Secondly – if you’re trying to execute MIM run profiles on a repeated schedule, you will find that it takes many schedule executions to eventually see the desired effect of say a change in HR location and position for an employee translated to a change in OU and group membership in AD. It takes many sync cycles to achieve the necessary outcomes, including ERE and DRE creation. Far better to run MIM in an event-driven manner to achieve near-real-time outcomes.
3rd party tools
Note
The tools I use to achieve the above for my MIM solutions are as follows
- UNIFY Identity Broker for HR applications – in a nutshell this presents any number of HR (or HR-like) applications/data sources to MIM in the form of an LDAP compliant directory (LDIF file ECMA), including all the features described above (multiple object classes, multi-valued attributes, reference attributes, delta imports, bi-directional attribute flows, etc.)
- UNIFY's MIM Event Broker – allows you to run MIM sync operations, and any other related activities, in an event driven manner (e.g. pending inbound changes in the MIM Portal, AD, HR, etc. can trigger delta import/sync run profiles immediately, and pending outbound changes from the MIM metaverse can trigger export run profiles to run immediately (or delayed if desired)
I hope this article sheds some light on how traditional data modelling methods can be applied to MIM to model common enterprise IAM requirements, with the help of some complementary technologies to present HR data as an LDAP directory, and to “event enable” MIM synchronization policy delivered via the MIM sync service.