Generic LDAP Connector

The generic LDAP connector is based on JNDI, and can be used to connect to any LDAPv3-compliant directory server, such as OpenDJ, Active Directory, SunDS, Oracle Directory Server Enterprise Edition, IBM Security Directory Server, and OpenLDAP.

OpenICF provides a legacy Active Directory (AD) .NET connector. Note, however, that the AD Connector will be deprecated in a future OpenICF release, and, ultimately, support for its use with OpenIDM will be discontinued. For simple Active Directory (and Active Directory LDS) deployments, the generic LDAP Connector works better than the Active Directory connector, in most circumstances. Using the generic LDAP connector avoids the need to install a remote connector server in the overall deployment. In addition, the generic LDAP connector has significant performance advantages over the Active Directory connector. For more complex Active Directory deployments, use the PowerShell Connector Toolkit, as described in "PowerShell Connector Toolkit".

Setting Up the Generic LDAP Connector

OpenIDM 6.2 bundles version 1.4.1.2 of the LDAP connector. Three sample LDAP connector configurations are provided in the path/to/openidm/samples/provisioners/ directory:

  • provisioner.openicf-opendjldap.json provides a sample LDAP connector configuration for an OpenDJ directory server.

  • provisioner.openicf-adldap.json provides a sample LDAP connector configuration for an Active Directory server.

  • provisioner.openicf-adldsldap.json provides a sample LDAP connector configuration for an Active Directory Lightweight Directory Services (AD LDS) server.

You should be able to adapt one of these sample configurations for any LDAPv3-compliant server.

The connectorRef configuration property provides information about the LDAP connector bundle, and is the same in all three sample LDAP connector configurations:

{
   "connectorRef": {
     "connectorHostRef": "#LOCAL",
     "connectorName": "org.identityconnectors.ldap.LdapConnector",
     "bundleName": "org.openidentityplatform.openicf.connectors.ldap-connector",
     "bundleVersion": "[1.4.0.0,2)"
   }
 }

The connectorHostRef property is optional, if you use the connector .jar provided in openidm/connectors, and you use a local connector server.

The following excerpt shows the configuration properties in the sample LDAP connector for OpenDJ. These properties are described in detail later in this section. For additional information on the properties that affect synchronization, see "Controlling What the LDAP Connector Synchronizes". For a complete list of the configuration properties for the LDAP connector, see "LDAP Connector Configuration":

"configurationProperties" : {
    "host" : "localhost",
    "port" : 1389,
    "ssl" : false,
    "startTLS" : false,
    "principal" : "cn=Directory Manager",
    "credentials" : "password",
    "baseContexts" : [
        "dc=example,dc=com"
    ],
    "baseContextsToSynchronize" : [
        "dc=example,dc=com"
    ],
    "accountSearchFilter" : null,
    "accountSynchronizationFilter" : null,
    "groupSearchFilter" : null,
    "groupSynchronizationFilter" : null,
    "passwordAttributeToSynchronize" : null,
    "synchronizePasswords" : false,
    "removeLogEntryObjectClassFromFilter" : true,
    "modifiersNamesToFilterOut" : [ ],
    "passwordDecryptionKey" : null,
    "changeLogBlockSize" : 100,
    "attributesToSynchronize" : [ ],
    "changeNumberAttribute" : "changeNumber",
    "passwordDecryptionInitializationVector" : null,
    "filterWithOrInsteadOfAnd" : false,
    "objectClassesToSynchronize" : [
        "inetOrgPerson"
    ],
    "vlvSortAttribute" : "uid",
    "passwordAttribute" : "userPassword",
    "useBlocks" : false,
    "maintainPosixGroupMembership" : false,
    "failover" : [ ],
    "readSchema" : true,
    "accountObjectClasses" : [
        "top",
        "person",
        "organizationalPerson",
        "inetOrgPerson"
    ],
    "accountUserNameAttributes" : [
        "uid"
    ],
    "groupMemberAttribute" : "uniqueMember",
    "passwordHashAlgorithm" : null,
    "usePagedResultControl" : true,
    "blockSize" : 100,
    "uidAttribute" : "dn",
    "maintainLdapGroupMembership" : false,
    "respectResourcePasswordPolicyChangeAfterReset" : false
},
host

