Link Historical Accounts
This sample demonstrates the retention of inactive (historical) LDAP accounts that have been linked to a corresponding managed user account. The sample builds on Two Way Synchronization Between LDAP and IDM and uses the LDAP connector to connect to a ForgeRock Directory Services (DS) instance. You can use any LDAP-v3 compliant directory server.
Sample Overview
In this sample, IDM is the source resource. Managed users in the IDM repository maintain a list of the accounts to which they have been linked on the local LDAP server. This list is stored in the historicalAccounts
field of the managed user entry. The list contains a reference to all past and current LDAP accounts. Each LDAP account in the list is represented as a relationship and includes information about the date the accounts were linked or unlinked, and whether the account is currently active.
This sample includes the following custom scripts, in its script
directory:
onLink-managedUser_systemLdapAccounts.js
When a managed user object is linked to a target LDAP object, this script creates the relationship entry in the managed user's
historicalAccounts
property. The script adds two relationship properties:linkDate
— specifies the date that the link was created.active
— boolean true/false. When set to true, this property indicates that the target object is currently linked to the managed user account.
onUnlink-managedUser_systemLdapAccounts.js
When a managed user object is unlinked from a target LDAP object, this script updates that relationship entry's properties with an
unlinkDate
that specifies when the target was unlinked, and sets theactive
property to false, indicating that the target object is no longer linked.check_account_state_change.js
During liveSync or reconciliation, this script checks if the LDAP account state has changed. If the state has changed, the script updates the historical account properties to indicate the new state (enabled or disabled), and the date that the state was changed. This date can only be approximated and is set to the time that the change was detected by the script.
ldapBackCorrelationQuery.js
This script correlates entries in the LDAP directory with managed user identities in IDM.
Run the Sample
This section walks you through each step of the sample to demonstrate how historical accounts are stored.
Set up DS using
/path/to/openidm/samples/historical-account-linking/data/Example.ldif
.Prepare IDM, and start the server using the sample configuration:
cd /path/to/openidm/ ./startup.sh -p samples/historical-account-linking
Create a user, Joe Smith, in IDM:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --header "Content-Type: application/json" \ --request POST \ --data '{ "userName": "joe.smith", "givenName": "Joe", "sn" : "Smith", "password" : "Passw0rd", "displayName" : "Joe Smith", "mail" : "joe.smith@example.com" }' \ "http://localhost:8080/openidm/managed/user?_action=create"
{ "_id": "24356bf0-f026-4dc1-9f68-2a571b0a236f", "_rev": "00000000c8dc2137", "userName": "joe.smith", "givenName": "Joe", "sn": "Smith", "displayName": "Joe Smith", "mail": "joe.smith@example.com", "accountStatus": "active", "effectiveRoles": [], "effectiveAssignments": [] }
Record Joe Smith's system-generated
_id
.Verify that the user Joe Smith was created in DS.
Because implicit synchronization is enabled by default, any change to the managed/user repository should be propagated to DS. For more information about implicit synchronization, see "Types of Synchronization".
The following command returns all users in DS and shows that user joesmith was created successfully:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/system/ldap/account?_queryFilter=true&_fields=_id,dn"
{ "result": [ { "_id": "0da50512-79bb-3461-bd04-241ee4c785bf", "dn": "uid=jdoe,ou=People,dc=example,dc=com" }, { "_id": "887732e8-3db2-31bb-b329-20cd6fcecc05", "dn": "uid=bjensen,ou=People,dc=example,dc=com" }, { "_id": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "dn": "uid=joe.smith0,ou=People,dc=example,dc=com" } ], ... }
Note that Joe Smith's
uid
in DS is appended with a0
. TheonCreate
script, defined in the mapping (sync.json
), increments theuid
each time a new DS entry is linked to the same managed user object.Verify that the historical account relationship object that corresponds to this linked LDAP account was created in the IDM repository.
The following command queries Joe Smith's managed user entry and returns all of the
historicalAccounts
for that entry:curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f/historicalAccounts?_queryFilter=true"
{ "result": [ { "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "00000000c2beced4", "_ref": "system/ldap/account/da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refResourceCollection": "system/ldap/account", "_refResourceId": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refProperties": { "active": true, "stateLastChanged": "Mon May 18 2020 13:47:18 GMT+0200 (SAST)", "state": "enabled", "linkDate": "Mon May 18 2020 13:47:18 GMT+0200 (SAST)", "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "00000000c2beced4" } } ], ... }
At this stage, Joe Smith has only one historical account link — the link to
system/ldap/account/da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa
, which corresponds to the DN"dn": "uid=joe.smith0,ou=People,dc=example,dc=com"
. Note that the relationship properties (_refProperties
) show the following information about the linked accounts:The date on which the accounts were linked
The fact that this link is currently active
The state of the account in DS (
enabled
)
Enable the liveSync schedule to propagate changes made in DS to the managed user repository.
To start liveSync, set
enabled
totrue
in theconf/schedule-liveSync.json
file:more /path/to/openidm/samples/historical-account-linking/conf/schedule-liveSync.json
{ "enabled" : true, "type" : "simple", "repeatInterval" : 15000, ...
Use the
manage-account
command in theopendj/bin
directory to disable Joe Smith's account in DS:/path/to/opendj/bin/manage-account set-account-is-disabled \ --port 4444 \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --hostname localhost \ --bindDN uid=admin \ --bindPassword password \ --operationValue true \ --targetDN uid=joe.smith0,ou=people,dc=example,dc=com
Account Is Disabled: true
Within 15 seconds, according to the configured schedule, liveSync should pick up the change. IDM should then adjust the
state
property in Joe Smith's managed user account.To make sure that the linked account state has changed, request Joe Smith's historical accounts:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f/historicalAccounts?_queryFilter=true"
{ "result": [ { "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "00000000d430e15a", "_ref": "system/ldap/account/da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refResourceCollection": "system/ldap/account", "_refResourceId": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refProperties": { "active": true, "stateLastChanged": "Mon May 18 2020 13:51:06 GMT+0200 (SAST)", "state": "disabled", "linkDate": "Mon May 18 2020 13:47:18 GMT+0200 (SAST)", "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "00000000d430e15a" } } ], ... }
Now, deactivate Joe Smith's managed user account by setting his
accountStatus
property toinactive
.You can deactivate the account over the REST interface, or by using the Admin UI.
To use the Admin UI, simply select Manage > User, select Joe Smith's account and change his Status to inactive, on his Details tab.
The following command deactivates Joe Smith's account over REST:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --header "Content-Type: application/json" \ --request PATCH \ --data '[ { "operation" : "replace", "field" : "accountStatus", "value" : "inactive" } ]' \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f"
{ "_id": "24356bf0-f026-4dc1-9f68-2a571b0a236f", "_rev": "000000004cc82207", "userName": "joe.smith", "givenName": "Joe", "sn": "Smith", "displayName": "Joe Smith", "mail": "joe.smith@example.com", "accountStatus": "inactive", "effectiveRoles": [], "effectiveAssignments": [] }
Request Joe Smith's historical accounts:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f/historicalAccounts?_queryFilter=true"
{ "result": [ { "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "0000000037beefe7", "_ref": "system/ldap/account/da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refResourceCollection": "system/ldap/account", "_refResourceId": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refProperties": { "active": false, "stateLastChanged": "Mon May 18 2020 13:51:06 GMT+0200 (SAST)", "state": "disabled", "linkDate": "Mon May 18 2020 13:47:18 GMT+0200 (SAST)", "unlinkDate": "Mon May 18 2020 13:52:33 GMT+0200 (SAST)", "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "0000000037beefe7" } } ] ... }
Activate Joe Smith's managed user account by setting his
accountStatus
property to active. This action should create a new entry in DS (withuid=joe.smith1
), and a new link from Joe Smith's managed user object to that DS entry.You can activate the account over the REST interface, or by using the Admin UI, as described previously.
The following command activates Joe Smith's account over REST:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --header "Content-Type: application/json" \ --request PATCH \ --data '[ { "operation" : "replace", "field" : "accountStatus", "value" : "active" } ]' \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f"
{ "_id": "24356bf0-f026-4dc1-9f68-2a571b0a236f", "_rev": "00000000c8d52133", "userName": "joe.smith", "givenName": "Joe", "sn": "Smith", "displayName": "Joe Smith", "mail": "joe.smith@example.com", "accountStatus": "active", "effectiveRoles": [], "effectiveAssignments": [] }
Verify that a new LDAP entry for user Joe Smith was created in DS.
The following command returns all IDs in DS and shows that two entries now exist for Joe Smith -
uid=joe.smith0
anduid=joe.smith1
.curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/system/ldap/account?_queryFilter=true&_fields=_id,dn"
{ "result": [ { "_id": "0da50512-79bb-3461-bd04-241ee4c785bf", "dn": "uid=jdoe,ou=People,dc=example,dc=com" }, { "_id": "887732e8-3db2-31bb-b329-20cd6fcecc05", "dn": "uid=bjensen,ou=People,dc=example,dc=com" }, { "_id": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "dn": "uid=joe.smith0,ou=People,dc=example,dc=com" }, { "_id": "52821eec-e00d-4321-8857-f46a870afc45", "dn": "uid=joe.smith1,ou=People,dc=example,dc=com" } ], ... }
Request Joe Smith's historical accounts:
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "http://localhost:8080/openidm/managed/user/24356bf0-f026-4dc1-9f68-2a571b0a236f/historicalAccounts?_queryFilter=true"
{ "result": [ { "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "0000000037beefe7", "_ref": "system/ldap/account/da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refResourceCollection": "system/ldap/account", "_refResourceId": "da7c8fe9-4959-4dc9-9cd5-60c0ead9b0aa", "_refProperties": { "active": false, "stateLastChanged": "Mon May 18 2020 13:51:06 GMT+0200 (SAST)", "state": "disabled", "linkDate": "Mon May 18 2020 13:47:18 GMT+0200 (SAST)", "unlinkDate": "Mon May 18 2020 13:52:33 GMT+0200 (SAST)", "_id": "3f193422-156b-4b66-adcf-447db1b7d770", "_rev": "0000000037beefe7" } }, { "_id": "8850640c-2233-4ddc-9725-6b4b2d59605f", "_rev": "000000000843ce68", "_ref": "system/ldap/account/52821eec-e00d-4321-8857-f46a870afc45", "_refResourceCollection": "system/ldap/account", "_refResourceId": "52821eec-e00d-4321-8857-f46a870afc45", "_refProperties": { "active": true, "stateLastChanged": "Mon May 18 2020 13:54:52 GMT+0200 (SAST)", "state": "enabled", "linkDate": "Mon May 18 2020 13:54:52 GMT+0200 (SAST)", "_id": "8850640c-2233-4ddc-9725-6b4b2d59605f", "_rev": "000000000843ce68" } } ], ... }
Note that Joe Smith's entry now shows two DS accounts, but that only the link to
uid=joe.smith1
("_ref": "system/ldap/account/52821eec-e00d-4321-8857-f46a870afc45",
) isenabled
andactive
.