chap-samples.xml revision f5d0c63de3b572323db6cf3c13ad64372f8e4b70
<?xml version="1.0" encoding="UTF-8"?>
<!--
! CCPL HEADER START
!
! This work is licensed under the Creative Commons
! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
! To view a copy of this license, visit
! or send a letter to Creative Commons, 444 Castro Street,
! Suite 900, Mountain View, California, 94041, USA.
!
! You can also obtain a copy of the license at
! See the License for the specific language governing permissions
! and limitations under the License.
!
! If applicable, add the following below this CCPL HEADER, with the fields
! enclosed by brackets "[]" replaced with your own identifying information:
! Portions Copyright [yyyy] [name of copyright owner]
!
! CCPL HEADER END
!
! Copyright 2011-2014 ForgeRock AS
!
-->
<chapter xml:id='chap-samples'
xmlns='http://docbook.org/ns/docbook'
version='5.0' xml:lang='en'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://docbook.org/ns/docbook
xmlns:xlink='http://www.w3.org/1999/xlink'>
<title>More OpenIDM Samples</title>
<para>The current distribution of OpenIDM comes with a variety of samples
<link xlink:href="install-guide#chap-sample"
Sample</citetitle></link>. This chapter describes the remaining OpenIDM
samples.</para>
<section xml:id="before-you-begin-samples">
<title>Before You Begin</title>
<para>Install OpenIDM, as described in <link
xlink:href="install-guide#chap-install"
OpenIDM Services</citetitle></link>.</para>
<para>OpenIDM comes with an internal noSQL database, OrientDB, for use as
the internal repository out of the box. This makes it easy to get started
with OpenIDM. OrientDB is not yet supported for production use, however,
so use a supported JDBC database when moving to production.</para>
<section xml:id="install-samples">
<title>Installing the Samples</title>
<indexterm>
<primary>Installing</primary>
<secondary>Samples</secondary>
</indexterm>
<para>
number of subdirectories, such as <filename>conf/</filename> and
<filename>script/</filename>. To start OpenIDM with a sample configuration,
<literal>-p</literal> option of the <command>startup</command> command to
point to the sample whose configuration you want to use. Some, but not all
samples require additional software, such as an external LDAP server or
database.
</para>
<para>
When you move from one sample to the next, bear in mind that you are
changing the OpenIDM configuration. For information on how configuration
changes work, see <link xlink:href="integrators-guide#when-configuring-notes"
Configuration</citetitle></link> in the <citetitle>Integrator's
Guide</citetitle>.
</para>
</section>
<section xml:id="preparing-openidm">
<title>Preparing OpenIDM</title>
<para>Install an instance of OpenIDM specifically to try the samples. That
way you can experiment as much as you like, and discard the result if you
are not satisfied.</para>
<para>
If you are using the same instance of OpenIDM for multiple samples, it is
helpful to clear out the repository created for an earlier sample. To do so,
directory.
</para>
<para>
OpenIDM should now be ready to start with a new sample. For a number of
the following samples, users are created either at the UI or with a
commons REST call. Once added, and when reconciliation is complete, such
users should be able to log into the UI.
</para>
</section>
</section>
<section xml:id="more-sample1">
<title>Sample 1 - XML File</title>
<para>Sample 1 is described in the chapter, <link
xlink:href="install-guide#chap-sample"
Sample</citetitle></link>.</para>
</section>
<section xml:id="more-sample2">
<title>Sample 2 - LDAP One Way</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 2 - LDAP one way</secondary>
</indexterm>
<para>Sample 2 resembles the first sample, but in sample 2 OpenIDM is
connected to a local LDAP server. The sample has been tested with
</link>, but it should work with any LDAPv3 compliant server.</para>
<para>Sample 2 demonstrates how OpenIDM can pick up new or changed objects
from an external resource. The sample contains only one mapping, from the
external LDAP server resource to the OpenIDM repository. The sample therefore
does not push any changes made to OpenIDM managed user objects out to the
LDAP server.</para>
<section xml:id="external-ldap-config-2">
<title>LDAP Server Configuration</title>
<itemizedlist>
<para>Sample 2 expects the following configuration for the external LDAP
server:</para>
<listitem><para>The LDAP server runs on the local host.</para></listitem>
<listitem><para>The LDAP server listens on port 1389.</para></listitem>
<listitem><para>A user with DN <literal>cn=Directory Manager</literal>
and password <literal>password</literal> has read access to the LDAP
server.</para></listitem>
<listitem>
<para>Directory data for that server is stored under base DN
<literal>dc=example,dc=com</literal>.</para>
</listitem>
<listitem><para>User objects for that server are stored under base DN
<literal>ou=People,dc=example,dc=com</literal>.</para></listitem>
<listitem><para>User objects have the object class
<literal>inetOrgPerson</literal>.</para></listitem>
<listitem><para>User objects have the following attributes:</para>
<itemizedlist>
<listitem><para><literal>cn</literal></para></listitem>
<listitem><para><literal>description</literal></para></listitem>
<listitem><para><literal>givenName</literal></para></listitem>
<listitem><para><literal>mail</literal></para></listitem>
<listitem><para><literal>sn</literal></para></listitem>
<listitem><para><literal>telephoneNumber</literal></para></listitem>
<listitem><para><literal>uid</literal></para></listitem>
<listitem><para><literal>userPassword</literal></para></listitem>
</itemizedlist>
<para>An example user object follows.</para>
<programlisting language="ldif">
dn: uid=jdoe,ou=People,dc=example,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
givenName: John
uid: jdoe
cn: John Doe
telephoneNumber: 1-415-523-0772
sn: Doe
mail: jdoe@example.com
description: Created by OpenIDM
userPassword: password</programlisting>
</listitem>
</itemizedlist>
<para>Prepare the LDAP server by creating a base suffix of
<literal>dc=example,dc=com</literal>, and importing these objects from
<programlisting language="ldif">
dn: dc=com
objectClass: domain
objectClass: top
dc: com
dn: dc=example,dc=com
objectClass: domain
objectClass: top
dc: example
dn: ou=People,dc=example,dc=com
ou: people
description: people
objectclass: organizationalunit
dn: uid=jdoe,ou=People,dc=example,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
givenName: John
uid: jdoe
cn: John Doe
telephoneNumber: 1-415-523-0772
sn: Doe
mail: jdoe@example.com
description: Created for OpenIDM
userPassword: password
</programlisting>
<para>There is an additional user, <literal>bjensen</literal> in the
sample LDIF file. This user is essentially a "dummy" user, provided for
compliance with RFC 4519, which stipulates that every
<literal>groupOfUniqueNames</literal> object must contain at least one
<literal>uniqueMember</literal>.</para>
</section>
<section xml:id="install-sample2">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 2.</para>
</section>
<section xml:id="run-sample2">
<title>Running the Sample</title>
<para>Run reconciliation over the REST interface.</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapAccounts_managedUser"</screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<note>
<para>
If you want to run a <command>curl</command> command over regular HTTP,
the URL to use protocol HTTP over port 8080. For instructions on how
Guide section entitled <link xlink:show="new"
xlink:href="integrators-guide#rest-over-https"
xlink:role="http://docbook.org/xlink/role/olink">
<citetitle>Restrict REST Access to the HTTPS Port</citetitle></link>.
</para>
</note>
<para>With the configuration of sample 2, OpenIDM creates user objects from
LDAP in OpenIDM, assigning the new objects random unique IDs. To list user
objects by ID, run a query over the REST interface.</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>
If you want the output to be formatted, include the
<literal>_prettyPrint=true</literal> request parameter or pipe the output to
a JSON parser such as <command>jq</command>, otherwise the resulting JSON
object appears all on one line.
</para>
<programlisting language="javascript">
{
"result": [
{
"_id": "53fbf0c5-aa37-4845-a4b3-92a21810a36d",
"_rev": "0"
},
{
"_id": "ae0aed26-2a9c-43e3-a6f0-ca707c9c6455",
"_rev": "0"
}
],
"resultCount": 2,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
}</programlisting>
<para>
You should now be able to review reconciled users in the UI. Point your
the <literal>openidm-admin</literal> user (with password
<literal>openidm-admin</literal>), and navigate to the Users tab. Select the
user whose profile information you want to see.
</para>
<mediaobject>
<alt>Example of adding a new user</alt>
<imageobject>
</imageobject>
</mediaobject>
<para>Alternatively, you can retrieve individual user objects by ID, as shown
here.</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
</section>
</section>
<section xml:id="more-sample2b">
<title>Sample 2b - LDAP Two Way</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 2b - LDAP two way</secondary>
</indexterm>
<para>Like sample 2, sample 2b also connects to an external LDAP
server.</para>
<para>Unlike sample 2, however, sample 2b has two mappings configured, one
from the LDAP server to the OpenIDM repository, and the other from the
OpenIDM repository to the LDAP server.</para>
<section xml:id="external-ldap-config-2b">
<title>External LDAP Configuration</title>
<para>Configure the LDAP server as for sample 2,
<xref linkend="external-ldap-config-2" />. The LDAP user must have write
access to create users from OpenIDM on the LDAP server.</para>
<para>
When configuring the LDAP server, be sure to import the appropriate
LDIF file, in this case,
</para>
</section>
<section xml:id="install-sample2b">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 2b.</para>
</section>
<section xml:id="run-sample2b">
<title>Running the Sample</title>
<para>Run reconciliation over the REST interface.</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapAccounts_managedUser"</screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<para>With the configuration of sample 2b, OpenIDM creates user objects from
LDAP in OpenIDM, assigning the new objects random unique IDs. To list user
objects by ID, run a query over the REST interface.</para>
<screen>
$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
</screen>
<para>The resulting JSON object should include content similar to the
following.</para>
<programlisting language="javascript">
{
"result": [
{
"_id": "53fbf0c5-aa37-4845-a4b3-92a21810a36d"
"_rev": "0",
},
{
"_id": "6490489f-bbff-4855-808a-5c1862b09339"
"_rev": "0",
}
"resultCount": 2,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
],
}</programlisting>
<para>To retrieve the user, log into the UI, on an URI such as
user
</para>
<para>
Alternatively, you can make a commons REST call to get a specific user
object by ID.</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>Test the second mapping by creating a user in the OpenIDM
repository. On UNIX:</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
--data '{
"mail":"fdoe@example.com",
"sn":"Doe",
"telephoneNumber":"555-1234",
"userName":"fdoe",
"givenName":"Felicitas",
"description":"Felicitas Doe",
"displayName":"fdoe"}' \
<para>On Windows:</para>
<screen>$ curl ^
--cacert self-signed.crt ^
--header "X-OpenIDM-Username: openidm-admin" ^
--header "X-OpenIDM-Password: openidm-admin" ^
--header "Content-Type: application/json" ^
--request POST ^
--data "{
\"mail\":\"fdoe@example.com\",
\"sn\":\"Doe\",
\"telephoneNumber"\:\"555-1234\",
\"userName\":\"fdoe\",
\"givenName\":\"Felicitas\",
\"description\":\"Felicitas Doe\",
\"displayName\":\"fdoe\"}" ^
<para>
By default, automatic synchronization is enabled. This means that when you
update a managed object, any mappings defined in the
source are automatically executed to update the target system. For more
information, see <link
xlink:href="integrators-guide#synchronization-mappings-file"
Mappings File</citetitle></link> in the <citetitle>Integrator's
Guide</citetitle>.
</para>
<para>Test that the automatic reconciliation has been successful by
locating the new user in the LDAP directory.</para>
-bindDN "cn=Directory Manager" \
-bindPassword password \
-hostname localhost \
-port 1389 \
-baseDN "dc=example,dc=com" \
"uid=fdoe" </userinput>
<computeroutput>dn: uid=fdoe,ou=People,dc=example,dc=com
mail: fdoe@example.com
givenName: Felicitas
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
uid: fdoe
cn: Felicitas Doe
sn: Doe</computeroutput>
</screen>
</section>
</section>
<section xml:id="more-sample2c">
<title>Sample 2c - Synchronizing LDAP Group Membership</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 2c - Synchronizing LDAP Group Membership</secondary>
</indexterm>
<para>Like sample 2b, sample 2c also connects to an external LDAP
server. The only difference is that in sample 2c, LDAP Group Memberships
are synchronized.</para>
<section xml:id="external-ldap-config-2c">
<title>External LDAP Configuration</title>
<para>Configure the LDAP server as for sample 2,
<xref linkend="external-ldap-config-2" />. The LDAP user must have write
access to create users from OpenIDM on the LDAP server.</para>
<para>In addition, two LDAP Groups should be created, which can be found in
<programlisting language="ldif">
dn: ou=Groups,dc=example,dc=com
ou: Groups
objectClass: organizationalUnit
objectClass: top
dn: cn=openidm,ou=Groups,dc=example,dc=com
uniqueMember: uid=jdoe,ou=People,dc=example,dc=com
cn: openidm
objectClass: groupOfUniqueNames
objectClass: top
dn: cn=openidm2,ou=Groups,dc=example,dc=com
uniqueMember: uid=bjensen,ou=People,dc=example,dc=com
cn: openidm2
objectClass: groupOfUniqueNames
objectClass: top</programlisting>
<para>The users with DNs <literal>uid=jdoe,ou=People,dc=example,dc=com</literal>
and <literal>uid=bjensen,ou=People,dc=example,dc=com</literal> are also
<literal>bjensen</literal> is essentially a "dummy" user, provided for
compliance with RFC 4519, which stipulates that every
<literal>groupOfUniqueNames</literal> object must contain at least one
<literal>uniqueMember</literal>. User <literal>bjensen</literal> is not
actually used in this sample.)</para>
</section>
<section xml:id="install-sample2c">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 2c.</para>
</section>
<section xml:id="run-sample2c">
<title>Running the Sample</title>
<para>Run reconciliation over the REST interface.</para>
<screen>$ <userinput>curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapAccounts_managedUser"</userinput></screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<para>With the configuration of sample 2c, OpenIDM creates user objects from
LDAP in OpenIDM, assigning the new objects random unique IDs. To list user
objects by ID, run a query over the REST interface.</para>
<screen>
$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
</screen>
<para>The resulting JSON object should appear similar to the following:</para>
<programlisting language="javascript">
{
"result": [
{
"_id": "53fbf0c5-aa37-4845-a4b3-92a21810a36d"
"_rev": "0",
}
{
"_id": "56f0fb7e-3837-464d-b9ec-9d3b6af665c3",
"_rev": "0"
}
]
"resultCount": 2,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
}</programlisting>
<para>
You should now be able to retrieve John Doe's user object in the UI,
navigating to the domain for OpenIDM such as
retrieve John Doe's user object at the command line by his ID.
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
"https://localhost:8443/openidm/managed/user/53fbf0c5-aa37-4845-a4b3-92a21810a36d"</userinput></screen>
<para>The user object should contain a property like: </para>
<screen>"ldapGroups":["cn=openidm,ou=Groups,dc=example,dc=com"]</screen>
<para>Now change the user on the OpenIDM side with the following REST
call (on UNIX):</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
--data '[
{
"operation":"replace",
"field":"/ldapGroups",
"value": ["cn=openidm2,ou=Groups,dc=example,dc=com"]
}
]' \
"https://localhost:8443/openidm/managed/user?_action=patch&_queryId=for-userName&uid=jdoe"</userinput></screen>
<para>
On Windows, you might need to escape certain characters, so your REST call
would look like this:
</para>
<screen><userinput>$ curl ^
--cacert self-signed.crt ^
--header "X-OpenIDM-Username: openidm-admin" ^
--header "X-OpenIDM-Password: openidm-admin" ^
--header "Content-Type: application/json" ^
--request POST ^
--data "[
{
\"operation\":\"replace\",
\"field\":\"\/ldapGroups\",
\"value\": [\"cn=openidm2,ou=Groups,dc=example,dc=com\"]
}
]" ^
"https://localhost:8443/openidm/managed/user?_action=patch&_queryId=for-userName&uid=jdoe"</userinput></screen>
<para>This will change the user's <literal>ldapGroups</literal> property
in OpenIDM from <filename>"cn=openidm,ou=Groups,dc=example,dc=com"</filename>
to <filename>"cn=openidm2,ou=Groups,dc=example,dc=com"</filename> and, as a
result, the user will be removed from the one LDAP group and added to
the other LDAP group on OpenDJ.</para>
<para>Retrieve John Doe's user object again and notice the changed
<literal>"ldapGroups"</literal> property.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
"https://localhost:8443/openidm/managed/user/56f0fb7e-3837-464d-b9ec-9d3b6af665c3"</userinput></screen>
<para>
By default, automatic synchronization is enabled. This means that when you
update a managed object, any mappings defined in the
source are automatically executed to update the target system. For more
information, see <link
xlink:href="integrators-guide#synchronization-mappings-file"
Mappings File</citetitle></link> in the <citetitle>Integrator's
Guide</citetitle>.
</para>
</section>
</section>
<section xml:id="more-sample2d">
<title>Sample 2d - Synchronizing LDAP Groups</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 2d - Synchronizing LDAP Groups</secondary>
</indexterm>
<para>Sample 2d also connects to an external LDAP server. This sample
focuses on LDAP Group synchronization.</para>
<section xml:id="external-ldap-config-2d">
<title>External LDAP Configuration</title>
<para>Configure the LDAP server as for sample 2,
<xref linkend="external-ldap-config-2" />. The LDAP user must have write
access to create users from OpenIDM on the LDAP server.</para>
<para>In addition, two LDAP Groups should be created, which can be found in
(if they have not already been added through sample 2c):</para>
<programlisting language="ldif">
dn: ou=Groups,dc=example,dc=com
ou: Groups
objectClass: organizationalUnit
objectClass: top
dn: cn=openidm,ou=Groups,dc=example,dc=com
uniqueMember: uid=jdoe,ou=People,dc=example,dc=com
cn: openidm
objectClass: groupOfUniqueNames
objectClass: top
dn: cn=openidm2,ou=Groups,dc=example,dc=com
uniqueMember: uid=bjensen,ou=People,dc=example,dc=com
uniqueMember: uid=jdoe,ou=People,dc=example,dc=com
cn: openidm2
objectClass: groupOfUniqueNames
objectClass: top
</programlisting>
<para>The user with dn <literal>uid=jdoe,ou=People,dc=example,dc=com</literal>
<para>There is an additional user, <literal>bjensen</literal> in the
sample LDIF file. This user is essentially a "dummy" user, provided for
compliance with RFC 4519, which stipulates that every
<literal>groupOfUniqueNames</literal> object must contain at least one
<literal>uniqueMember</literal>. <literal>bjensen</literal> is not actually
used in this sample.</para>
</section>
<section xml:id="install-sample2d">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 2d.</para>
</section>
<section xml:id="run-sample2d">
<title>Running the Sample</title>
<para>Run reconciliation <emphasis>for the groups mapping</emphasis> over
the REST interface.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapGroups_managedGroup"</userinput></screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<para>With the configuration of sample 2d, OpenIDM creates group objects from
LDAP in OpenIDM. To list group objects by ID, run a query over the REST interface.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET
<para>The resulting JSON object should include content similar to the
following.</para>
<programlisting language="javascript">
{
"result":[
{
"_id":"3c704429-aacd-4995-816a-fac33451c642"
"_rev": "0",
},
{
"_id":"b0982152-5099-4358-bdd1-45a39ebe0d77"
"_rev": "0",
}
]
"resultCount": 2,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
}</programlisting>
<para>To retrieve a group, get the object by ID.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
"https://localhost:8443/openidm/managed/group/b0982152-5099-4358-bdd1-45a39ebe0d77"</userinput></screen>
<para>Your group's object should be similar to the following:</para>
<programlisting language="javascript">
{
"name": [
"openidm"
],
"uniqueMember": [
"uid=jdoe,ou=People,dc=example,dc=com"
],
"description": [],
"dn": "cn=openidm,ou=Groups,dc=example,dc=com",
"_rev": "0",
"_id": "b0982152-5099-4358-bdd1-45a39ebe0d77"
}
</programlisting>
</section>
</section>
<section xml:id="more-sample3">
<title>Sample 3 - Scripted SQL Implementation of Groovy Connector 1.4.0.0</title>
<para>
OpenICF 1.4 introduces a new, generic Groovy Connector. The Groovy Connector
is a scripted connector that enables you to run Groovy scripts on any
external resource. Without a specific implementation, the Groovy connector
does not do anything.
</para>
<para>
This sample demonstrates a Scripted SQL implementation of the Groovy
Connector in which an instance of the Scripted SQL framework is made to work
with the HRDB schema. The "connector" in this sample is therefore really an
HRDB connector that is implemented with the help of the Scripted SQL (Groovy)
connector framework.
</para>
<para>
The Groovy connector is bundled with OpenIDM ${serverDocTargetVersion}, in
</para>
<para>
The connector configuration file for this sample
indicates the Scripted SQL implementation of the Groovy connector as follows:
</para>
<programlisting language="javascript">{
"name" : "scriptedsql",
"connectorRef" : {
"bundleName" : "org.forgerock.openicf.connectors.groovy-connector",
"bundleVersion" : "${openicfBundleVersion}",
},
... </programlisting>
<para>
This sample configuration assumes a MySQL server, running on the localhost,
and listening on port 3306. The sample database, HRDB, is created with the
</para>
<para>
The Groovy scripts required for the sample are located in the
these scripts to address the requirements of your specific deployment,
however, the sample scripts are a good starting point on which to base your
customization.
</para>
<note>
<para>
This sample is supported with Java version 7 only. The dependencies required
and do not require a separate download.
</para>
<para>
If you are using the Scripted SQL connector implementation with Java version
6, you must download the related dependencies. For more information, see
<xref linkend="sample-3-java-6" /> at the end of this section.
</para>
</note>
<para>
Prepare a fresh installation of OpenIDM before trying this sample.
</para>
<section xml:id="external-mysql-config-sample3b">
<title>External Configuration</title>
<para>
Before you start, make sure that MySQL is running.
</para>
<procedure>
<step>
<para>
Ensure that the connection details in the connector configuration file
match the details of your MySQL instance. The default configuration is as
follows:
</para>
<programlisting language="javascript">"configurationProperties" : {
"username" : "root",
"password" : "password",
"autoCommit" : true,
"reloadScriptOnExecution" : false,
"authenticateScriptFileName" : "AuthenticateScript.groovy",
"createScriptFileName" : "CreateScript.groovy",
"testScriptFileName" : "TestScript.groovy",
"searchScriptFileName" : "SearchScript.groovy",
"deleteScriptFileName" : "DeleteScript.groovy",
"updateScriptFileName" : "UpdateScript.groovy",
"syncScriptFileName" : "SyncScript.groovy",
"schemaScriptFileName" : "SchemaScript.groovy",
"classpath" : [
"&{launcher.project.location}/tools"
]
}, </programlisting>
<itemizedlist>
<para>
As indicated in the preceding excerpt of the connector configuration
file, the sample expects the following MySQL configuration:
</para>
<listitem>
<para>
The database is available on the local host.
</para>
</listitem>
<listitem>
<para>
The database listens on port 3306.
</para>
</listitem>
<listitem>
<para>
You can connect over the network to the database with user
<literal>root</literal> and password <literal>password</literal>.
</para>
</listitem>
<listitem>
<para>
The MySQL instance serves a database named <literal>HRDB</literal>.
</para>
</listitem>
</itemizedlist>
</step>
<step>
<para>
The database schema is described in the data definition language file,
<literal>HRDB</literal> database and its tables, import the file into
MySQL before running the sample.
</para>
<screen>$ <userinput>mysql -u root -p < /path/to/openidm/samples/sample3/data/sample_HR_DB.mysql</userinput>
Enter password:
$ </screen>
<para>
The import creates a database named <literal>HRDB</literal> with a table
named <literal>Users</literal>.
</para>
<para>
After importing the schema, review the contents of the
<literal>HRDB</literal> database as follows:
</para>
<screen><userinput>$ mysql -u root -p</userinput>
mysql > <userinput>use HRDB;</userinput>
<computeroutput>Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed</computeroutput>
mysql > <userinput>select * from Users;</userinput>
<computeroutput>
+----+--------+--------------+-----------+----------+---------------+--------...
| id | uid | password | firstname | lastname | fullname | email ...
+----+--------+------------------------------------------+-----------+-------...
| 1 | bob | e38ad2149... | Bob | Fleming | Bob Fleming | Bob.Fle...
| 2 | rowley | 2aa60a8ff... | Rowley | Birkin | Rowley Birkin | Rowley....
| 3 | louis | 1119cfd37... | Louis | Balfour | Louis Balfour | Louis.B...
| 4 | john | a1d7584da... | John | Smith | John Smith | John.Sm...
| 5 | jdoe | edba955d0... | John | Doe | John Doe | John.Do...
+----+--------+------------------------------------------+-----------+-------...
5 rows in set (0.00 sec)
</computeroutput></screen>
</step>
</procedure>
<para>
You can exit from the MySQL prompt with the <command>quit</command>
command.
</para>
<note>
<para>
The passwords in the output shown above are hashed to the SHA-1 standard,
as they cannot be read into OpenIDM as clear text. The SHA-1 Hash function
is used for compatibility reasons. In a production database, you should use
a more secure algorithm.
</para>
</note>
</section>
<section xml:id="install-sample3">
<title>Install the Sample</title>
<procedure>
<step>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>.
</para>
</step>
<step>
<para>
Download the <link xlink:show="new"
xlink:href="http://dev.mysql.com/downloads/connector/j/5.1.html">MySQL
Driver</link>, (MySQL Connector/J, version 5.1 or later) from the MySQL
website. Unpack the download and copy the .jar into the
</para>
<screen>$ cp mysql-connector-java-<replaceable>version</replaceable>-bin.jar /path/to/openidm/bundle/</screen>
</step>
<step>
<para>
Start OpenIDM with the configuration for sample 3.
</para>
<computeroutput>Executing /startup.sh...
Using OPENIDM_OPTS: -Xmx1024m -Xms1024m
OpenIDM version "${serverDocTargetVersion}" (revision: 0) null null
-> OpenIDM ready</computeroutput></screen>
</step>
</procedure>
</section>
<section xml:id="run-sample3">
<title>Reconciling the Repository</title>
<procedure>
<step>
<para>
sample includes the mapping <literal>systemHrdb_managedUser</literal>,
which synchronize users from the source <literal>HRDB</literal> table with
the target OpenIDM repository. Run the reconciliation operation with the
following command.
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
<computeroutput>{"_id":"179d3685-c850-4f30-a9ca-c6e37fe3f25d"}</computeroutput></screen>
<para>
The reconciliation operation returns an <literal>_id</literal> and creates
the five users from the MySQL database in the OpenIDM repository.
</para>
</step>
<step>
<para>
Retrieve the list of users from the repository by querying the IDs in the
repository. The following example returns the ID, username, and surname
of all users in the repository:
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
"https://localhost:8443/openidm/managed/user?_queryId=query-all&fields=_openidm_id,userName,sn"</userinput>
<computeroutput>{
"remainingPagedResults": -1,
"pagedResultsCookie": null,
"resultCount": 5,
"result": [
{
"sn": "Birkin",
"userName": "rowley",
"_rev": "0",
"_id": "fb207e49-3498-4772-8ad6-72b7c6dec363"
},
{
"sn": "Smith",
"userName": "john",
"_rev": "0",
"_id": "bdb781b6-7225-4438-8af9-31841ceb2f4b"
},
{
"sn": "Balfour",
"userName": "louis",
"_rev": "0",
"_id": "d837d220-ed69-4398-920e-34ea0fa74351"
},
{
"sn": "Fleming",
"userName": "bob",
"_rev": "0",
"_id": "22944fe5-4cd7-4a10-a747-bc9e0dad065e"
},
{
"sn": "Doe",
"userName": "jdoe",
"_rev": "0",
"_id": "21e0a3a2-3233-40d7-ad73-64e2e1f4672e"
}
]
}</computeroutput></screen>
</step>
<step>
<para>
To retrieve the complete user record, include the ID of the user in the
request. The following example returns the record for user
<literal>jdoe</literal>.
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<computeroutput>{
"stateProvince": "",
"userName": "jdoe",
"postalAddress": "",
"effectiveAssignments": {},
"roles": [
"openidm-authorized"
],
"country": "",
"effectiveRoles": [
"openidm-authorized"
],
"givenName": "John",
"address2": "",
"lastPasswordAttempt": "Thu Sep 18 2014 20:24:11 GMT+0200 (SAST)",
"passwordAttempts": "0",
"sn": "Doe",
"mail": "John.Does@example.com",
"city": "",
"lastPasswordSet": "",
"organization": "ENG",
"postalCode": "",
"_id": "21e0a3a2-3233-40d7-ad73-64e2e1f4672e",
"_rev": "1",
"accountStatus": "active",
"telephoneNumber": ""
} </computeroutput></screen>
</step>
</procedure>
</section>
<section xml:id="sample3-paging">
<title>Using Paging With Sample 3</title>
<para>
All OpenICF ${openicfBundleVersion} connectors support the use of paging
parameters to restrict query results. The following command indicates that
only two records should be returned (<literal>_pageSize=2</literal>) and
that the records should be sorted according to their
<literal>timestamp</literal> and <literal>_id</literal>
(<literal>_sortKeys=timestamp,id</literal>). Including the
<literal>timestamp</literal> in the sort ensures that, as you page through
the set, changes to records that have already been visited are not lost.
Instead, those records are pushed onto the last page.
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
"https://localhost:8443/openidm/system/scriptedsql/account?_queryId=query-all-ids&_pageSize=2&_sortKeys=timestamp,id"</userinput>
<computeroutput>{
"remainingPagedResults": -1,
"pagedResultsCookie": "2014-09-10 12:18:46.0,2",
"resultCount": 2,
"result": [
{
"_id": "1",
"uid": "bob"
},
{
"_id": "2",
"uid": "rowley"
}
]
}
</computeroutput></screen>
<para>
The <literal>"pagedResultsCookie"</literal> is used by the server to keep
track of the position in the search results. You can ignore the
<literal>"remainingPagedResults": -1</literal> in the output. The real value
of this property is not returned because the scripts that the connector uses
do not do any counting of the records in the resource.
</para>
<para>
Using the <literal>"pagedResultsCookie"</literal> from the previous step,
run a similar query, to retrieve the following set of records in the
database. You must URL-encode the space character between the date and time
in the <literal>"pagedResultsCookie"</literal> value, with
<literal>%20</literal>, as shown in the following example:
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<computeroutput>{
"remainingPagedResults": -1,
"pagedResultsCookie": "2014-09-10 12:18:46.0,4",
"resultCount": 2,
"result": [
{
"_id": "3",
"uid": "louis"
},
{
"_id": "4",
"uid": "john"
}
]
}</computeroutput></screen>
<para>
For more information about paging support, see <link xlink:show="new"
xlink:href="integrators-guide#paging-query-results"
Results</citetitle></link> in the <citetitle>Integrator's Guide</citetitle>.
</para>
</section>
<section xml:id="sample3-updating-mysql">
<title>Reconciling the MySQL Database</title>
<procedure>
<para>
The second mapping defined in the mapping configuration file for this
sample (<literal>managedUser_systemHrdb</literal>) synchronizes users from
the source OpenIDM repository to the target <literal>HRDB</literal> table.
Instead of running a manual reconciliation operation to synchronize these
resources, you can edit one of the user records in the OpenIDM UI. Changes
are propagated automatically, through the automatic synchronization
mechanism.
</para>
<step>
<para>
Log in to the OpenIDM UI (https://localhost:8443/openidmui) as any one of
the users that was created in the repository by the previous
reconciliation operation.
</para>
<para>
To obtain the clear text passwords of these users, look at the
</para>
<para>
For example, log into the UI as user <literal>john</literal> with the
password <literal>password4</literal>.
</para>
<mediaobject>
<imageobject>
</imageobject>
</mediaobject>
</step>
<step>
<para>
Update the password or profile of the user <literal>john</literal> (or the
user as whom you logged in in the previous step).
</para>
<para>
The following example updates the email address for user
<literal>john</literal> to <literal>John.P.Smith@example.com</literal>.
</para>
<mediaobject>
<imageobject>
</imageobject>
</mediaobject>
</step>
<step>
<para>
Changes are automatically synchronized to the MySQL database. Retrieve
user <literal>john</literal>'s record from the MySQL database by including
his <literal>_id</literal> in the query, for example:
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<computeroutput>{
"_id": "4",
"email": "John.P.Smith@example.com",
"organization": "SUPPORT",
"firstName": "John",
"lastName": "Smith",
"uid": "john",
"fullName": "John Smith"
}</computeroutput></screen>
</step>
</procedure>
</section>
<section xml:id="sample-3-java-6">
<title>Using Sample 3 With Java Version 6</title>
<para>
The default sample works only with Java Version 7, and bundles the required
sample with Java Version 6, you must remove these dependencies and download
the dependencies specific to Java 6. Follow these steps:
</para>
<procedure>
<step>
<para>
folder:
</para>
<itemizedlist>
<listitem>
<para>
</para>
</listitem>
<listitem>
<para>
</para>
</listitem>
</itemizedlist>
</step>
<step>
<para>
Create a <filename>lib</filename> folder in the OpenIDM installation
directory.
</para>
$ mkdir lib</userinput></screen>
</step>
<step>
<para>
directory:
</para>
<itemizedlist>
<listitem>
<para>
<link xlink:href="http://search.maven.org/#artifactdetails%7Corg.apache.geronimo.ext.tomcat%7Cjuli%7C7.0.39.2%7Cbundle"
</para>
</listitem>
<listitem>
<para>
<link xlink:href="http://search.maven.org/#artifactdetails%7Corg.apache.tomcat%7Ctomcat-jdbc%7C7.0.53%7Cjar"
</para>
</listitem>
</itemizedlist>
</step>
</procedure>
<para>
The remainder of the sample should work as for Java Version 7.
</para>
</section>
</section>
<section xml:id="more-sample4">
<title>Sample 4 - CSV to XML File</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 4 - CSV file</secondary>
</indexterm>
<para>Sample 4 works with two databases, a comma-separated value file
and an XML file. There is no need to include any external
resources.
</para>
<para>
A correlation query is used to relate the records in these
two files.
</para>
<section xml:id="install-sample4">
<title>Install the Sample</title>
<para>No external configuration is required for this sample. Prepare
OpenIDM as described in <xref linkend="preparing-openidm"/>, then start up
OpenIDM with the configuration of sample 4.</para>
</section>
<section xml:id="examine-sample4">
<title>Check and then Run the Sample</title>
<para>
users. The first line of the file sets the attribute names.
</para>
<para>
Review the current contents of the database in the
purposes, make a copy of the file in a temporary directory with a command
like:
</para>
<para>
The reconciliation command run here uses the information
</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
<para>Check the results of reconciliation. Review the updated contents
<para>
If you want to experiment further, try changing the data in the
again.
</para>
<para>
These users will not be visible from the OpenIDM UI, since they are mapped
directly between the XML and CSV files. The internal OpenIDM repository is
not updated in this sample.
</para>
</section>
</section>
<section xml:id="more-sample5">
<title>Sample 5 - Synchronization of Two Resources</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 5 - Synchronization of two resources</secondary>
</indexterm>
<para>
Sample 5 demonstrates the flow of data from one external resource to
another. The resources are named <literal>LDAP</literal> and
<literal>AD</literal> but in the sample, both directory-like resources are
simulated with XML files.
</para>
<para>
You can optionally configure an outbound email service, if you want to
receive emailed reconciliation summaries, as described in the following
section.
</para>
<section xml:id="email-sample5">
<title>Configure Email for the Sample</title>
<para>
If you do not configure the email service, the functionality of the sample
does not change. However, you might see the following message at the
OpenIDM console when you run a reconciliation operation:
</para>
<screen>Email service not configured; report not generated.</screen>
<procedure>
<para>
To configure an email summary, follow these steps:
</para>
<step>
<para>
</para>
</screen>
</step>
<step>
<para>
as described in the chapter on
<link xlink:show="new" xlink:href="integrators-guide#chap-mail"
Email</citetitle></link>.
</para>
</step>
<step>
<para>
Near the start of the file, configure the OpenIDM email service to send
statistics to the email addresses of your choice:
</para>
<programlisting language="javascript">
var params = {
//UPDATE THESE VALUES
from : "openidm@example.com",
to : "youremail@example.com",
cc : "idmadmin2@example.com,idmadmin3@example.com",
subject : "Recon stats for " + global.mappingName,
},
template,
</programlisting>
</step>
</procedure>
</section>
<section xml:id="install-sample5">
<title>Install the Sample</title>
<para>
No external configuration is required for this sample. Prepare OpenIDM as
described in <xref linkend="preparing-openidm"/>, then start OpenIDM with
the configuration of sample 5.
</para>
<para>
The XML files that simulate the resources are located in the
OpenIDM with the sample 5 configuration, OpenIDM creates the
until you run reconciliation.
</para>
</section>
<section xml:id="run-sample5">
<title>Run the Sample</title>
<para>
Run a reconciliation operation, to synchronize the contents of the simulated
LDAP resource to the OpenIDM repository.
</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapAccounts_managedUser"</screen>
<para>
This command creates a user in the repository. It is not necessary to run a
second reconciliation operation to synchronize the AD resource. Automatic
synchronization propagates any change made to managed users in the OpenIDM
repository to the simulated AD resource.
</para>
<para>
contain information for the same user that was present in the startup
</para>
<para>
Alternatively, you can list users in the AD resource with the following
command:
</para>
<screen>$ <userinput>curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
</userinput>
<computeroutput>{
"result" : [ {
"name" : "DDOE1",
"__UID__" : "8dad9df3-820d-41ea-a3ab-a80c241bbc98",
"_id" : "8dad9df3-820d-41ea-a3ab-a80c241bbc98"
} ],
"resultCount" : 1,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}</computeroutput>
</screen>
<para>
You can use the <literal>_id</literal> of the user to read the user
information from the AD resource, for example:
</para>
<screen>$ <userinput>curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
</userinput>
<computeroutput>{
"email" : [ "mail1@example.com" ],
"name" : "DDOE1",
"__UID__" : "8dad9df3-820d-41ea-a3ab-a80c241bbc98",
"firstname" : "Darth",
"lastname" : "Doe",
"_id" : "8dad9df3-820d-41ea-a3ab-a80c241bbc98"
}[</computeroutput></screen>
<para>
To verify that the sample is working, repeat the process. Set up a second
that file might appear with a second user (<literal>GDOE1</literal>) is
shown here:
</para>
<programlisting language="xml" width="120"><?xml version="1.0" encoding="UTF-8"?>
<icf:OpenICFContainer
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://openidm.forgerock.com/xml/ns/public/resource/instances/resource-schema-extension
<ri:__ACCOUNT__>
<icf:__UID__>1</icf:__UID__>
<icf:__PASSWORD__>TestPassw0rd2</icf:__PASSWORD__>
<ri:firstname>Darth</ri:firstname>
<icf:__DESCRIPTION__>Created By XML1</icf:__DESCRIPTION__>
<icf:__NAME__>DDOE1</icf:__NAME__>
<ri:email>mail1@example.com</ri:email>
<ri:lastname>Doe</ri:lastname>
</ri:__ACCOUNT__>
<ri:__ACCOUNT__>
<icf:__UID__>2</icf:__UID__>
<icf:__PASSWORD__>TestPassw0rd2</icf:__PASSWORD__>
<ri:firstname>Garth</ri:firstname>
<icf:__DESCRIPTION__>Created By XML1</icf:__DESCRIPTION__>
<icf:__NAME__>GDOE1</icf:__NAME__>
<ri:email>mail2@example.com</ri:email>
<ri:lastname>Doe</ri:lastname>
</ri:__ACCOUNT__>
</icf:OpenICFContainer></programlisting>
<para>
Rerun the reconciliation and query REST commands shown previously. The
reconciliation operation creates the new user from the simulated LDAP
resource in the OpenIDM repository. Automatic synchronization then creates
that user in the AD resource.
</para>
</section>
</section>
<section xml:id="more-sample5b">
<title>Sample 5b - Compensated Synchronization with <literal>onSync</literal></title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 5b - Synchronization with the <literal>onSync</literal>
script hook</secondary>
</indexterm>
<para>
The compensated synchronization mechanism depicted in this sample can help
manage the risks associated with synchronizing data across multiple
resources.
</para>
<para>
replays that change to all configured external resources. If synchronization
fails for one target resource (for example, due to a policy validation
failure on the target, or the target being unavailable), the synchronization
operation stops at that point. The effect is that a record might be changed
in the repository, and in the targets on which synchronization was successful,
but not on the failed target, or any targets that would have been
synchronized after the failure. This situation can result in disparate data
sets across resources. While a reconciliation operation would eventually
bring all targets back in sync, reconciliation can be an expensive operation
with large data sets.
</para>
<para>
The compensated synchronization mechanism ensures that either all resources
are synchronized successfully, or that the original change is rolled back.
This mechanism uses an <literal>onSync</literal> script hook configured with
</para>
<para>
Sample 5b is similar to sample 5 in that it simulates two external resources
with XML files (located in the
OpenIDM with the sample. Sample 5b adds the <literal>onSync</literal> script
hook to the process, configured in the
</para>
<para>
the <literal>onSync</literal> hook, which calls the
</para>
<programlisting language="javascript">
...
},
"onSync" : {
"type" : "text/javascript",
"file" : "compensate.js"
},
</programlisting>
<para>
You can use the <literal>onSync</literal> script hook to ensure that changes
made in the repository are synchronized to all external resources, or that
no changes are made. For more information about how automatic synchronization
uses the <literal>onSync</literal> script hook, see <link xlink:show="new"
xlink:role="http://docbook.org/xlink/role/olink"
xlink:href="integrators-guide#sync-types-automatic"><citetitle>How Automatic
Sync works with onSync</citetitle></link> in the <citetitle>Integrator's
Guide</citetitle>.
</para>
<para>
You can optionally configure an outbound email service for this sample, if
you want to receive emailed reconciliation summaries. The email service
configuration is identical to that of sample 5
(<xref linkend="email-sample5" />).
</para>
<section xml:id="install-sample5b">
<title>Install the Sample</title>
<para>No external configuration is required for this sample. Prepare
OpenIDM as described in <xref linkend="preparing-openidm"/>, then start
OpenIDM with the configuration of sample 5b.</para>
<para>
The XML files that simulate an external LDAP and AD resource are now located
contain users until you run reconciliation.
</para>
<para>
Run the sample in exactly the same way that you did for Sample 5, following
the steps in <xref linkend="run-sample5" />.
</para>
</section>
<section xml:id="onsync-sample5b">
<title>Demonstrate onSync</title>
<para>
To demonstrate integration of the samples with the OpenIDM UI, this sample
uses the UI to view and make changes to user objects in the repository.
However, you can also use the REST interface to make these changes, as shown
in the previous section.
</para>
<para>
Log into the OpenIDM UI as the administrative user. On a local system,
administrative account and password are both <literal>openidm-admin</literal>.
</para>
<para>
Make a change to the data of an existing user (<literal>DDOE1</literal>).
With automatic synchronization, that change is reflected almost immediately
on the external resources. For sample 5b, you should see the changes in both
directory. Alternatively, you can query the external resources over REST, as
described previously.
</para>
<para>
The synchronization is successful, across all configured external resources,
so the updated user record can be seen in both the
</para>
<para>
The next step is to simulate a problem connecting to the LDAP resource. One
way to do so on the local system is to rename the LDAP data file so that it
is unreadable. On a Linux system, the following command, as an
administrative user, would serve that purpose:
</para>
<para>
In the UI, now try another update to user <literal>DDOE1</literal>. With the
modified filename of the simulated LDAP resource, automatic synchronization
cannot write to this resource. An error similar to the following is
</para>
<screen>Data file does not exist:
<para>
Although the AD resource is available, automatic synchronization will not
reach this resource, because the mapping is specified
</para>
<para>
When the automatic synchronization fails for the LDAP resource, the
<literal>onSync</literal> hook invokes the
the original change by performing another update to DDOE1 in the repository
synchronization to the AD and LDAP resources.
</para>
<para>
Because the LDAP resource is still unreadable, the synchronization to LDAP
again. This time, however, the script recognizes that the change was
originally called as a result of a compensation and aborts.
</para>
<para>
The original synchronization error from the first update is thrown from the
script and the UI should display that error. If you refresh the UI, and view
that user entry again, you will notice that the change to the entry has been
reverted.
</para>
<para>
Note that if you change the name of the AD resource file (to make it
successfully with the LDAP resource (because that mapping appears first in
entry, and the LDAP resource.
</para>
</section>
</section>
<section xml:id="more-sample6">
<title>Sample 6 - LiveSync With an AD Server</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 6 - LiveSync between two LDAP servers</secondary>
</indexterm>
<para>
Sample 6 resembles sample 5, but demonstrates LiveSync from an external
resource. Sample 6 includes configuration files for two scenarios, depending
on whether you have a live Active Directory (AD) service, or whether you
need to simulate an AD service with an OpenDJ server. Each scenario is
associated with a file in the
directory.
</para>
<variablelist>
<varlistentry>
<term>Active AD Deployment</term>
<listitem>
<para>
If you have an actual AD deployment available, copy the
<filename>conf/</filename> subdirectory. You can then configure
synchronization between an OpenDJ Directory Server and an active AD
deployment.
</para>
<para>
As this sample demonstrates synchronization <emphasis>from</emphasis> the
AD server <emphasis>to</emphasis> OpenDJ, data on the AD server is not
changed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Simulated AD Deployment</term>
<listitem>
<para>
If you need to simulate an AD deployment, copy the
<filename>conf/</filename> subdirectory. You can then configure
synchronization between an OpenDJ Directory server and a simulated
AD server.
</para>
<para>
This sample simulates an AD server on the same instance of OpenDJ, using a
different base DN.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
The options shown in the associated configuration files can be easily
modified to work with any standard LDAP server.
</para>
<section xml:id="more-sample6-realad">
<title>Sample 6 with an Active AD Deployment</title>
<para>
If you have an existing, active instance of AD, set up OpenDJ, as described
in the <link xlink:show="new"
<citetitle>OpenDJ Installation Guide</citetitle></link>.
</para>
<para>
During installation, populate OpenDJ with the data in the
</para>
<para>
The actions run in this sample should not change any data on the AD server.
</para>
</section>
<section>
<title>Sample 6 with a Simulated AD Deployment</title>
<para>
In this sample, an AD deployment is simulated with a different baseDN
(<literal>dc=fakead,dc=com</literal>) on the same OpenDJ server instance.
You can also simulate the AD server with a separate OpenDJ instance, running
on the same host, as long as the two instances communicate on different
ports. The data for the simulated AD instance is contained in the file
</para>
</section>
<section xml:id="external-resource-sample6">
<title>External Configuration</title>
<section xml:id="prepare-livesync-sample6">
<title>Prepare OpenDJ For LiveSync</title>
<para>
This sample assumes a replicated OpenDJ server. When configured,
OpenDJ replication includes an External Change Log (ECL), required to
support LiveSync. LiveSync detects changes in OpenDJ by reading the ECL.
</para>
<para>
To activate the OpenDJ ECL, enable replication as described in the
<link xlink:show="new"
xlink:href="http://opendj.forgerock.org/opendj-server/doc/admin-guide/index.html#chap-replication">
<citetitle>OpenDJ Administration Guide chapter on Managing Data
Replication</citetitle></link>
</para>
<para>
Once configured, you can proceed with either an active or simulated AD
deployment.
</para>
</section>
<section xml:id="external-resource-sample6-active">
<title>External Configuration for an Active AD Deployment</title>
<para>
To configure an active AD deployment for sample 6, open the
a text editor. Update it as needed. At minimum, you should check and
if needed update the following parameters in that file, as shown in the
following table:
</para>
<table xml:id="realad-json-configuration">
<title>Key Parameters for an Active AD Configuration</title>
<tgroup cols="2">
<colspec colnum="1" colwidth="2*"/>
<colspec colnum="2" colwidth="3*"/>
<thead>
<row>
<entry>Option</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>host</entry>
</row>
<row>
<entry>port</entry>
<entry>The LDAP port; the default is 389.</entry>
</row>
<row>
<entry>ssl</entry>
<entry>By default, SSL is not used.</entry>
</row>
<row>
<entry>principal</entry>
<entry>The full DN of the account to bind with, such as
"CN=Administrator,CN=Users,DC=example,DC=com"</entry>
</row>
<row>
<entry>credentials</entry>
<entry>If a password is used, replace null with that password.
When OpenIDM starts, it encrypts that password in the
</row>
<row>
<entry>baseContexts</entry>
<entry>The DNs for account containers, such as
["CN=Users,DC=Example,DC=com"]</entry>
</row>
<row>
<entry>baseContextsToSynchronize</entry>
<entry>Set to the same value as <literal>baseContexts</literal></entry>
</row>
<row>
<entry>accountSearchFilter</entry>
<entry>Default searches for active user (not computer) accounts</entry>
</row>
<row>
<entry>accountSynchronizationFilter</entry>
<entry>Default synchronizes with active user (not computer)
accounts</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
If you do not want to filter out computer and disabled user accounts,
set the <literal>accountSearchFilter</literal> and
<literal>accountSynchronizationFilter</literal> to <literal>null</literal>.
</para>
</section>
<section xml:id="external-resource-sample6-simulated">
<title>External Configuration for a Simulated AD Deployment</title>
<para>
Not everyone has a testable instance of AD readily available. For such
the <filename>data/</filename> subdirectory to simulate an AD deployment.
</para>
<para>
If you have not already done so, copy the
<filename>conf</filename> subdirectory.
</para>
<para>
As previously mentioned, you can use a separate OpenDJ instance to
simulate the AD server. However, the following instructions assume that
the simulated AD server runs on the same OpenDJ instance.
</para>
<para>
note the following:
</para>
<itemizedlist>
<listitem>
<para>
OpenDJ directory server uses port 1389 by default for users who cannot
use privileged ports, so this is the port that is specified in the
provisioner file. Adjust the port if your OpenDJ server is listening on
a different port.
</para>
</listitem>
<listitem>
<para>
The simulated AD server uses the base DN
<literal>dc=fakead,dc=com</literal>.
</para>
</listitem>
</itemizedlist>
<para>
To load the data for the simulated AD instance, launch the OpenDJ control
panel, add the simulated AD baseDN (<literal>dc=fakead,dc=com</literal>),
"Append to Existing Data", not "Overwrite Existing Data". Otherwise, the
data in the <literal>dc=example,dc=com</literal> baseDN will be
overwritten.
</para>
</section>
</section>
<section xml:id="install-sample6">
<title>Start OpenIDM with Sample 6</title>
<para>
Now that OpenDJ and a real or simulated AD database is configured,
prepare OpenIDM as described in <xref linkend="preparing-openidm"/>.
You can then start OpenIDM with the configuration for sample 6.
</para>
</section>
<section xml:id="run-sample6">
<title>Run the Sample</title>
<para>The following sections show how to run the sample with command-based
reconciliation with a REST call, and to configure scheduled reconciliation
with LiveSync.
</para>
<section xml:id="run-sample6-reconciliation">
<title>Using Reconciliation</title>
<para>
Now that OpenIDM is in operation, review the entries in the OpenDJ
data store. When you run reconciliation, any entries that share the same
<literal>uid</literal> with the AD data store will be updated with the
contents from AD.
</para>
<para>
If you have set up the simulated AD data store as described in
<xref linkend="external-resource-sample6-simulated" />, compare the
entries for <literal>uid=jdoe</literal> as shown in the
Note the different values of <literal>givenName</literal> for
<literal>uid=jdoe</literal>.
</para>
<para>
Run reconciliation over the REST interface. If you have followed the
instructions for the simulated AD data store, the following command
takes the information for user <literal>jdoe</literal> imported from the
Johnny, and synchronizes that information to the LDAP database, overwriting
the <literal>givenName</literal> of John for that same user
<literal>jdoe</literal>.
</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemAdAccounts_managedUser"</screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<screen>{"_id":"9ece3807-08c3-4ec6-87fb-a6a2d0c71cee"}</screen>
<para>
The reconciliation operation synchronizes the data in the AD deployment
automatically synchronized to the OpenDJ server, as described in
<link xlink:show="new" xlink:href="integrators-guide#handling-sync"
xlink:role="http://docbook.org/xlink/role/olink">
<citetitle>Synchronization Situations and Actions</citetitle></link>.
</para>
<para>After reconciliation, list all users in the OpenDJ server data
store.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>The result should resemble the following JSON object.</para>
<programlisting language="javascript">{
"result": [ {
"dn" : "uid=jdoe,ou=People,dc=example,dc=com",
"_id" : "uid=jdoe,ou=People,dc=example,dc=com"
}, {
"dn" : "uid=bjensen,ou=People,dc=example,dc=com",
"_id" : "uid=bjensen,ou=People,dc=example,dc=com"
} ],
"resultCount": 2,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
}</programlisting>
<para>
You see only two entries, as the <literal>uid=jdoe</literal> entry from
<literal>dc=fakead,dc=com</literal> overwrites the original LDAP entry for
<literal>uid=jdoe</literal> in the reconciled LDAP data store.
</para>
<para>
To read the user object in the OpenDJ server, run the
<command>ldapsearch</command> command. The following example returns the
entry for user <literal>uid=jdoe</literal>:
</para>
--port 1389 \
--baseDN dc=example,dc=com \
"(uid=jdoe)"</userinput></screen>
</section>
<section xml:id="run-sample6-live-sync">
<title>Using LiveSync</title>
<para>You can start reconciliation by using a scheduled configuration or
by using the REST interface directly. However, to use LiveSync, you must
configure a schedule. When LiveSync is active, the default schedule in the
configuration file runs LiveSync every 15 seconds.
</para>
<para>
LiveSync pushes changes made in the AD data store to the OpenIDM repository,
automatically.
</para>
<para>
LiveSync is disabled by default. To activate LiveSync, change the
value of the <literal>"enabled"</literal> property
from <literal>false</literal> to <literal>true</literal>.
</para>
<programlisting language="javascript">{
"enabled" : false,
"type" : "cron",
"invokeService" : "provisioner",
"invokeContext" : {
"action" : "liveSync",
},
"invokeLogLevel" : "debug"
}</programlisting>
<procedure xml:id="test-live-sync">
<title>Testing LiveSync</title>
<para>
Now you can test LiveSync. This procedure assumes that you have configured
OpenDJ using the parameters and commands described in this section.
</para>
<step>
<para>
Create an LDIF file with a new user entry (<literal>uid=bsmith</literal>)
that will be added to the simulated AD data store.
</para>
</step>
<step>
<para>
The following is the contents of a sample
<screen>dn: uid=bsmith,ou=People,dc=fakead,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
givenName: Barry
description: Created to see LiveSync work
uid: bsmith
cn: Barry
sn: Smith
mail: bsmith@example.com
telephoneNumber: 1-415-523-0772
userPassword: passw0rd</screen>
</para>
</step>
<step>
<para>
</para>
</step>
<step>
<para>
Use the <command>ldapmodify</command> command to add the
</para>
--port 1389
--defaultAdd
--bindDN "cn=Directory Manager"
--bindPassword password
</step>
<step>
<para>
Now you can test synchronization by viewing the new user in the OpenIDM
repository. The easiest way to do this, is through OpenIDM UI. You should
be able to log into the UI with any of the accounts in the AD data store.
For this example, log into the UI as user <literal>bsmith</literal>, with
password <literal>passw0rd</literal>. The fact that you can log into the
UI as this new user indicates that LiveSync has synchronized the user
</para>
</step>
<step>
<para>
Automatic synchronization pushes this change out to the OpenDJ data store.
To test this synchronization operation, search the OpenDJ baseDN for the
new user entry.
</para>
--port 1389 \
--baseDN ou=people,dc=example,dc=com \
"(uid=bsmith)"</userinput></screen>
</step>
</procedure>
</section>
</section>
</section>
<section xml:id="more-sample7">
<title>Sample 7 - Scripting a SCIM-like Schema</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 7 - Scripting a SCIM-like Schema</secondary>
</indexterm>
<para>Sample 7 demonstrates how you can use OpenIDM to expose user data with a
SCIM-like schema. The sample uses the XML file connector to read in attributes
from external accounts and construct a JSON object for users stored in the
OpenIDM repository. For more information about SCIM schema, see
<link xlink:show="new"
<citetitle>System for Cross-Domain Identity Management:
Core Schema 1.1</citetitle></link>.</para>
<section xml:id="install-sample7">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 7.</para>
</section>
<section xml:id="run-sample7">
<title>Running the Sample</title>
<para>Run a reconciliation to pull the user from
OpenIDM internal repository.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"</userinput></screen>
<para>Reconciliation creates a user object in the repository. Retrieve the
user from the repository.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>The user object has the following JSON representation.</para>
<programlisting language="javascript">{
"_id" : "DDOE1",
"_rev" : "2",
"schemas" : "['urn:scim:schemas:core:1.0']",
"ims" : [ {
"type" : "aim",
"value" : "jonyOnAim"
}, {
"type" : "skype",
"value" : "skyperHiasl"
} ],
"locale" : null,
"phoneNumbers" : [ {
"type" : "work",
"value" : "1234567"
}, {
"type" : "home",
"value" : "1234568"
} ],
"emails" : [ {
"type" : "work",
"value" : "hallo@example.com",
"primary" : true
}, {
"type" : "home",
"value" : "jdoe@forgerock.com"
} ],
"externalId" : "DDOE1",
"preferredLanguage" : "en_US",
"meta" : {
"lastModified" : "Thu May 01 2014 12:57:10 GMT-0800 (GMT-08:00)",
"created" : "Thu May 01 2014 12:56:27 GMT-0800 (GMT-08:00)"
},
"userType" : "permanent",
"photos" : [ {
"type" : "photo",
}, {
"type" : "thumbnail",
} ],
"title" : "Mr.Universe",
"profileUrl" : "https://login.example.com/DDOE1",
"nickName" : "Jonny",
"name" : {
"familyName" : "Doe",
"middleName" : "Hias",
"formatted" : "Dr. John H Doe III",
"givenName" : "John",
"honorificSuffix" : "III",
"honorificPrefix" : "Dr."
},
"userName" : "DDOE1",
"displayName" : "John Doe",
"addresses" : [ {
"streetAddress" : "100 Universal City Plaza",
"region" : "CA",
"formatted" : "100 Universal City Plaza\nHollywood, CA 91608 USA",
"postalCode" : "91608",
"primary" : "true",
"locality" : "Hollywood",
"type" : "work",
"country" : "USA"
}, {
"streetAddress" : "222 Universal City Plaza",
"region" : "CA",
"formatted" : "222 Universal City Plaza\nHollywood, CA 91622 USA",
"postalCode" : "91622",
"primary" : "false",
"locality" : "Hollywood",
"type" : "home",
"country" : "USA"
} ],
"groups" : [ {
"value" : "usemploys",
"display" : "US Employees"
}, {
"value" : "euemploys",
"display" : "EU Employees"
} ]
}</programlisting>
<para>
transforms the user data from the resource into the JSON object layout
required by SCIM schema.
</para>
</section>
</section>
<section xml:id="more-sample8">
<title>Sample 8 - Logging in Scripts</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 8 - Logging in Scripts</secondary>
</indexterm>
<para>OpenIDM provides a <literal>logger</literal> object with
<literal>debug()</literal>, <literal>error()</literal>,
<literal>info()</literal>, <literal>trace()</literal>, and
<literal>warn()</literal> functions that you can use to log messages to
the OpenIDM console from your scripts.</para>
<section xml:id="install-sample8">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 8.</para>
brief examples of log messages.
</para>
</section>
<section xml:id="run-sample8">
<title>Running the Sample</title>
<para>Run reconciliation over the REST interface.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"</userinput></screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<para>Notice the log messages displayed on the OpenIDM (Felix) console.
The following example omits timestamps and so forth to show only the message
strings.</para>
<programlisting language="none">->
...Case no Source: the source object contains: = null [5235432-...
...Case emptySource: the source object contains: = {lastname=Carter, mobile...
...Case sourceDescription: the source object contains: = Created By XML1
...Case onCreate: the source object contains: = {lastname=Carter, mobile...
...Case result: the source object contains: = {SOURCE_IGNORED={count=0, ids=[]},...</programlisting>
</section>
</section>
<section xml:id="more-sample9">
<title>Sample 9 - Asynchronous Reconciliation Using Workflows</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 9 - asynchronous reconciliation</secondary>
</indexterm>
<para>Sample 9 demonstrates asynchronous reconciliation using workflows.
Reconciliation generates an approval request for each ABSENT user. The
file, which specifies that an <literal>ABSENT</literal> condition should
launch the <literal>managedUserApproval</literal> workflow:</para>
<programlisting language="javascript">...
{
"situation" : "ABSENT",
"action" : {
"workflowName" : "managedUserApproval",
"type" : "text/javascript",
"file" : "workflow/triggerWorkflowFromSync.js"
}
},
... </programlisting>
<para>When the request is approved by an administrator, the absent users are
created by an asynchronous reconciliation process.</para>
<para>Prepare a fresh installation of OpenIDM before trying this
sample.</para>
<section xml:id="install-sample9">
<title>Install the Sample</title>
<para>Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>,
then start OpenIDM with the configuration for sample 9.</para>
</section>
<section xml:id="run-sample9">
<title>Running the Sample</title>
<orderedlist>
<listitem>
<para>Run reconciliation over the REST interface.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"</userinput></screen>
<para>Successful reconciliation returns a reconciliation run ID.</para>
<para>The reconciliation starts an approval workflow for each ABSENT
user. These approval workflows (named <literal>managedUserApproval</literal>)
wait for the request to be approved by an administrator.</para>
</listitem>
<listitem>
<para>Query the invoked workflow task instances over REST.</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>
In this case, the request returns two workflow results, each with a
process ID (<literal>_id</literal>) as well as a process definition
ID. You will use the value of the <literal>_id</literal> shortly.
</para>
<screen>{
"result" : [ {
"tenantId" : "",
"createTime" : "2014-05-01T13:48:42.980-08:00",
"executionId" : "101",
"delegationStateString" : null,
"processVariables" : { },
"_id" : "123",
"processInstanceId" : "101",
"description" : null,
"priority" : 50,
"name" : "Evaluate request",
"dueDate" : null,
"parentTaskId" : null,
"processDefinitionId" : "managedUserApproval:1:3",
"taskLocalVariables" : { },
"suspensionState" : 1,
"assignee" : "openidm-admin",
"cachedElContext" : null,
"queryVariables" : null,
"activityInstanceVariables" : { },
"deleted" : false,
"suspended" : false,
"_rev" : 1,
"revisionNext" : 2,
"category" : null,
"taskDefinitionKey" : "evaluateRequest",
"owner" : null,
"eventName" : null,
"delegationState" : null
}, {
"tenantId" : "",
"createTime" : "2014-05-01T13:48:42.980-08:00",
"executionId" : "102",
"delegationStateString" : null,
"processVariables" : { },
"_id" : "124",
"processInstanceId" : "102",
"description" : null,
"priority" : 50,
"name" : "Evaluate request",
"dueDate" : null,
"parentTaskId" : null,
"processDefinitionId" : "managedUserApproval:1:3",
"taskLocalVariables" : { },
"suspensionState" : 1,
"assignee" : "openidm-admin",
"cachedElContext" : null,
"queryVariables" : null,
"activityInstanceVariables" : { },
"deleted" : false,
"suspended" : false,
"_rev" : 1,
"revisionNext" : 2,
"category" : null,
"taskDefinitionKey" : "evaluateRequest",
"owner" : null,
"eventName" : null,
"delegationState" : null
} ],
"resultCount" : 2,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}</screen>
</listitem>
<listitem>
<para>
Approve the requests over REST, by setting the
<literal>"requestApproved"</literal> parameter for the specified task
instance to <literal>"true"</literal>. Note the use of one of the
values of <literal>_id</literal> in the REST call, in this case,
<literal>124</literal>.
</para>
<para>On UNIX:</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
--data '{"requestApproved": "true"}' \
<para>On Windows:</para>
<screen><userinput>$ curl ^
--cacert self-signed.crt ^
--header "X-OpenIDM-Username: openidm-admin" ^
--header "X-OpenIDM-Password: openidm-admin" ^
--header "Content-Type: application/json" ^
--request POST ^
--data "{\"requestApproved\": \"true\"}" ^
<para>A successful call returns the following:</para>
<screen>{"Task action performed":"complete"}</screen>
</listitem>
<listitem>
<para>
Once the request has been approved, an asynchronous reconciliation
operation runs, which creates the users whose accounts were approved in
the previous step.
</para>
<para>
List the users that were created by the asynchronous reconciliation.
</para>
<screen><userinput>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--request GET \
<para>One user is returned.</para>
<screen>{
"result": [ {
"_rev": "0",
"_id": "1"
} ],
"resultCount": 1,
"pagedResultsCookie": null,
"remainingPagedResults": -1,
}</screen>
</listitem>
</orderedlist>
</section>
</section>
<section xml:id="more-sample-openam">
<title>Sample OpenAM - Configuring Authentication Management for OpenIDM</title>
<indexterm>
<primary>Samples</primary>
<secondary>Sample OpenAM - Authentication Management for OpenIDM</secondary>
</indexterm>
<para>
This sample demonstrates how you can protect a deployment of OpenIDM with
ForgeRock's <link xlink:show="new"
<citetitle>OpenAM Access Management</citetitle></link> product.
</para>
<para>
In this sample, you will use OpenIDM together with OpenAM and ForgeRock's
<citetitle>OpenDJ Directory Services</citetitle></link> product.
</para>
<para>
When configured together, you can demonstrate one use case that maximizes
Identity Relationship Management (IRM) functionality. OpenIDM can maintain
user data in OpenDJ data stores. Once protected by OpenAM, you can configure
rules for authorized access.
</para>
<para>
This sample configures OpenIDM and OpenDJ on one system, with a URL of
</para>
AME-4386 -->
<note>
<para>
At this time, this sample assumes that you have deployed OpenAM 12.
</para>
</note>
<section xml:id="prepare-sample-openam">
<title>Prepare the Sample</title>
<para>
Before installing OpenIDM, you need to prepare your systems. To set up this
sample, you need to take the following basic steps:
</para>
<itemizedlist>
<listitem>
<para>
Install OpenDJ, using a base DN of <literal>dc=example,dc=com</literal>.
This example assumes that you install OpenDJ on the same system as
</para>
<para>
If you set up OpenDJ on a secure port with a self-signed certificate, you
should import that certificate into the OpenIDM datastore, as described in
the following section of the Integrator's Guide: <link xlink:show="new"
xlink:role="http://docbook.org/roles/xlink/role/olink"
xlink:href="integrators-guide#security-management-service"><citetitle>
Accessing the Security Management Service</citetitle></link>.
</para>
</listitem>
<listitem>
<para>
Install an OpenAM 12 server in an environment that OpenIDM can access with
RESTful calls. For installation instructions, see the <link xlink:show="new"
xlink:href="http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/install-guide/index.html">
<citetitle>OpenAM Installation Guide</citetitle></link>. This example
assumes that you have deployed the associated <literal>.war</literal>
file in your selected Java EE container with the following name:
</para>
<para>
When installing OpenAM, configure it to use the OpenDJ data store
</para>
<para>
This sample assumes that you will configure OpenAM-based Single Sign-On
(SSO) as described in the OpenAM Administration Guide. For this sample,
cookie domain as described in the following section of the noted OpenAM
Guide: <link xlink:show="new"
xlink:href="http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/admin-guide/index.html#configure-sso-one-domain">
<citetitle>Configure SSO on One Domain</citetitle></link>.
</para>
</listitem>
<listitem>
<para>
Prepare OpenIDM as described in <xref linkend="preparing-openidm"/>.
</para>
</listitem>
<listitem>
<para>
As OpenAM works with FQDNs, you will need to either set up the noted
an address database such as a DNS server or the static
<filename>hosts</filename> configuration file of both systems.
</para>
</listitem>
<listitem>
<para>
Do not start OpenIDM yet. You need to configure it further.
</para>
</listitem>
</itemizedlist>
<note>
<para>
When you configure OpenAM for this sample, you do not need to install a
Java EE agent. This sample uses the <literal>OPENAM_SESSION</literal>
module to protect OpenIDM.
</para>
</note>
</section>
<section xml:id="configure-openam-sample">
<title>Configuring OpenIDM for the OpenAM Sample</title>
<para>
Before starting OpenIDM, you will need to change two configuration files,
related to authentication and provisioning.
</para>
<section xml:id="configure-openam-sample-auth-json">
<para>
To configure OpenIDM authentication, open the
</para>
<para>
Under <literal>"authModules"</literal>, find the
<literal>"OPENAM_SESSION"</literal> authentication module. The default
entries which you must fill in:
</para>
<programlisting language="javascript">"authModules" : [
{
"name" : "OPENAM_SESSION",
"properties" : {
"openamDeploymentUrl" : "",
"groupRoleMapping" : {
"openidm-admin" : [ ]
},</programlisting>
<para>
Based on a standard <literal>openidm-admin</literal> user and the
previously noted URL and <literal>.war</literal> file for your OpenAM
deployment, you would change the code snippet to:
</para>
<programlisting language="javascript">"authModules" : [
{
"name" : "OPENAM_SESSION",
"properties" : {
"openamDeploymentUrl" : "https://openam.example.com:8443/openam",
"groupRoleMapping" : {
"openidm-admin" : [
"cn=idmAdmins,ou=Groups,dc=example,dc=com"
]
},</programlisting>
<para>
Do remember to include <literal>/openam</literal> in the value of
<literal>"openamDeploymentUrl"</literal>. After the Java EE container used
so that you can access it on the <literal>/openam</literal> endpoint.
</para>
<para>
With the <literal>"groupRoleMapping"</literal>, you can add the
Distinguished Names (DN) of groups to the list. This feature will then
assign the noted role, such as <literal>openidm-admin</literal> to any user
who is a member of one of these groups. For more information on how roles
are assigned, see the following section in the Integrator's Guide on
xlink:href="integrators-guide#openidm-roles" xlink:show="new">
<citetitle>Roles and Authentication</citetitle></link>.
</para>
<!-- The README suggests this is needed only for self-signed certs. I think
this may be required for regular certs too, or does our truststore include
the "standard list"? -->
<para>
The <literal>"openamDeploymentUrl"</literal> shown above assumes that you
are using SSL. If you have a self-signed certificate, you will need to
import that into the OpenIDM truststore file. For more information, see
the following section of the Integrator's Guide: <link xlink:show="new"
xlink:role="http://docbook.org/roles/xlink/role/olink"
xlink:href="integrators-guide#security-management-service"><citetitle>
Accessing the Security Management Service</citetitle></link>.
</para>
</section>
<section xml:id="configure-openam-sample-prov">
<title>Configure Provisioning for the OpenAM Sample</title>
<para>
This section describes how you can customize the
edits parallel those for <link xlink:show="new"
xlink:role="http://docbook.org/roles/xlink/role/olink"
xlink:href="install-guide#more-sample2c"><citetitle>Sample
2c - Synchronizing LDAP Group Membership</citetitle></link>.
</para>
<para>
Open the noted provisioner file, which you can find in the
initial version of this file, you should see something similar to the
following code:
</para>
<programlisting language="javascript">{
"name" : "ldap",
"configurationProperties" : {
"host" : "localhost",
"port" : 1389,
"ssl" : false,
"principal" : "cn=Directory Manager",
"credentials" : "password",
"baseContexts" : [
"dc=example,dc=com"
],
"baseContextsToSynchronize" : [
"dc=example,dc=com"
],</programlisting>
<para>
This snippet already matches the noted base context of
<literal>"dc=example,dc=com"</literal> with a principal of
<literal>"cn=Directory Manager"</literal>.
</para>
<para>
You will want to change the <literal>"localhost"</literal> entry to the
URL where OpenDJ is installed. In this case, that URL is
set up communications over a regular or secure LDAP port, you might
change the <literal>"port"</literal> number to 389 or 636. The following
excerpt illustrates the change to a secure connector configuration:
</para>
<programlisting language="javascript">{
"name" : "ldap",
"configurationProperties" : {
"host" : "openidm.example.com",
"port" : 636,
"ssl" : true,
"principal" : "cn=Directory Manager",
"credentials" : "password",
"baseContexts" : [
"dc=example,dc=com"
],
"baseContextsToSynchronize" : [
"dc=example,dc=com"
],</programlisting>
<para>
Just remember, if you want to set up secure communications with OpenDJ,
you should configure OpenDJ with that in mind. If you have a self-signed
certificate for OpenDJ, you will also want to import that into the
OpenIDM truststore, as discussed in the following section of the
Integrator's Guide: <link xlink:show="new"
xlink:role="http://docbook.org/roles/xlink/role/olink"
xlink:href="integrators-guide#security-management-service"><citetitle>
Accessing the Security Management Service</citetitle></link>.
</para>
</section>
</section>
<section xml:id="install-sample-openam">
<title>Install the Sample</title>
<para>
If you have not already done so, make sure OpenDJ is running on its
</para>
<para>
Finish preparing OpenIDM, with the procedure described in
<xref linkend="preparing-openidm"/>, then start OpenIDM with the
configuration for sample openam.
</para>
<para>
If you have not already done so, make sure OpenAM is also running on its
</para>
</section>
<section xml:id="run-sample-openam">
<title>Running the Sample</title>
<para>
With everything configured, now run reconciliation on the
database:
</para>
<screen>$ curl \
--cacert self-signed.crt \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Content-Type: application/json" \
--request POST \
"https://localhost:8443/openidm/recon?_action=recon&mapping=systemLdapAccounts_managedUser"</screen>
<para>
Successful reconciliation returns a reconciliation run ID.
</para>
</section>
<section xml:id="review-sample-openam">
<title>Make Sure the Sample Works as Intended</title>
<para>
You should still be able to access the OpenIDM UI
in the "normal" way. In this case, you would point a browser to
</para>
<para>
The difference is how OpenIDM uses a proxy service to authenticate with
OpenAM's REST-based authentication service. This sample implements the
directory.
</para>
<para>
The first time you log into the OpenIDM UI, you should see a login prompt
configured with OpenAM. The default version of this prompt appears quite
similar to the OpenIDM prompt. When you login through OpenAM, successfully,
you will receive a valid SSO token.
</para>
<para>
The next time you access OpenIDM, with the SSO token stored in your browser,
you will be logged in automatically, with all the roles configured for your
user account. This works only if your session is still active in OpenAM.
For more information, see the OpenAM Administration Guide section on
<link xlink:show="new"
xlink:href="http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/admin-guide/#session-mgmt">
<citetitle>Session Management</citetitle></link>.
</para>
<note>
<para>You can review the contents of the SSO token by pointing a browser to
endpoint. In this case, that URL would be
</note>
</section>
<section xml:id="sample-openam-going-further">
<title>Additional Options for the OpenAM Sample</title>
<para>
You can extend the OpenAM sample in one of three ways:
</para>
<itemizedlist>
<listitem>
<para><literal>Disable INTERNAL_USER by enabling LiveSync</literal></para>
<para>
enable scheduled reconciliation and LiveSync. To do so, edit the following
<literal>"enabled" : true</literal> in each of these files.
</para>
<para>
This ensures that any change to the OpenDJ user store is automatically
see <xref linkend="more-sample6"/>.
</para>
<para>
Execute the reconciliation command described earlier in the description
for this sample.
</para>
<para>
Once scheduled reconciliation and LiveSync are configured, you can then
disable the <literal>INTERNAL_USER</literal> under
<literal>authModules</literal> in the relevant
section of the file and set <literal>"enabled" : false</literal>. Once
complete, the only users with access to OpenIDM are users with a valid
SSO authentication token in their browsers.
</para>
</listitem>
<!-- possible additional options; can incorporate with more detail
<listitem>
<para>
<literal>Set up workflows to request access to applications</literal>
</para>
<para>
You can configure a workflow to allow users to request access to
additional applications. Upon approval, OpenIDM can update user accounts
with the permissions used by OpenAM to control access to that application.
For more information on workflows, see the Integrator's Guide section to
<link xlink:role="http://docbook.org/roles/xlink/role/olink"
xlink:href="integrators-guide#chap-workflow" xlink:show="new">
<citetitle>Integrating Business Processes and Workflows</citetitle>.
</link>
</para>
</listitem>
<listitem>
<para><literal>Single Sign-On Dashboard</literal></para>
<para>
You could extend workflow concepts to give users a choice of
applications, based on their SSO token. Once configured, you could set up
a "Single Sign-On" application dashboard for your users.
</para>
</listitem> also:
Integrated Services For Custom Applications
Based on the presence of a shared SSO token, any application secured by OpenAM
could reliably invoke OpenIDM REST services in an integrated and transparent
way. For example, an intranet portal could make AJAX requests to OpenIDM to
start a workflow process or execute a query. The fact that the request was
being made to OpenIDM would be hidden from the user - the SSO token that they
used to access the intranet would also be used by OpenIDM, and everything
would just work seamlessly.
-->
</itemizedlist>
</section>
</section>
</chapter>