The host name or IP address of the server on which the LDAP instance is running.

port

The port on which the LDAP server listens for LDAP requests. The sample configuration specifies a default port of 1389.

ssl

If true, the specified port listens for LDAPS connections.

If you use the LDAP connector over SSL, set the ssl property to true, and the port to 636 in the connector configuration file. You must also specify the path to a truststore in your project’s conf/system.properties file. A truststore is provided by default at openidm/security/truststore. Add the following line to the system.properties file, substituting the path to your own truststore if you do not want to use the default:

# Set the truststore
javax.net.ssl.trustStore=/path/to/openidm/security/truststore
startTLS

Specifies whether to use the startTLS operation to initiate a TLS/SSL session. To use startTLS, set "startTLS":true, and "ssl":false. Your connection should use the insecure LDAP port (typically 389 or 1389 for an OpenDJ server).

principal

The bind DN that is used to connect to the LDAP server.

credentials

The password of the principal that is used to connect to the LDAP server.

baseContexts

One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member. During reconciliation operations, OpenIDM searches through the base contexts listed in this property for changes. (See also "Controlling What the LDAP Connector Synchronizes").

baseContextsToSynchronize

One or more starting points in the LDAP tree that will be used to determine if a change should be synchronized. During LiveSync operations, OpenIDM searches through the base contexts listed in this property for changes. If no value is specified here, the values in listed in the baseContexts property are used. (See also "Controlling What the LDAP Connector Synchronizes").

accountSynchronizationFilter

Used during synchronization actions to filter out LDAP accounts. (See also "Controlling What the LDAP Connector Synchronizes").

accountObjectClasses

This property lists all the object classes that represent an account. If this property has multiple values, an OR filter is used to determine the affected entries. For example, if the value of this property is ["organizationalPerson", "inetOrgPerson"], any entry with the object class organizationalPerson OR the object class inetOrgPerson is considered as an account entry. The value of this property must not include the top object class.

accountSearchFilter

Search filter that user accounts must match. (See also "Controlling What the LDAP Connector Synchronizes").

accountUserNameAttributes

Attributes holding the account’s user name. Used during authentication to find the LDAP entry matching the user name.

attributesToSynchronize

List of attributes used during object synchronization. OpenIDM ignores change log updates that do not include any of the specified attributes. If empty, OpenIDM considers all changes. (See also "Controlling What the LDAP Connector Synchronizes").

blockSize

Block size for simple paged results and VLV index searches, reflecting the maximum number of entries retrieved at any one time.

changeLogBlockSize

Block size used when fetching change log entries.

changeNumberAttribute

Change log attribute containing the last change number.

failover

LDAP URLs specifying alternative LDAP servers to connect to if OpenIDM cannot connect to the primary LDAP server specified in the host and port properties.

filterWithOrInsteadOfAnd

In most cases, the filter to fetch change log entries is AND-based. If this property is set, the filter ORs the required change numbers instead.

groupMemberAttribute

LDAP attribute holding members for non-POSIX static groups.

groupSearchFilter

Search filter that group entries must match.

maintainLdapGroupMembership

If true, OpenIDM modifies group membership when entries are renamed or deleted.

In the sample LDAP connector configuration file provided with OpenIDM, this property is set to false. This means that LDAP group membership is not modified when entries are renamed or deleted in OpenIDM. To ensure that entries are removed from LDAP groups when the entries are deleted, set this property to true or enable referential integrity on the LDAP server. For information about configuring referential integrity in OpenDJ, see Configuring Referential Integrity in the OpenDJ Administration Guide.

maintainPosixGroupMembership

If true, OpenIDM modifies POSIX group membership when entries are renamed or deleted.

modifiersNamesToFilterOut

Use this property to avoid loops caused by changes made to managed user objects being synchronized. For more information, see "Controlling What the LDAP Connector Synchronizes".

objectClassesToSynchronize

