Thursday 30 September 2021

Hybrid Managed Objects in ForgeRock IDM

Mappings

As you may be aware, ForgeRock IDM can store data in the repository using a 'generic' mapping, or an 'explicit' mapping - or anywhere inbetween. 

Generic means that any data is stored in a JSON blob (true for DS and Postgres repos - it's different for other DBs that don't handle JSON natively - but that's another topic entirely!)

Explicit means that any property in IDM must be explicitly mapped to an attribute in the underlying repository. 

By default, a standalone IDM uses generic for all managed objects. The following link describes explicit and generic mappings for DS repos: https://backstage.forgerock.com/docs/idm/7.1/objects-guide/explicit-generic-mapping.html#explicit-generic-mapping-ds 

Shared DS Repo

For 'shared repo' scenarios, an explicit mapping for the managed/user object is used. This is because ForgeRock AM doesn't understand JSON blobs in DS, so for AM to see users and attribute values IDM needs to use 'explicit'. The other managed objects aren't used by AM so IDM can still use generic mappings for those. 

repo.ds.json

It's repo.ds.json that controls the generic/explicit settings - and the platform setup guide for shared repo gets you to replace the default repo.ds.json with one that uses explicit mappings for managed/user (but generic mappings for other managed objects). 
Whilst this means that AM can now access the properties managed by IDM, the downside is that some flexibility is reduced. I can't simply modify the IDM managed user definition and expect it to work. I also have to change the DS schema and repo.ds.json mapping files. For production implementations this is generally a minor concern. But for prototyping and development purposes, it's a right royal...you know what! 
So, I generally switch my 'explicit' managed user mapping to a 'hybrid' managed user mapping. 

Hybrid mapping

This means that some properties in the managed user definition are explicitly mapped - so AM can use them, whereas anything else is 'generic'. Note that AM can't natively understand these generic properties - so it might not work for all situations. But it does mean I can easily change my IDM managed user definition to store additional properties. 

Caveat
I do this before I start IDM for the first time - so if you have already started storing data or making changes to config you may find some inconsistencies after doing this. I would always recommend starting afresh if possible. 


Let's look at the repo.ds.json file the Platform Setup guide references. At the time of writing, v7.1 is the latest and the guide references this: https://backstage.forgerock.com/docs/platform/7.1/resources/repo.ds.json Note there are 'explicitMapping' and 'genericMapping' blocks in the 'resourceMapping' block.
Diving into the 'explicitMapping' block we will see a 'managed/user' block:
If you expand the 'managed/user' block you will see the explicit mappings of IDM named properties to DS attribute names. (The DS attributes need to be defined in the DS schema - a topic for a different article! In this case, the attributes are present in the schema by virtue of DS setup profiles - yet another article!!) 
We need to move this 'managed/user' block to the 'genericMapping' block and then modify it to add the JSON property for storing additional IDM properties.  This is because 'hybrid' managed objects are better described as 'generic objects with some explicit property mappings'. 

So, cut and paste the entire 'managed/user' block into the 'genericMapping' block - it's over 200 lines - taking care to ensure you retain valid JSON (watch for missing/leftover commas!). I usually paste it in between the 'managed/*' and 'managed/role' blocks within the 'genericMapping' block. For example:
Ok, so now we need to make the changes to this block: 
  • Tell IDM which JSON attribute to use, and the JSON matching rule. To do this, add this within the 'managed/user' block:
"jsonAttribute" : "fr-idm-managed-user-custom-attrs", "jsonQueryEqualityMatchingRule" : "caseIgnoreJsonQueryMatch",
  • Add the objectClass that is the container for the JSON attribute To do this, add the following to the to the list of 'objectClasses' within the 'managed/user' block:
"fr-idm-managed-user-hybrid-obj"
 The result should look like this:

Note that we don't need to do anything with the 'properties' block - this will retain all of the AM specific explicit mappings for those properties. All we've done is tell IDM to store anything that isn't in the 'properties' section in the 'fr-idm-managed-user-custom-attrs' attribute. By the way, this attribute is already included in the DS schema through the setup profile - hence we don't need to change the DS schema. It's definition can be found here: https://backstage.forgerock.com/docs/ds/7.1/schemaref/at-fr-idm-managed-user-custom-attrs.html 


Now start IDM. You will be able to make IDM managed/user schema changes, and any data for those properties will now be stored in the JSON attribute.