LDAP connector

The LDAP connector can be used with any directory which supports the LDAP and LDAPS protocols such as OpenLDAP, Active Directory or eDirectory.

Installing the connector

The steps below describe how to install and start the connector. Depending on whether you are using Kubernetes, Swarm or RPM, the instructions will vary.

RPM File

First, download jar file into /usr/local/openiam/connectors/bin and change owner to OpenIAM user.

wget https://download.openiam.com/release/enterprise/4.2.1.4/connectors/ldap-connector-rabbitmq.jar
chown openiam:openiam /usr/local/openiam/connectors/bin/ldap-connector-rabbitmq.jar

Next, create a new .sh file for starting LDAP connector by running:

nano ldap_start.sh

Content of the file:

#!/bin/bash
. /usr/local/openiam/env.conf
export VAULT_CERTS="$HOME_DIR/vault/certs/"
export JAVA_HOME="$HOME_DIR/jdk"
export JAR_FILE="ldap-connector-rabbitmq"
export JAVA_OPTS="-Xmx256m -Djdk.tls.client.protocols=TLSv1.2"
su openiam -c "$JAVA_HOME/bin/java -Dlogging.level.root=ERROR -Dlogging.level.org.openiam=ERROR -Dconfpath=$HOME_DIR/ -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.trustStore=$HOME_DIR/conf/$JAR_FILE/ -jar $JAVA_OPTS $HOME_DIR/connectors/bin/$JAR_FILE.jar > $HOME_DIR/logs/$JAR_FILE.log&"

Make file executable by running:

chmod +x ldap_start.sh

To start the connector, use the following command:

./ldap_start.sh

Docker Swarm

Kubernetes

Synchronization

OpenIAM provides two pre-configured synchronization options for the LDAP connector:

  1. OpenLDAP User
    • Matches users by User ID.
  2. OpenLDAP Group
    • Matches groups by name and cn.

To access synchronization settings:

  1. Log in to the Web Console.
  2. Navigate to Provisioning > Synchronization.
  3. Search for OpenLDAP User or OpenLDAP Group.

Both synchronization configurations come with example transformation scripts.

Enabling attributes in LDAP connector

To enable attributes in the LDAP connector, start by logging in to the OpenIAM Web Console.

  1. Navigate to Provisioning > Connectors.
  2. Find the LDAP connector and click Edit.
  3. In the left-hand menu, find the Connector Configuration option and click it.

Connector configuration

  1. In the window that opens, select the checkbox(es) based on your requirements. In the example below, the Base DN for Group and Search Base DN for Group checkboxes are enabled.

Checkboxes example

  1. Click Save. Proceed with configuring the Managed System.

Configuring managed system

OpenIAM has a built-in Managed System configuration named OpenLDAP, which can be found by logging in to the Web Console and going to Provisioning > Managed System. It can be used as is, as it is already pre-configured. If you choose to configure the managed system from scratch, you must fill in the fields manually.

LDAP Managed system

To configure attributes for a Managed System, follow the steps below:

  1. Provide all required details and verify that Base DN and Search Base DN are present for both Group and User. If not, add them.

        Example:

  • Base DN for Group: ou=groups,dc=ldap,dc=local
  • Search Base DN for Group: ou=groups,dc=ldap,dc=local
  1. Configure Synchronization for OpenLDAP User and OpenLDAP Group as described above. Verify each configuration in both OpenLDAP User and OpenLDAP Group, and update the necessary details as needed.

  2. The transformation rule to be used is LdapGroupTransformationScript.groovy. This script can be found using the search engine under Administration > Groovy Manager, or see the full script below.