OpenIDM synchronizes only entries that have these object classes. See also "Controlling What the LDAP Connector Synchronizes".

passwordAttribute

Attribute to which OpenIDM writes the predefined PASSWORD attribute.

passwordAttributeToSynchronize

OpenIDM synchronizes password values on this attribute.

passwordDecryptionInitializationVector

This is a legacy attribute, and its value should remain set to null. To configure password synchronization between an LDAP server and OpenIDM, use one of the password synchronization plugins, described in "Synchronizing Passwords Between OpenIDM and an LDAP Server" in the Integrator’s Guide.

passwordDecryptionKey

This is a legacy attribute, and its value should remain set to null. To configure password synchronization between an LDAP server and OpenIDM, use one of the password synchronization plugins, described in "Synchronizing Passwords Between OpenIDM and an LDAP Server" in the Integrator’s Guide.

passwordHashAlgorithm

Hash password values with the specified algorithm, if the LDAP server stores them in clear text.

The hash algorithm can be one of the following:

  • NONE - Clear text

  • WIN-AD - Used for password changes to Active Directory

  • SHA - Secure Hash Algorithm

  • SHA-1 - A 160-bit hash algorithm that resembles the MD5 algorithm

  • SSHA - Salted SHA

  • MD5 - A 128-bit message-digest algorithm

  • SMD5 - Salted MD5

readSchema

If true, read the schema from the LDAP server.

This property is used only during the connector setup, to generate the object types.

If this property is false, the LDAP connector provides a basic default schema that can manage LDAP users and groups. The default schema maps inetOrgPerson to the OpenICF ACCOUNT property, and groupOfUniqueNames to the OpenICF GROUP property. The following LDAP object classes are also included in the default schema:

  • organization

  • organizationalUnit

  • person

  • organizationalPerson

  • account

  • groupOfNames

removeLogEntryObjectClassFromFilter

If true, the filter to fetch change log entries does not contain the changeLogEntry object class, and OpenIDM expects no entries with other object types in the change log. The default setting is true.

respectResourcePasswordPolicyChangeAfterReset

If true, bind with the Password Expired and Password Policy controls, and throw PasswordExpiredException and other exceptions appropriately.

synchronizePasswords

This is a legacy attribute, and its value should remain set to false. To configure password synchronization between an LDAP server and OpenIDM, use one of the password synchronization plugins, described in "Synchronizing Passwords Between OpenIDM and an LDAP Server" in the Integrator’s Guide.

uidAttribute

Specifies the LDAP attribute that should be used as the immutable ID (UID) for the entry. For an OpenDJ resource, you should use the entryUUID. You can use the DN as the UID attribute but note that this is not immutable.

useBlocks

If useBlocks is false, no pagination is used. If useBlocks is true, the connector uses block-based LDAP controls, either the simple paged results control, or the virtual list view control, depending on the setting of the usePagedResultControl property.

usePagedResultControl

Taken into account only if useBlocks is true. If usePagedResultControl is false, the connector uses the virtual list view (VLV) control, if it is available. If usePagedResultControl is true, the connector uses the simple paged results control for search operations.

useTimestampsForSync

If true, use timestamps for LiveSync operations, instead of the change log.

By default, the LDAP connector has a change log strategy for LDAP servers that support a change log (such as OpenDJ and Oracle Directory Server Enterprise Edition). If the LDAP server does not support a change log, or if the change log is disabled, LiveSync for create and modify operations can still occur, based on the timestamps of modifications.

vlvSortAttribute

Attribute used as the sort key for virtual list view.

Controlling What the LDAP Connector Synchronizes

To control the set of LDAP entries that are affected by reconciliation and automatic synchronization operations, set the following properties in the provisioner configuration. Automatic synchronization operations includes LiveSync (synchronization of changes from the LDAP server to OpenIDM) and implicit sync (synchronization from the OpenIDM repository to the LDAP server).

baseContexts

The starting points in the LDAP tree that are used when searching the directory tree, for example, dc=example,dc=com. These base contexts must include the set of users and the set of groups that must be searched during reconciliation operations.

