f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang<!-- please include docs in any mod of this file
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jangIt's designed for "single sourcing" with the published docs -->
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! CCPL HEADER START
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! This work is licensed under the Creative Commons
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! To view a copy of this license, visit
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! http://creativecommons.org/licenses/by-nc-nd/3.0/
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! or send a letter to Creative Commons, 444 Castro Street,
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! Suite 900, Mountain View, California, 94041, USA.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! You can also obtain a copy of the license at
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! See the License for the specific language governing permissions
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! and limitations under the License.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! If applicable, add the following below this CCPL HEADER, with the fields
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! enclosed by brackets "[]" replaced with your own identifying information:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! Portions Copyright [yyyy] [name of copyright owner]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! CCPL HEADER END
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang ! Copyright 2015 ForgeRock AS
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang<chapter xml:id='chap-multiaccount-sample'
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang version='5.0' xml:lang='en'
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang xsi:schemaLocation='http://docbook.org/ns/docbook
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[sample-multiaccount-linking]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangThe Multi-Account Linking Sample
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThe sample provided in the `samples/multiaccountlinking` directory illustrates how OpenIDM addresses links from multiple
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleaccounts to one identity.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThis sample is based on a common use case in the insurance industry, where a company (Example.com) employs agents to
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangsell policies to their insured customers. Most of their agents are also insured. These different roles are sometimes
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleknown as the multi-account linking conundrum.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleWith minor changes, this sample works for other use cases. For example, you may have a hospital that employs doctors who
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienletreat patients. Some of their doctors are also patients of that hospital.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[external-ldap-config-multiaccount]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangExternal LDAP Configuration
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang~~~~~~~~~~~~~~~~~~~~~~~~~~~
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangConfigure the LDAP server as for sample 2,
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.janghttp://openidm.forgerock.org/doc/bootstrap/install-guide/index.html#external-ldap-config-2[External LDAP Configuration^]
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThe LDAP user must have write access to create users from OpenIDM on the LDAP server. When you configure the LDAP
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleserver, import the appropriate LDIF file, in this case, _openidm/samples/multiaccountlinking/data/Example.ldif_.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[install-sample-multiaccount]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangInstall the Sample
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang------------------
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangPrepare OpenIDM as described in
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.janghttp://openidm.forgerock.org/doc/bootstrap/install-guide/index.html#preparing-openidm[Preparing OpenIDM^],
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlethen start OpenIDM with the following configuration for the Multi-Account Linking sample.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>cd /path/to/openidm</userinput></screen>
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>./startup.sh -p samples/multiaccountlinking</userinput></screen>
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[multiaccount-create-users]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangCreate New Identities for the Sample
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang------------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleFor the purpose of this sample, create identities for users John Doe and Barbara Jensen. To create these identities from
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlethe Admin UI, navigate to `https://localhost:8443/admin` and click Manage > User > New User.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleAlternatively, use the following REST calls to set up identities for the noted users:
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-Type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--request POST \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "displayName" : "Barbara Jensen",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "description" : "Created for OpenIDM",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "givenName" : "Barbara",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "mail" : "bjensen@example.com",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "telephoneNumber" : "1-360-229-7105",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "sn" : "Jensen",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "userName" : "bjensen",
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang "accountStatus" : "active"
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang"https://localhost:8443/openidm/managed/user?_action=create"</userinput></screen>
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-Type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--request POST \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "displayName" : "John Doe",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "description" : "Created for OpenIDM",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "givenName" : "John",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "mail" : "jdoe@example.com",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "telephoneNumber" : "1-415-599-1100",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "sn" : "Doe",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "userName" : "jdoe",
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang "accountStatus" : "active"
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang"https://localhost:8443/openidm/managed/user?_action=create"</userinput></screen>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleIn the output, you will see an ID number associated with each user, in the following format:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen> "_id" : "35d0a49d-2571-401f-b429-96c66b23a1c0",</screen>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleRecord the `_id` number for each user. You will use those numbers to assign desired roles for each user.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[multiaccount-create-roles]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangCreate New Roles for the Sample
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang-------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleFor this sample, to set up links for multiple accounts on OpenIDM, you need to set up roles. To do so, set up roles for
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang`Agent` and `Insured`. To create these roles in the Admin UI, navigate to `https://localhost:8443/admin` and click
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleManage > Role > New Role.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangAlternatively, use the following REST calls to set up the `Agent` and `Insured` roles:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-Type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang--request POST \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "name" : "Agent",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "description" : "Role assigned to insurance agents."
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang"https://localhost:8443/openidm/managed/role?_action=create"</userinput></screen>
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-Type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang--request POST \
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "name" : "Insured",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "description" : "Role assigned to insured customers."
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang"https://localhost:8443/openidm/managed/role?_action=create"</userinput></screen>
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangDo record the `_id` output for the `Agent` and `Insured` roles. You will use those numbers to assign desired roles for each
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleNOTE: While you could use `PUT` to create roles with descriptive names, we recommend that you use `POST` to create roles
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlewith immutable IDs.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[multiaccount-assign-roles]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangAssign Roles to Appropriate Users
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang---------------------------------
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangNow you can assign roles to appropriate users. To review, user `jdoe` is an `Agent` and user `bjensen` is `Insured`.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleYou will need the `_id` value for each user. The `_id` values shown in the following commands are random; substitute the
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle`_id` values that you collected when creating users.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThe following command adds the `Agent` role to user `jdoe`, by their `_id` values:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "If-Match: *" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--request PATCH \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "operation" : "add",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "field" : "/roles/-",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "_ref" : "managed/role/287dc4b1-4b19-49ec-8b4c-28a6c12ede34"
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang"https://localhost:8443/openidm/managed/user/8fae84ed-1f30-4542-8087-e7fa6e89541c"</userinput></screen>
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangAnd this next command adds the `Insured` role to user `bjensen`:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "If-Match: *" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--request PATCH \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "operation" : "add",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "field" : "/roles/-",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "_ref" : "managed/role/bb9302c4-5fc1-462c-8be2-b17c87175d1b"
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang"https://localhost:8443/openidm/managed/user/d0b79f30-946f-413a-b7d1-d813034fa345"</userinput></screen>
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangNow assign the `Insured` role to user `jdoe`, as that user is both an insured customer and
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang<screen>$ <userinput>curl \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang--header "Content-type: application/json" \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang--header "X-OpenIDM-Username: openidm-admin" \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang--header "X-OpenIDM-Password: openidm-admin" \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang--header "If-Match: *" \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang--request PATCH \
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang "operation" : "add",
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang "field" : "/roles/-",
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang "_ref" : "managed/role/006935c2-b080-45cd-8347-881df42cae0c"
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang"https://localhost:8443/openidm/managed/user/a3335177-7366-4656-a66c-8d6e77a5786f"</userinput></screen>
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangUser `jdoe` should now have two managed roles:
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang"effectiveRoles" : [ {
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "_ref" : "managed/role/6aabe990-ec05-403e-bc5d-ff9b217ba571",
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "_refProperties" : {
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "_id" : "687714b8-5854-42c7-a190-c781ea5174c5",
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "_rev" : "1"
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "_ref" : "managed/role/844110ce-3686-43bb-aabf-46b17a14abaa"
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang[[multiaccount-background]]
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangBackground: Link Qualifiers, Agents, and Insured Customers
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang----------------------------------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThis is a good moment to take a step back, to see how this sample works, based on custom options in the `sync.json`
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleconfiguration file.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleOpenIDM defines mappings between source and target accounts in the `sync.json` file, which allows you to create a link
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlebetween one source entry and multiple target entries using a concept known as a "link qualifier," which enables
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleone-to-many relationships in mappings and policies.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangFor more information on resource mappings and link qualifiers, see the following sections of the Integrator's Guide:
03c23263ac1e762ec24dfa8995d255b03b4f9a1cmike.janghttp://openidm.forgerock.org/doc/bootstrap/integrators-guide/#synchronization-mappings-file[Configuring the Synchronization Mapping]
03c23263ac1e762ec24dfa8995d255b03b4f9a1cmike.janghttp://openidm.forgerock.org/doc/bootstrap/integrators-guide/#mapping-link-qualifiers[Adding Link Qualifiers to a Mapping]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangIn this sample, we use two link qualifiers:
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang* `insured` represents the insured customer accounts associated with Example.com, created under the following LDAP container:
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle `ou=Customers,dc=example,dc=com`
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle* `agent` represents agent accounts, considered independent contractors, and created under the following LDAP container:
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang `ou=Contractors,dc=example,dc=com`
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangAssume that agents and insured customers connect via two different portals. Each group gets access to different features,
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienledepending on the portal.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleAgents may have two different accounts; one each for professional and personal use. While the accounts are different,
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlethe identity information for each agent should be the same for both accounts.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleTo that end, this sample sets up link qualifiers for two categories of users: `insured` and `agent`, under the
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle`managedUser_systemLdapAccounts` mapping:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<programlisting language="javascript">{
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "name" : "managedUser_systemLdapAccounts",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "linkQualifiers" : [
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang}</programlisting>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleYou can verify this in the Admin UI. Click Configure > Mappings > `managedUser_systemLdapAccounts` > Properties >
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleLink Qualifiers. You should see `insured` and `agent` in the list of configured Link Qualifiers.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleIn addition, this sample also includes a transformation script between an LDAP Distinguished Name (`dn`) and the two
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlecategories of users. The following excerpt of the `sync.json` file includes that script:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<programlisting language="javascript">{
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "target" : "dn",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "transform" : {
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "globals" : { },
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang "if (linkQualifier === 'agent') {
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang 'uid=' + source.userName + ',ou=Contractors,dc=example,dc=com';
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang } else if (linkQualifier === 'insured') {
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang 'uid=' + source.userName + ',ou=Customers,dc=example,dc=com';
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang},</programlisting>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThe following validSource script looks through the effective roles of a user, with two objectives:
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang* Determine whether the user has an `Agent` or `Insured` role, and segregates accounts
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangbased on link qualfiers and roles.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang* Uses the `effectiveRoles` property to determine whether a user has an
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang`Agent` or `Insured` role, based on the effective roles of that user.
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jang<programlisting language="javascript">"validSource" : {
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "globals" : { },
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "source" : "var res = false;
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang while (!res && i < source.effectiveRoles.length) {
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang var roleId = source.effectiveRoles[i];
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang if (roleId != null && roleId.indexOf("/") != -1) {
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang var roleInfo = openidm.read(roleId);
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang logger.warn("Role Info : {}",roleInfo);
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang res = (((roleInfo.properties.name === 'Agent')
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang &&(linkQualifier ==='agent'))
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang || ((roleInfo.properties.name === 'Insured')
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang &&(linkQualifier ==='insured')));
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang}</programlisting>
f49e88b98c3a7fcf8e21cdc26dc6c3ebc3bf764emike.jangYou can see how correlation queries are configured in the `sync.json` file.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThe structure for the correlation query specifies one of two link qualifiers: insured or agent. For each link qualifier,
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlethe correlation query defines a script that verifies if the subject `dn` belongs in a specific container. For this
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlesample, the container (`ou`) may be Customers or Contractors.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleYou can can avoid specifying the structure of the `dn` attribute in two places in the `sync.json` file with the
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlefollowing code, which leverages the expression builder to reuse the construct defined in the `dn` mapping:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<programlisting language="javascript">"correlationQuery" : [
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "linkQualifier" : "insured",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "expressionTree" : {
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "mapping" : "managedUser_systemLdapAccounts",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "linkQualifier" : "agent",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "expressionTree" : {
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "mapping" : "managedUser_systemLdapAccounts",
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang],</programlisting>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleYou can also leverage the expression builder in the UI. Review how the UI illustrates the expression builder. To do so,
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienleclick Configure > Mapping > select a mapping > Association > Association Rules. Edit either link qualifier. You will see
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlehow the expression builder is configured for this sample.
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang[[multiaccount-roles-update]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangUpdate Roles With Desired LDAP Attributes
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang-----------------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleThis use case illustrates how accounts frequently have different functions on target systems. For example, while agents
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlemay be members of a Contractor group, insured customers may be part of a Chat Users group (possibly for access to
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlecustomer service).
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangWhile an agent may also be an insured customer, you do not want other `insured` accounts to have the same properties
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle(or memberships) as the `agent` account. In this sample, we ensure that OpenIDM limits role based assignments to the
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlecorrect account.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangWith the following commands you will create two managed assignments which will be used by the `agent` and `insured`
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleRecord the `_id` number for each user. You will use those numbers to assign desired roles for each user.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangThe following command will create an `agent` assignment.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle<screen>$ <userinput>curl \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --header "Content-Type: application/json" \
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang --header "X-OpenIDM-Username: openidm-admin" \
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang --header "X-OpenIDM-Password: openidm-admin" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --request POST \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "name" : "ldapAgent",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "description" : "LDAP Agent Assignment",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "mapping" : "managedUser_systemLdapAccounts",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "attributes": [
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "name": "ldapGroups",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "cn=Contractors,ou=Groups,dc=example,dc=com"
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "assignmentOperation" : "mergeWithTarget",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "unassignmentOperation" : "removeFromTarget"
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "linkQualifiers": ["agent"]
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle"https://localhost:8443/openidm/managed/assignment?_action=create"</userinput></screen>
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangNow repeat the process for the `insured` assignment, with the value set to the `Chat Users` group:
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle<screen>$ <userinput>curl \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --header "Content-Type: application/json" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --header "X-OpenIDM-Username: openidm-admin" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --header "X-OpenIDM-Password: openidm-admin" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle --request POST \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "name" : "ldapCustomer",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "description" : "LDAP Customer Assignment",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "mapping" : "managedUser_systemLdapAccounts",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "attributes": [
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "name": "ldapGroups",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "cn=Chat Users,ou=Groups,dc=example,dc=com"
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "assignmentOperation" : "mergeWithTarget",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "unassignmentOperation" : "removeFromTarget"
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang "linkQualifiers": ["insured"]
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle"https://localhost:8443/openidm/managed/assignment?_action=create"</userinput></screen>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleNow you can add the created assignments to their respective roles.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangAdd the `insured` assignment to the insured customer role:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "Content-type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--header "If-Match: *" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--request PATCH \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "operation" : "add",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "field" : "/assignments/-",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "_ref" : "managed/assignment/ee5241b2-e571-4736-8fb2-6b9caa9d0554"
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle"https://localhost:8443/openidm/managed/role/287dc4b1-4b19-49ec-8b4c-28a6c12ede34"</userinput></screen>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleAdd the agent assignment to the agent role:
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle<screen>$ <userinput>curl \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle--header "Content-type: application/json" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle--header "X-OpenIDM-Username: openidm-admin" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle--header "X-OpenIDM-Password: openidm-admin" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle--header "If-Match: *" \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle--request PATCH \
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "operation" : "add",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "field" : "/assignments/-",
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle "_ref" : "managed/assignment/12927c5d-576f-491e-ba65-e228cd218947"
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle"https://localhost:8443/openidm/managed/role/bb9302c4-5fc1-462c-8be2-b17c87175d1b"</userinput></screen>
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang[[multiaccountlinking-recon]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangReconciling Managed Users to the External LDAP Server
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang-----------------------------------------------------
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleNow that you have loaded `Example.ldif` into OpenDJ, and have started OpenIDM, you can perform a reconciliation from
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlethe internal Managed Users repository to the external OpenDJ data store:
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang<screen>$ <userinput>curl \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang --header "Content-Type: application/json" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang --header "X-OpenIDM-Username: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang --header "X-OpenIDM-Password: openidm-admin" \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang --request POST \
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang "https://localhost:8443/openidm/recon?_action=recon&mapping=managedUser_systemLdapAccounts"</userinput>
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleWith all of the preparation work that you have done, this reconciliation will create three new accounts on the external
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle * Two accounts under the `ou=Customers,dc=example,dc=com` branch `dn` under the insured customers role, `bjensen` and
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle * One account under the `ou=Contractors,dc=example,dc=com` branch `dn` under the insurance agents role, `jdoe`.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad KienleCongratulations, you have just created accounts in two different areas of the LDAP Directory Information Tree.
b449feac6a5dab18b07affbd6bf553ec4abad5eemike.jang[[multilinking-review]]
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jangReviewing the Result
a8b98a6f6ead0f58f71c30707011343c16001a97mike.jang--------------------
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jangYou have already confirmed that user `bjensen` has a `insured` role, and user `jdoe` has both a `insured` and `agent`
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienlerole. You can confirm the same result in the Admin UI:
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang. Click Manage > Role. You should see both Agent and Insured in the Role List window that appears.
b31a18cdb1b7c0bd3b3436df2992af32f0dd21a9Chad Kienle. Click Agent > Users. You should see that user `jdoe` is included as an Agent.
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang. Click Back to Roles > Insured > Users. You should see that users `bjensen` and
887d436d254d110d582c344fd0aa3c6e7fcaf709mike.jang`jdoe` are included in the Insured role.