chap-passwords.xml revision f1613c6159d707bbb749c4e3d2c4544106662c7c
<?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-passwords'
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>Managing Passwords</title>
<indexterm>
<primary>Passwords</primary>
</indexterm>
<para>OpenIDM provides password management features that help you enforce
password policies, limit the number of passwords users must remember, and
let users reset and change their passwords.</para>
<section xml:id="enforce-password-policy">
<title>Enforcing Password Policy</title>
<para>A password policy is a set of rules defining what sequence of
characters constitutes an acceptable password. Acceptable passwords generally
are too complex for users or automated programs to generate or guess.</para>
<para>Password policies set requirements for password length, character sets
that passwords must contain, dictionary words and other values that passwords
must not contain. Password policies also require that users not reuse old
passwords, and that users change their passwords on a regular basis.</para>
<indexterm>
<primary>Objects</primary>
<secondary>Managed objects</secondary>
<tertiary>Passwords</tertiary>
</indexterm>
<para>OpenIDM can enforce password policy rules by applying validation rules
to attributes of managed user objects. Suppose you want to rule out use of
the following user passwords.</para>
<itemizedlist>
<listitem><para><literal>password</literal></para></listitem>
<listitem><para><literal>123456</literal></para></listitem>
<listitem><para><literal>12345678</literal></para></listitem>
<listitem><para><literal>qwerty</literal></para></listitem>
<listitem><para><literal>abc123</literal></para></listitem>
</itemizedlist>
<para>You could include the following configuration in
<programlisting language="javascript">
{
"objects" : [
{
"name" : "user",
"properties" : [
{
"name" : "password",
"encryption" : {
"key" : "openidm-sym-default"
}
}
],
"onValidate" : {
"type" : "text/javascript",
"file" : "script/password-validator.js"
}
}
]
}</programlisting>
<para>The corresponding script,
<literal>true</literal> if the password is valid. For example, the following
script checks that the password is not one of those listed above.</para>
<programlisting language="javascript">
const dictionary = ['password','123456','12345678', 'qwerty', 'abc123'];
function isValidPassword() {
var cleartextObject = openidm.decrypt(object);
for (var i = 0; i < dictionary.length; i++) {
if (cleartextObject.password == dictionary[i]) {
throw "Password Policy Violation Exception";
};
};
};
isValidPassword();</programlisting>
<para>To try this script with the default example, update
sample user's password in
something invalid such as <literal>123456</literal>, and add a mapping for
<programlisting language="javascript">
"properties" : [
{
"source" : "description",
"target" : "description"
},
{
"source" : "firstname",
"target" : "givenName"
},
{
"source" : "email",
"target" : "email"
},
{
"source" : "lastname",
"target" : "familyName"
},
{
"source" : "name",
"target" : "userName"
},
<emphasis role="strong">{
"source" : "password",
"target" : "password"
},</emphasis>
{
"source" : "name",
"target" : "_id"
}
],
</programlisting>
<para>In addition remove <literal>"flags" :
["NOT_READABLE","NOT_RETURNED_BY_DEFAULT"]</literal> from the password
file.</para>
<para>The script called for <literal>onValidate</literal> lets you define
rules to validate a property's value before OpenIDM stores the object.
If the value violates the rules, OpenIDM throws an exception.</para>
<para>The following excerpt from
when trying to reconcile a user having an invalid password.</para>
<programlisting language="none">
Jan 16, 2012 10:21:11 AM
WARNING: Failed to create target object
Password Policy Violation Exception</programlisting>
<variablelist>
<para>The password validation mechanism can apply in many situations.</para>
<varlistentry>
<term>Password change and password reset</term>
<listitem>
<para>Password change involves changing a user or account password
in accordance with password policy. Password reset involves setting a
new user or account password on behalf of a user.</para>
<para>You can configure OpenIDM to control password values as they are
provisioned as shown in the previous examples.</para>
<para>To change the default administrative user password,
<literal>openidm-admin</literal>, see the procedure, <link
xlink:role="http://docbook.org/xlink/role/olink"
xlink:href="integrators-guide#security-replace-default-user-password"
><citetitle>To Replace the Default User & Password</citetitle></link>,
for instructions.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Password recovery</term>
<listitem>
<para>Password recovery involves recovering a password or setting a new
password when the password has been forgotten.</para>
<para>OpenIDM can provide a self-service end user interface for password
changes, password recovery, and password reset.</para>
<!-- TODO: Show how to set up UI for this when the UI is delivered. -->
</listitem>
</varlistentry>
<varlistentry>
<term>Password comparisons with dictionary words</term>
<listitem>
<para>You can add dictionary lookups to prevent use of password values
that match dictionary words.</para>
<!-- TODO: Example -->
</listitem>
</varlistentry>
<varlistentry>
<term>Password history</term>
<listitem>
<para>You can add checks to prevent reuse of previous password
values</para>
<!-- TODO: Example -->
</listitem>
</varlistentry>
<varlistentry>
<term>Password expiration</term>
<listitem>
<para>You can configure OpenIDM to call a workflow that ensures users
are able to change expiring or to reset expired passwords.</para>
<!-- TODO: Example -->
</listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="password-sync">
<title>Password Synchronization</title>
<indexterm>
<primary>Synchronization</primary>
<secondary>Passwords</secondary>
</indexterm>
<para>Password synchronization intercepts user password changes, and ensures
uniform password changes across resources that store the password. Following
password synchronization, the user authenticates using the same password on
each resource. No centralized directory or authentication server is required
for performing authentication. Password synchronization reduces the number of
passwords users need to remember, so they can use fewer, stronger
passwords.</para>
<para>OpenIDM can propagate passwords to the resources storing a user's
password. OpenIDM can intercept and synchronize passwords changed natively
on OpenDJ and Active Directory. See the example in
for a sample password synchronization configuration.</para>
<para>Before using the sample, you must set up OpenDJ and Active Directory,
and adjust the password attributes, set in the sample as
<literal>ldapPassword</literal> for OpenDJ, <literal>adPassword</literal>
for Active Directory, and <literal>password</literal> for the internal
OpenIDM password. Also, either set up password policy enforcement on OpenDJ
or Active Directory rather than OpenIDM, or ensure that all password policies
enforced are identical to prevent password updates on one resource from being
rejected by OpenIDM or by another resource.</para>
<para>Also set up password synchronization plugins for OpenDJ and for Active
Directory. The password synchronization plugins help by intercepting password
changes on the resource before the passwords are stored in encrypted
form. The plugins then send intercepted password values to OpenIDM over an
encrypted channel.</para>
<procedure xml:id="install-opendj-password-sync-plugin">
<title>To Install the OpenDJ Password Synchronization Plugin</title>
<indexterm>
<primary>Synchronization</primary>
<secondary>Passwords</secondary>
<tertiary>With OpenDJ</tertiary>
</indexterm>
<para>Before you start, make sure you configure OpenDJ to communicate over
LDAPS as described in the <link xlink:show="new"
xlink:href='http://opendj.forgerock.org/doc/admin-guide/OpenDJ-Admin-Guide.html#chap-listeners'>OpenDJ documentation</link>.</para>
<para>The following steps install the plugin in OpenDJ directory server
running on the same host as OpenIDM. If you run OpenDJ on a different host
use the fully qualified domain name rather than <literal>localhost</literal>,
and use your certificates rather than the example.</para>
<step>
<para>Import the self-signed OpenIDM certificate into the trust store for
OpenDJ.</para>
$ keytool
-import
-alias openidm-localhost
-keystore truststore
-storepass `cat keystore.pin`
Owner: CN=localhost, O=OpenIDM Self-Signed Certificate
Issuer: CN=localhost, O=OpenIDM Self-Signed Certificate
Serial number: 4e4bc38e
Valid from: Wed Aug 17 15:35:10 CEST 2011 until: Tue Aug 17 15:35:10 CEST 2021
Certificate fingerprints:
MD5: B8:B3:B4:4C:F3:22:89:19:C6:55:98:C5:DF:47:DF:06
SHA1: DB:BB:F1:14:55:A0:53:80:9D:62:E7:39:FB:83:15:DA:60:63:79:D1
Signature algorithm name: SHA1withRSA
Version: 3
Trust this certificate? [no]: yes
Certificate was added to keystore</screen>
</step>
<step>
<para>Download the OpenDJ password synchronization plugin, OpenIDM Agents
- OpenDJ <?eval ${opendjPasswordPluginVersion}?>, from the OpenIDM
xlink:show="new">download page</link>.</para>
</step>
<step>
<para>Unzip the module delivery.</para>
<screen>$ unzip ~/Downloads/opendj-accountchange-handler-<?eval ${opendjPasswordPluginVersion}?>-SNAPSHOT.zip
creating: opendj/
...</screen>
</step>
<step>
<para>Copy files to the directory where OpenDJ is installed.</para>
<screen>$ cd opendj
</step>
<step>
<para>Restart OpenDJ to load the additional schema from the module.</para>
$ /stop-ds --restart</screen>
</step>
<step>
<para>Add the configuration provided to OpenDJ's configuration.</para>
<!-- TODO: Figure out how to do this with dsconfig instead of ldapmodify. -->
<screen>$ /ldapmodify
--port 1389
--hostname `hostname`
--bindDN "cn=Directory Manager"
--bindPassword "password"
--defaultAdd
--filename /config/openidm-pwsync-plugin-config.ldif
Processing ADD request for cn=OpenIDM Notification Handler,
cn=Account Status Notification Handlers,cn=config
ADD operation successful for DN cn=OpenIDM Notification Handler
,cn=Account Status Notification Handlers,cn=config</screen>
</step>
<step>
<para>Restart OpenDJ.</para>
<screen>$ /stop-ds --restart
...
/opendj-accountchange-handler-<?eval ${opendjPasswordPluginVersion}?>.jar' (build <unknown>,
revision <unknown>)
...
Directory Server has sent an alert notification generated by class
The Directory Server has started successfully</screen>
</step>
<step>
<para>Enable the plugin for the appropriate password policy.</para>
<para>The following command enables the plugin for the default password
policy.</para>
<screen>$ /dsconfig
set-password-policy-prop
--port 4444
--hostname `hostname`
--bindDN "cn=Directory Manager"
--bindPassword password
--policy-name "Default Password Policy"
--set account-status-notification-handler:"OpenIDM Notification Handler"
--trustStorePath /config/admin-truststore
--no-prompt</screen>
</step>
</procedure>
<procedure xml:id="install-ad-password-sync-plugin">
<title>To Install the Active Directory Password Synchronization Plugin</title>
<indexterm>
<primary>Synchronization</primary>
<secondary>Passwords</secondary>
<tertiary>With Active Directory</tertiary>
</indexterm>
<para>You install the plugin on Active Directory primary domain controllers
(PDCs) to intercept password changes, and send the password values to
OpenIDM over an encrypted channel. You must have Administrator privileges to
install the plugin. In a clustered Active Directory environment, you must
also install the plugin on all PDCs.</para>
<step>
<para>Download the Active Directory password synchronization plugin,
OpenIDM Agents - AD <?eval ${adPasswordPluginVersion}?>, from the OpenIDM
xlink:show="new">download page</link>.</para>
</step>
<step>
launch the installation wizard.</para>
</step>
<step>
<para>Complete the installation with the help of the following hints.</para>
<variablelist>
<varlistentry>
<!-- Yes, this hint seems unnecessary. But if people need to know what
licensing is used without opening up the installer, they can get
that info right here: -->
<term>CDDL license agreement</term>
<listitem>
<para>You must accept the agreement to proceed with the
installation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>OpenIDM URL</term>
<listitem>
<para>URL where OpenIDM is deployed such as
SSL mutual authentication</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Private Key alias</term>
<listitem>
<para>Alias used for the OpenIDM certificate also stored in the
<literal>openidm-localhost</literal> used for evaluation</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Private Key password</term>
<listitem>
<para>Password to access the PFX keystore file, such as
<literal>changeit</literal> for evaluation. PFX files contain
encrypted private keys, certificates used for authentication and
encryption.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Directory poll interval (seconds)</term>
<listitem>
<para>Number of seconds between calls to check that Active Directory
is available, such as 60</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Query ID parameter</term>
<listitem>
<para>Query identifier configured in OpenIDM the
<literal>for-userName</literal> for evaluation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>OpenIDM user password attribute </term>
<listitem>
to which OpenIDM applies password changes</para>
</listitem>
</varlistentry>
<varlistentry>
<term>OpenIDM user search attribute</term>
<listitem>
<para>The <literal>sAMAccountName</literal> value holder attribute name
in the query definition. For example,
<literal>"SELECT * FROM ${_resource} WHERE userName = '${uid}'"</literal>.
Use <literal>uid</literal> for the evaluation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Select Certificate File</term>
<listitem>
<para>The PKCS 12 format PFX file containing the certificate used to
encrypt communications with OpenIDM. Use
evaluation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Select Output Directory</term>
<listitem>
<para>Select a secure directory where the password changes are queued.
The queue contains the encrypted passwords. Yet, the server has to
prevent access to this folder except access by the <literal>Password
Sync service</literal>. The path name cannot include spaces.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Select Log Directory</term>
<listitem>
<para>The plugin stores logs in the location you select. The path name
cannot include spaces.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Select Destination Location</term>
<listitem>
<para>Setup installs the plugin in the location you select, by default
<filename>C:\Program Files\OpenIDM Password Sync</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
</step>
<step>
<para>After running the installation wizard, restart the computer.</para>
</step>
<step>
<para>If you must change any settings after installation, access settings
using the Registry Editor under HKEY_LOCAL_MACHINE > SOFTWARE >
ForgeRock > OpenIDM > PasswordSync.</para>
</step>
</procedure>
<procedure xml:id="setup-openidm-for-password-sync">
<title>To Set Up OpenIDM to Handle Password Changes</title>
<para>Follow these steps to configure OpenIDM to access password changes
from the directory server.</para>
<step>
<para>Add the directory server certificate to the OpenIDM trust store so
that OpenIDM knows to trust the directory server during mutual
authentication.</para>
<para>The following commands show how to do this with the default OpenDJ
and OpenIDM settings.</para>
$ keytool
-keystore keystore
-storepass `cat keystore.pin`
-export
-alias server-cert
> /tmp/opendj.crt
$ keytool
-import
-alias opendj-server-cert
-file /tmp/opendj.crt
-keystore truststore
-storepass changeit
-trustcacerts
Owner: CN=localhost.localdomain, O=OpenDJ Self-Signed Certificate
Issuer: CN=localhost.localdomain, O=OpenDJ Self-Signed Certificate
Serial number: 4f143976
Valid from: Mon Jan 16 15:51:34 CET 2012 until: Wed Jan 15 15:51:34 CET 2014
Certificate fingerprints:
MD5: 7B:7A:75:FC:5A:F0:65:E5:84:43:6D:10:B9:EA:CC:F0
SHA1: D1:C6:C9:8A:EA:09:FD:1E:48:BB:B2:F5:95:41:50:2C:AB:4D:0F:C9
Signature algorithm name: SHA1withRSA
Version: 3
Trust this certificate? [no]: yes
Certificate was added to keystore</screen>
</step>
<step>
<para>Add the configuration to managed objects to handle password
synchronization.</para>
<para>You can find an example for synchronization with both OpenDJ and
JavaScript lines folded for readability:</para>
<programlisting language="javascript">
{
"objects": [
{
"name": "user",
"properties": [
{
"name": "ldapPassword",
"encryption": {
"key": "openidm-sym-default"
}
},
{
"name": "adPassword",
"encryption": {
"key": "openidm-sym-default"
}
},
{
"name": "password",
"encryption": {
"key": "openidm-sym-default"
}
}
],
"onUpdate": {
"type": "text/javascript",
"source":
"if (newObject.ldapPassword != oldObject.ldapPassword) {
} else if (newObject.adPassword != oldObject.adPassword) {
}"
}
}
]
}</programlisting>
<para>This sample assumes you define the password as
<literal>ldapPassword</literal> for OpenDJ, and
<literal>adPassword</literal> for Active Directory.</para>
</step>
<step>
<para>When you change a password on the directory server and run
reconciliation, you notice the value changes in OpenIDM.</para>
</step>
</procedure>
</section>
</chapter>