baseContextsToSynchronize

The starting points in the LDAP tree that are used to determine if a change should be synchronized. This property is used only for automatic synchronization operations. Only entries that fall under these base contexts are considered during synchronization operations.

accountSearchFilter

Only user accounts that match this filter are searched, and therefore affected by reconciliation and synchronization operations. If you do not set this property, all accounts within the base contexts specified previously are searched.

accountSynchronizationFilter

This property is used during reconciliation and automatic synchronization operations, and filters out any LDAP accounts that you specifically want to exclude from these operations.

objectClassesToSynchronize

During automatic synchronization operations, only the object classes listed here are considered for changes. OpenIDM ignores change log updates (or changes to managed objects) which do not have any of the object classes listed here. If this property is not set, OpenIDM considers changes to all attributes specified in the mapping.

attributesToSynchronize

During automatic synchronization operations, only the attributes listed here are considered for changes. Objects that include these attributes are synchronized. Objects that do not include these attributes are ignored. If this property is not set, OpenIDM considers changes to all attributes specified in the mapping. Automatic synchronization includes LiveSync and implicit synchronization operations. For more information, see "Types of Synchronization" in the Integrator’s Guide

This attribute works only with LDAP servers that log changes in a change log, not with servers (such as Active Directory) that use other mechanisms to track changes.

modifiersNamesToFilterOut

This property enables you to define a list of DNs. During synchronization operations, the connector ignores changes made by these DNs.

When a managed user object is updated, and that change is synchronized to the LDAP server, the change made on the LDAP server is recorded in the change log. A LiveSync operation picks up the change, and attempts to replay the change on the managed user object, effectively resulting in a loop of updates.

To avoid this situation, you can specify a unique user in your LDAP directory, that will be used only for the LDAP connector. The unique user must be something other than cn=directory manager, for example cn=openidmuser. You can then include that user DN as the value of modifiersNamesToFilterOut. When a change is made through the LDAP connector, and that change is recorded in the change log, the modifier’s name (cn=openidmuser) is flagged and OpenIDM does not attempt to replay the change back to the managed user repository. So you are effectively indicating that OpenIDM should not synchronized changes back to managed user that originated from managed user, thus preventing the update loop.

This attribute works only with LDAP servers that log changes in a change log, not with servers (such as Active Directory) that use other mechanisms to track changes.

Using the Generic LDAP Connector With Active Directory

The LDAP connector provides new functionality for managing Active Directory users and groups. Among other changes, the new connector can handle the following operational attributes to manage Active Directory accounts:

  • ENABLE - uses the userAccountControl attribute to get or set the account status of an object.

    The LDAP connector reads the userAccountControl to determine if an account is enabled or disabled. The connector modifies the value of the userAccountControl attribute if OpenIDM changes the value of ENABLE.

  • ACCOUNT_EXPIRES - gets or sets the accountExpires attribute of an Active Directory object.

  • LOCK_OUT - uses the msDS-User-Account-Control-Computed system attribute to check if a user account has been locked.

    If OpenIDM sets the LOCK_OUT to FALSE, the LDAP connector sets the Active Directory lockoutTime to 0 to unlock the account.

    If OpenIDM sets the LOCK_OUT to TRUE, the LDAP connector ignores the change and logs a message.

  • PASSWORD_EXPIRED - uses the msDS-User-Account-Control-Computed system attribute to check if a user password has expired.

    To force password expiration (to force a user to change their password when they next log in), pwdLastSet must be set to 0. The LDAP connector sets pwdLastSet to 0, if OpenIDM sets PASSWORD_EXPIRED to TRUE.

    To remove password expiration, pwdLastSet must be set to 0 and then -1. This sets the value of pwdLastSet to the current time. The LDAP connector sets pwdLastSet to -1 if OpenIDM sets PASSWORD_EXPIRED to FALSE.

You must update your provisioner configuration to be able to use these new operational attributes. You can use this sample provisioner configuration as a guide.

Managing Active Directory Users With the LDAP Connector