package org.openiam.sync.service.impl
import org.apache.commons.collections4.CollectionUtils
import org.openiam.base.AttributeOperationEnum
import org.openiam.idm.srvc.grp.dto.Group
import org.openiam.idm.srvc.grp.dto.GroupAttribute
import org.openiam.idm.srvc.meta.domain.MetadataTypeGrouping
import org.openiam.idm.srvc.synch.dto.LineObject
import org.openiam.idm.srvc.user.dto.User
import org.openiam.provision.dto.ProvisionUser
import org.openiam.sync.service.impl.service.AbstractGroupTransformScript
class LdapGroupTransformationScript extends AbstractGroupTransformScript {
@Override
int execute(LineObject rowObj, Group group) {
println "** - Group Transformation script called."
try {
group.setPolicyId("4000");
def ldapMdType = getMetadataTypeByNameAndGrouping("LDAP group", MetadataTypeGrouping.GROUP_TYPE);
if (ldapMdType)
group.setMdTypeId(ldapMdType.getId())
else
group.setMdTypeId("GENERAL_GROUP")
populateObject(rowObj, group)
} catch (Exception ex) {
ex.printStackTrace();
println "** - Transformation script error."
return -1;
}
println "** - Transformation script completed." + group
return NO_DELETE
}
private void populateObject(LineObject rowObj, Group group) {
def columnMap = rowObj.columnMap
group.name = columnMap.get("cn")?.value
group.managedSysId = config.getManagedSysId()
group.description = columnMap.get("displayName")?.value
if (group.getDescription() && group.getDescription().length() > 254) {
group.setDescription(group.getDescription().substring(0, 254));
}
group.status = "ACTIVE"
addGroupAttribute(group, "gidNumber", columnMap.get("gidNumber")?.value);
addGroupAttribute(group, "dn", columnMap.get("dn")?.value);
def obj = columnMap.get("objectClass")
if (obj.valueList.contains("posixGroup")) {
println "Objectclass ${obj.valueList}"
def membersAttr = columnMap.get("memberUid")
if (membersAttr) {
def members = membersAttr.valueList
if (members) {
addGroupMembers(group, members)
}
}
} else if (obj.valueList.contains("groupOfNames")) {
println "Objectclass ${obj.valueList}"
def membersAttrs = columnMap.get("member")
if (membersAttrs) {
def members = membersAttrs.valueList
if (members) {
def uids = extractUids(members)
if (uids) {
addGroupMembers(group, uids)
}
}
}
}
}
List<String> extractUids(List<String> valueList) {
return valueList.collect { entry ->
def afterUid = entry.split("uid=")[1]
def uid = afterUid.split(",", 2)[0]
return uid
}
}
private void addGroupMembers(Group g, List<String> users) {
if (!isNewUser && CollectionUtils.isNotEmpty(users)) {
for (String us : users) {
User u = getUserByLogin(us, config.getManagedSysId())
println "found member:" + u?.displayName
if (u != null) {
if (g.getUser(u.getId()) == null) {
try {
Set<String> rights = new HashSet<>()
rights.add("IS_CERTIFIED")
u.addGroup(g, rights, null, null)
userManager.save(new ProvisionUser(u), null)
} catch (Exception e) {
log.warn("Can't attach user to group.")
}
}
}
}
}
}
@Override
void init() {}
}
  1. Review the LDAP schema and update the code as needed. For example, if the objectClass is posixGroup, the member information is returned in the memberUid attribute; otherwise, it is in the member attribute.

  2. Specify the attribute names to retrieve from LDAP (such as member) in the SourceAttributesNames Groovy script.

Connector troubleshooting tips

SSL connection issue

Symptoms:

org.openiam.connector.core.base.exception.ConnectorException: javax.naming.CommunicationException: simple bind failed: xxxxx.xx.xxx.xxx.xxx:636 [Root exception is javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target] Caused by: javax.naming.CommunicationException: simple bind failed: myldap.example.com:636

Solution:

Make sure port is open and reachable, and you can connect via telnet command

telnet myldap.example.com 636

If you are connecting to LDAP via secured port 636 you should import ca_cert issued by domain into java keystore:

keytool -noprompt -import -v -trustcacerts -alias ldap_ca$(pwgen -s 13 1) -file /path/to/ca_cert.crt -keystore /usr/local/openiam/jdk/lib/security/cacerts -keypass changeit -storepass changeit
Note that certificate must be imported into proper JVM that is used to start connector. Afterwards, you need to restart the connector.