chap-sample.xml revision 245d622535c32563b59ef5027b1171167ba9b451
<?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-2012 ForgeRock AS
!
-->
<chapter xml:id='chap-sample'
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 http://docbook.org/xml/5.0/xsd/docbook.xsd'
xmlns:xlink='http://www.w3.org/1999/xlink'
xmlns:xinclude='http://www.w3.org/2001/XInclude'>
<title>First OpenIDM Sample</title>
<indexterm>
<primary>Getting started</primary>
</indexterm>
<indexterm>
<primary>Samples</primary>
<secondary>Sample 1 - XML file</secondary>
</indexterm>
<indexterm>
<primary>Repository database</primary>
<secondary>Evaluation version</secondary>
</indexterm>
<para>This chapter provides an overview of the first sample and how it is
configured. To see a listing and an overview of the rest of the samples
the chapter <link xlink:href="install-guide#chap-samples"
Samples</citetitle></link>.</para>
<section xml:id="before-you-begin-sample">
<title>Before You Begin</title>
<para>Install OpenIDM as described in the chapter on <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>
<para>If you want to query the internal noSQL database, download and unzip
xlink:show="new">OrientDB <?eval ${orientdbVersion}?></link>. You will find
the shell console in the <filename>bin</filename> directory. Start OrientDB
the <command>connect</command> command.</para>
>
></screen>
<variablelist>
<para>When you have connected to the database, you might find the following
commands useful.</para>
<varlistentry>
<term><command>info</command></term>
<listitem><para>Shows classes and records</para></listitem>
</varlistentry>
<varlistentry>
<term><command>select * from managed_user</command></term>
<listitem><para>Shows all users in the OpenIDM repository</para></listitem>
</varlistentry>
<varlistentry>
<term><command>select * from audit_activity</command></term>
<listitem><para>Shows all activity audit records</para>
<para>This table is created when there is some activity.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>select * from audit_recon</command></term>
<listitem><para>Shows all reconciliation audit records</para>
<para>This table is created when you run reconciliation.</para></listitem>
</varlistentry>
</variablelist>
<para>You can also use OrientDB Studio to query the default OrientDB
repository. After you have installed and started OpenIDM, point your browser
</literal> and the default user and password are <literal>admin</literal> and
<literal>admin</literal>. Click Connect to connect to the repository. For
more information about OrientDB Studio, see the
OrientDB Studio documentation</link>.</para>
</section>
<section xml:id="about-the-sample">
<title>About the Sample</title>
<para>OpenIDM connects identity data objects held in external resources
by mapping one object to another. To connect to external resources,
connectors, configured for use with the external resources.</para>
<para>When objects in one external resource change, OpenIDM determines how
the changes affect other objects, and can make the changes as necessary.
This sample demonstrates how OpenIDM does this by using
<firstterm>reconciliation</firstterm> and
<firstterm>synchronization</firstterm>. OpenIDM reconciliation compares
objects in one object set to mapped objects in another object set.
Reconciliation can work in write mode, where OpenIDM writes changes to
affected objects, or in report mode, where OpenIDM reports on what changes
would be written without making the changes. OpenIDM synchronization reflects
changes in objects to any mapped objects, making changes as necessary to
create or remove mapped objects and links to associate them. For a more
thorough explanation of reconciliation and synchronization, see the section on
<link xlink:href="integrators-guide#sync-types"
Synchronization</citetitle></link> in the <citetitle>Integrator's
Guide</citetitle>.</para>
<para>This sample connects to an XML file that holds sample user data. The
XML file is configured as the authoritative source. In this sample, users are
created in the local repository to show you how you can manage local users
through the REST APIs. You can also use OpenIDM without storing managed
objects for users in the local repository, instead reconciling and
synchronizing objects directly through connectors to external
resources.</para>
<para>Furthermore, this sample involves only one external resource. In
practice, you can connect as many resources as needed for your
deployment.</para>
<variablelist xml:id="about-the-sample-configuration">
<title>Sample Configuration Files</title>
<para>You can find configuration files for the sample under the
the samples, keep the following in mind.</para>
<orderedlist>
<listitem>
<para>OpenIDM regularly scans for any scheduler configuration files in the
<filename>conf</filename> directory.</para>
</listitem>
<listitem>
<para>OpenIDM's reconciliation service reads the mappings and actions for
the source and target users from
</listitem>
<listitem>
<para>Reconciliation runs, querying all users in the source, and then
creating, deleting, or modifying users in the local OpenIDM repository
according to the synchronization mappings.</para>
</listitem>
<listitem>
<para>OpenIDM writes all operations to the audit logs in both the internal
directory.</para>
</listitem>
</orderedlist>
<para>The following configuration files play important roles in this
sample.</para>
<varlistentry>
<listitem>
<para>This connector configuration file serves as the XML file resource.
In this sample, the connector instance acts as the authoritative source
for users. In the configuration file you can see that the
<literal>xmlFilePath</literal> is set to
contains two users, in XML format.</para>
<para>For details on the OpenICF connector configuration files see
<link xlink:href="integrators-guide#chap-resource-conf"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Connecting to External Resources</citetitle></link> in
the <citetitle>Integrator's Guide</citetitle>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>samples/sample1/conf/schedule-reconcile_systemXmlAccounts_managedUser.json</filename></term>
<listitem>
<para>The sample schedule configuration file defines a reconciliation
job that, if enabled by setting <literal>"enabled" : true</literal>,
starts a reconciliation each minute for the mapping named
<literal>systemXmlAccounts_managedUser</literal>. The mapping is defined
<programlisting language="javascript">{
"enabled" : false,
"type": "cron",
"schedule": "30 0/1 * * * ?",
"persisted" : true,
"misfirePolicy" : "fireAndProceed",
"invokeService": "org.forgerock.openidm.sync",
"invokeContext": {
"action": "reconcile",
"mapping": "systemXmlfileAccounts_managedUser"
}
}</programlisting>
<para>For information about the schedule configuration see <link
xlink:href="integrators-guide#chap-scheduler-conf"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Scheduling Tasks and Events</citetitle></link> in the
<citetitle>Integrator's Guide</citetitle>.</para>
<para>Apart from the scheduled reconciliation run, you can also start
the reconciliation run through the REST interface. The call to the REST
interface is an HTTP POST such as the following.</para>
<screen width="100">$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request POST
"http://localhost:8080/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"</screen>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>This sample configuration file defines the configuration for
reconciliation and synchronization. The
<literal>systemXmlAccounts_managedUser</literal> is the mapping for the
the synchronization mappings between the XML file connector (source) and
the local repository (target).</para>
<programlisting language="javascript">
{
"mappings": [
{
"name": "systemXmlfileAccounts_managedUser",
"correlationQuery": {
"type": "text/javascript",
"source": "var query = {'_queryId' : 'for-userName',
'uid' : source.name};query;"
},
"properties": [
{
"source": "_id",
"target": "_id"
},
{
"source": "description",
"target": "description"
},
{
"source": "firstname",
"target": "givenName"
},
{
"source": "email",
"target": "email"
},
{
"source": "lastname",
"target": "familyName"
},
{
"source": "name",
"target": "userName"
},
{
"source": "password",
"target": "password"
}
{
"source" : "mobileTelephoneNumber",
"target" : "phoneNumber"
},
{
"source" : "securityQuestion",
"target" : "securityQuestion"
},
{
"source" : "securityAnswer",
"target" : "securityAnswer"
},
{
"source" : "passPhrase",
"target" : "passPhrase"
},
{
"source" : "roles",
"target" : "roles"
}
],
"policies": [
{
"situation": "CONFIRMED",
"action": "UPDATE"
},
{
"situation": "FOUND",
"action": "IGNORE"
},
{
"situation": "ABSENT",
"action": "CREATE"
},
{
"situation": "AMBIGUOUS",
"action": "IGNORE"
},
{
"situation": "MISSING",
"action": "IGNORE"
},
{
"situation": "SOURCE_MISSING",
"action": "IGNORE"
},
{
"situation": "UNQUALIFIED",
"action": "IGNORE"
},
{
"situation": "UNASSIGNED",
"action": "IGNORE"
}
]
}
]
}</programlisting>
<para>Source and target paths that start with <literal>managed</literal>,
local OpenIDM repository. Paths that start with <literal>system</literal>,
objects, in this case the XML file connector.</para>
<para>To filter objects from the resource for a particular target, you can
use the <literal>validTarget</literal> script in the mapping to ensure
that only users who match specified criteria are considered part of the
reconciliation. You can use an <literal>onCreate</literal> script in a
mapping to set default values for a user created in the target resource.
For details on scripting see the <link
xlink:href="integrators-guide#appendix-scripting"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Scripting Reference</citetitle></link> appendix in the
<citetitle>Integrator's Guide</citetitle>.</para>
<para>For more information about synchronization, reconciliation, and
xlink:href="integrators-guide#chap-synchronization"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Configuring Synchronization</citetitle></link> in the
<citetitle>Integrator's Guide</citetitle>.</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="sample-running-reconciliation">
<title>Running Reconciliation</title>
<para>Start OpenIDM with the configuration for sample 1.</para>
</screen>
<para>Reconcile the objects in the resources, either by setting
<literal>"enabled" : true</literal> in the schedule configuration file
and then waiting until the scheduled reconciliation happens, or by using the
REST interface, as follows:</para>
<screen width="100"><?dbfo pgwide="1"?>$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request POST
"http://localhost:8080/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"</screen>
<para>Successful reconciliation returns a reconciliation run ID, similar
to the following:</para>
<screen>{"_id":"2d87c817-3d00-4776-a705-7de2c65937d8"}</screen>
<para>To see what happened, look at the CSV format log file,
</section>
<section xml:id="sample-viewing-users-logs">
<title>Viewing Users and Logs</title>
<para>After reconciliation runs, you can use the REST interface to display
all users in the local repository. Use a REST client to perform an HTTP
GET on the following URL:
with the headers <literal>"X-OpenIDM-Username: openidm-admin"</literal> and
<literal>"X-OpenIDM-Password: openidm-admin"</literal>.
</para>
<para>OpenIDM returns a JSON file. Depending on your browser, it can display
the JSON or download it as a file. Alternatively, you can use the following
command to get the JSON file.</para>
<screen>$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request GET
{
"query-time-ms":1,
"result":[
{
"_id":"joe",
"_rev":"0"
},{
"_id":"bjensen",
"_rev":"0"
},{
"_id":"scarter",
"_rev":"0"
}
],
"conversion-time-ms":0
}
</screen>
<para>If you created user <literal>joe</literal> as described previously in
this guide, you see IDs for three users. The second and third users,
<literal>bjensen</literal> and <literal>scarter</literal>, were created
during the reconcililation. Now try a RESTful GET of user
<literal>bjensen</literal> by appending the user ID to the managed user URL
<screen>$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request GET
{
"_id":"bjensen",
"_rev":"0",
"frequentlyUsedApplications":"",
"passwordAttempts":"0",
"familyName":"Jensen",
"address1":"",
"address2":"",
"givenName":"Barbara",
"securityQuestion":"1",
"country":"",
"city":"",
"siteImage":"1",
"lastPasswordSet":"",
"postalCode":"",
"phoneNumber":"1234567",
"passPhrase":"",
"email":"bjensen@example.com",
"description":"Created By XML1",
"accountStatus":"active",
"roles":"openidm-authorized",
"userApplicationsOrder":"",
"stateProvince":"",
"userName":"bjensen@example.com"
}</screen>
<para>In the OrientDB console, connect to the database, and then query the
users and audit logs. The following shows edited excerpts from a console
session querying OrientDB. To make it easier to view the records, the first
query only requests three specific fields.</para>
> select familyName,email,description from managed_user
---+---------+--------------------+--------------------+--------------------
#| RID |familyName |email |description
---+---------+--------------------+--------------------+--------------------
0| #-2:0|smith |[1] |My first user
1| #-2:1|Jensen |bjensen@example.com |Created By XML1
2| #-2:2|Carter |scarter@example.com |Created By XML1
---+---------+--------------------+--------------------+--------------------
3 item(s) found. Query executed in 0.0040 sec(s).
> select * from audit_activity
---+---------+---------------+-------------------+-------------------------+...
#| RID |rev |status |timestamp |...
---+---------+---------------+-------------------+-------------------------+...
0| #-2:0|0 |SUCCESS |2012-10-26T12:05:50.923Z |...
1| #-2:1|0 |SUCCESS |2012-10-26T12:05:50.966Z |...
2| #-2:2|0 |SUCCESS |2012-10-26T12:05:51.530Z |...
3| #-2:3|0 |SUCCESS |2012-10-26T12:05:51.605Z |...
...
18 item(s) found. Query executed in 0.0090 sec(s).
> select * from audit_recon
---+---------+--------------------+-----------+------------------------+---------...
#| RID |reconId |status |timestamp |message ...
---+---------+--------------------+-----------+------------------------+---------...
0| #22:0|48650107-66ef-48f...|SUCCESS |2012-10-26T12:05:50.701Z|Reconcili...
1| #22:1|48650107-66ef-48f...|SUCCESS |2012-10-26T12:05:52.160Z|null ...
2| #22:2|48650107-66ef-48f...|SUCCESS |2012-10-26T12:05:52.856Z|null ...
3| #22:3|48650107-66ef-48f...|SUCCESS |2012-10-26T12:05:52.861Z|SOURCE_IG...
---+---------+--------------------+-----------+------------------------+---------...
4 item(s) found. Query executed in 0.0070 sec(s).
</screen>
<para>This information is also available in the CSV format audit logs located
</section>
<section xml:id="sample-adding-users-resource">
<title>Adding Users in a Resource</title>
<para>Add a user to the source connector XML data file to see reconciliation
in action. During the next reconciliation, OpenIDM finds the new user in the
source connector, and creates the user in the local repository. To add the
user, copy the following XML into
<programlisting language="xml"><ri:__ACCOUNT__>
<icf:__UID__>tmorris</icf:__UID__>
<icf:__NAME__>tmorris@example.com</icf:__NAME__>
<ri:password>TestPassw0rd#</ri:password>
<ri:firstname>Toni</ri:firstname>
<ri:lastname>Morris</ri:lastname>
<ri:email>tmorris@example.com</ri:email>
<ri:mobileTelephoneNumber>1234567</ri:mobileTelephoneNumber>
<ri:securityQuestion>1</ri:securityQuestion>
<ri:securityAnswer>Some security answer</ri:securityAnswer>
<ri:roles>openidm-authorized</ri:roles>
<icf:__DESCRIPTION__>Created By XML1</icf:__DESCRIPTION__>
</ri:__ACCOUNT__></programlisting>
<para>Run reconciliation again, as described in the section on <link
linkend="sample-running-reconciliation"><citetitle>Running
Reconciliation</citetitle></link>. After reconciliation has run, query the
local repository to see the new user appear in the list of all users under
<screen>$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request GET
{
"query-time-ms":1,
"result":[{
"_id":"joe",
"_rev":"0"
},{
"_id":"bjensen",
"_rev":"0"
},{
"_id":"scarter",
"_rev":"0"
},{
"_id":"tmorris",
"_rev":"0"
}],
"conversion-time-ms":0
}
</screen>
<para>Also look at the reconciliation audit log,
reconciliation. This formatted excerpt from the log covers the two
reconciliation runs done in this sample.</para>
<programlisting language="csv" width="110"><?dbfo pgwide="1"?>
"_id", "action",...,"reconId","situation","sourceObjectId", "targetObjectId","timestamp";
"7e...","CREATE",...,"486...", "ABSENT", "system/xmlfile/account/bjensen","managed/user/bjensen",...;
"1a...","CREATE",...,"486...", "ABSENT", "system/xmlfile/account/scarter","managed/user/scarter",...;
"33...","UPDATE",...,"aa9...", "CONFIRMED","system/xmlfile/account/bjensen","managed/user/bjensen",...;
"1d...","UPDATE",...,"aa9...", "CONFIRMED","system/xmlfile/account/scarter","managed/user/scarter",...;
"0e...","CREATE",...,"aa9...", "ABSENT", "system/xmlfile/account/tmorris","managed/user/tmorris",...;
</programlisting>
<para>The important fields in the audit log are the action, the situation,
the source <literal>sourceObjectId</literal>, and the target
<literal>targetObjectId</literal>. For each object in the source,
reconciliation results in a situation that leads to an action on the
target.</para>
<para>In the first reconciliation run (the abbreviated
<literal>reconID</literal> is shown as <literal>486...</literal>), the source
object does not exist in the target, resulting in an ABSENT situation and an
action to CREATE the object in the target. The object created earlier in the
target does not exist in the source, and so is IGNORED.</para>
<para>In the second reconciliation run (the abbreviated
<literal>reconID</literal> is shown as <literal>aa9...</literal>), after you
added a user to the source XML, OpenIDM performs an UPDATE on the user objects
<literal>bjensen</literal> and <literal>scarter</literal> that already exist
in the target, in this case changing the internal ID. OpenIDM performs a CREATE
on the target for the new user (<literal>tmorris</literal>).</para>
<para>You configure the action that OpenIDM takes based on an object's
For the list of all possible situations and actions, see the <link
xlink:href="integrators-guide#chap-synchronization"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Configuring Synchronization</citetitle></link> chapter in the
<citetitle>Integrator's Guide</citetitle>.</para>
<para>For details on auditing, see the <link
xlink:href="integrators-guide#chap-auditing"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Using Audit Logs</citetitle></link> chapter in the
<citetitle>Integrator's Guide</citetitle>.</para>
</section>
<section xml:id="sample-adding-users-rest">
<title>Adding Users Through REST</title>
<para>You can also add users directly to the local repository through the
REST interface. The following example adds a user named James Berg.</para>
<para>Create <literal>james</literal> (UNIX).</para>
<screen>$ curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request PUT
--data '{
"userName":"jberg",
"familyName":"Berg",
"givenName":"James",
"email":"jberg@example.com",
"phoneNumber":"5556787",
"description":"Created by OpenIDM REST.",
"password":"MyPassw0rd"
}'
{"_id":"jberg","_rev":"0"}</screen>
<para>Create <literal>james</literal> (Windows).</para>
<screen>C:\>curl
--header "X-OpenIDM-Username: openidm-admin"
--header "X-OpenIDM-Password: openidm-admin"
--request PUT
--data "{
\"userName\":\"jberg\",
\"familyName\":\"Berg\",
\"givenName\":\"James\",
\"email\":\"jberg@example.com\",
\"phoneNumber\":\"5556787\",
\"description\":\"Created by OpenIDM REST.\",
\"password\":\"MyPassw0rd\"
}"
{"_id":"jberg","_rev":"0"}</screen>
<para>OpenIDM creates the new user in the repository. If you configure a
mapping to apply changes from the local repository to the XML file connector
as a target, OpenIDM then updates the XML file to add the new user.</para>
</section>
</chapter>