If you create or update users in Active Directory, and those user entries include passwords, you must use the LDAP connector over SSL. You cannot create or update an Active Directory user password in clear text. To use the connector over SSL, set "ssl" : true in the provisioner configuration and set the path to your truststore in your project’s conf/system.properties file. For example, add the following line to that file:

# Set the truststore
javax.net.ssl.trustStore=/path/to/openidm/security/truststore

The following command adds an Active Directory user. The output shows the operational attributes described in the previous section:

$ curl \
 --header "Content-Type: application/json" \
 --header "X-OpenIDM-Username: openidm-admin" \
 --header "X-OpenIDM-Password: openidm-admin" \
 --request POST \
 --data '{
 "dn": "CN=Brian Smith,CN=Users,DC=example,DC=com",
 "cn": "Brian Smith",
 "sAMAccountName": "bsmith",
 "userPrincipalName": "bsmith@example.com",
 "userAccountControl": "512",
 "givenName": "Brian",
 "mail": "bsmith@example.com",
 "__PASSWORD__": "Passw0rd"
 }' \
 http://localhost:8080/openidm/system/ad/account?_action=create
{
  "_id": "<GUID=cb2f8cbc032f474c94c896e69db2feb3>",
  "mobile": null,
  "postalCode": null,
  "st": null,
  "employeeType": null,
  "objectGUID": "<GUID=cb2f8cbc032f474c94c896e69db2feb3>",
  "cn": "Brian Smith",
  "department": null,
  "l": null,
  "description": null,
  "info": null,
  "manager": null,
  "sAMAccountName": "bsmith",
  "sn": null,
  "whenChanged": "20151217131254.0Z",
  "userPrincipalName": "bsmith@example.com",
  "userAccountControl": "512",
  "__ENABLE__": true,
  "displayName": null,
  "givenName": "Brian",
  "middleName": null,
  "facsimileTelephoneNumber": null,
  "lastLogon": "0",
  "countryCode": "0",
  "employeeID": null,
  "co": null,
  "physicalDeliveryOfficeName": null,
  "pwdLastSet": "2015-12-17T13:12:54Z",
  "streetAddress": null,
  "homePhone": null,
  "__PASSWORD_NOTREQD__": false,
  "telephoneNumber": null,
  "dn": "CN=Brian Smith,CN=Users,DC=example,DC=com",
  "title": null,
  "mail": "bsmith@example.com",
  "postOfficeBox": null,
  "__SMARTCARD_REQUIRED__": false,
  "uSNChanged": "86144",
  "__PASSWORD_EXPIRED__": false,
  "initials": null,
  "__LOCK_OUT__": false,
  "company": null,
  "employeeNumber": null,
  "accountExpires": "0",
  "c": null,
  "whenCreated": "20151217131254.0Z",
  "uSNCreated": "86142",
  "division": null,
  "groups": [],
  "__DONT_EXPIRE_PASSWORD__": false,
  "otherHomePhone": []
}

Note that the command sets the userAccountControl to 512, which is an enabled account. The value of the userAccountControl determines the account policy. The following list describes the common values for the userAccountControl.

512

Enabled account.

514

Disabled account.

544

Enabled account, password not required.

546

Disabled account, password not required.

66048

Enabled account, password does not expire.

66050

Disabled account, password does not expire.

66080

Enabled account, password does not expire and is not required.

66082

Disabled account, password does not expire and is not required.

262656

Enabled account, smartcard required.

262658

Disabled account, smartcard required.

262688

Enabled account, smartcard required, password not required.

262690

Disabled account, smartcard required, password not required.

328192

Enabled account, smartcard required, password does not expire.

328192

Enabled account, smartcard required, password does not expire.

328194

Disabled account, smartcard required, password does not expire.

328224

Enabled account, smartcard required, password does not expire and is not required.

328226

Disabled account, smartcard required, password does not expire and is not required.

Managing Active Directory Groups With the LDAP Connector

The following command creates a basic Active Directory group with the LDAP connector:

$ curl \
 --header "Content-Type: application/json" \
 --header "X-OpenIDM-Username: openidm-admin" \
 --header "X-OpenIDM-Password: openidm-admin" \
 --request POST \
 --data '{
 "dn": "CN=Employees,DC=example,DC=com"
 }' \
 http://localhost:8080/openidm/system/ad/group?_action=create
{
  "_id": "<GUID=240da4e959d81547ad8629f5b2b5114d>"
}

The LDAP connector exposes two special attributes to handle Active Directory group scope and type: GROUP_SCOPE and GROUP_TYPE.

The GROUP_SCOPE attribute is defined in the provisioner configuration as follows:

...
    "__GROUP_SCOPE__" : {
        "type" : "string",
        "nativeName" : "__GROUP_SCOPE__",
        "nativeType" : "string"
    },

The value of the GROUP_SCOPE attribute can be global, domain, or universal. If no group scope is set when the group is created, the scope is global by default. For more information about the different group scopes, see the corresponding Microsoft documentation.

The GROUP_TYPE attribute is defined in the provisioner configuration as follows:

...
"__GROUP_TYPE__" : {
 "type" : "string",
 "nativeName" : "__GROUP_TYPE__",
 "nativeType" : "string"
 },

The value of the GROUP_TYPE attribute can be security or distribution. If no group type is set when the group is created, the type is security by default. For more information about the different group types, see the corresponding Microsoft documentation.

The following example creates a new distribution group, with universal scope:

$ curl \
 --header "Content-Type: application/json" \
 --header "X-OpenIDM-Username: openidm-admin" \
 --header "X-OpenIDM-Password: openidm-admin" \
 --request POST \
 --data '{
 "dn": "CN=NewGroup,DC=example,DC=com",
 "__GROUP_SCOPE__": "universal",
 "__GROUP_TYPE__": "distribution"
 }' \
 http://localhost:8080/openidm/system/ad/group?_action=create
{
  "_id": "<GUID=f189df8a276f91478ad5055b1580cbcb>"
}

Handling Active Directory Dates

Most dates in Active Directory are represented as the number of 100-nanosecond intervals since January 1, 1601 (UTC). For example:

pwdLastSet: 130698687542272930

OpenIDM generally represents dates as an ISO 8601-compliant string with yyyy-MM-dd’T’HH:mm:ssZ format. For example:

2015-03-02T20:17:48Z

The generic LDAP connector therefore converts any dates from Active Directory to ISO 8601 format, for fields such as pwdLastSet, accountExpires, lockoutTime, and lastLogon.

OpenICF Interfaces Implemented by the LDAP Connector

The LDAP Connector implements the following OpenICF interfaces.

Authenticate

Provides simple authentication with two parameters, presumed to be a user name and password.

Create

Creates an object and its uid.

Delete

Deletes an object, referenced by its uid.

Resolve Username

Resolves an object by its username and returns the uid of the object.

Schema

Describes the object types, operations, and options that the connector supports.

Script on Connector

Enables an application to run a script in the context of the connector. Any script that runs on the connector has the following characteristics:

  • The script runs in the same execution environment as the connector and has access to all the classes to which the connector has access.

  • The script has access to a connector variable that is equivalent to an initialized instance of the connector. At a minimum, the script can access the connector configuration.

  • The script has access to any script-arguments passed in by the application.

Search

Searches the target resource for all objects that match the specified object class and filter.

Sync

Polls the target resource for synchronization events, that is, native changes to objects on the target resource.

Test

Tests the connector configuration. Testing a configuration checks all elements of the environment that are referred to by the configuration are available. For example, the connector might make a physical connection to a host that is specified in the configuration to verify that it exists and that the credentials that are specified in the configuration are valid.

This operation might need to connect to a resource, and, as such, might take some time. Do not invoke this operation too often, such as before every provisioning operation. The test operation is not intended to check that the connector is alive (that is, that its physical connection to the resource has not timed out).

You can invoke the test operation before a connector configuration has been validated.

Update

Updates (modifies or replaces) objects on a target resource.

LDAP Connector Configuration

The LDAP Connector has the following configurable properties.

Configuration Properties

Property

Type

Default

Encrypted

Required