eXo Platform 3.5

## Chapter 80. LDAP Configuration

## Overview

You may decide that you want eXo users to be mapped to an existing directory. eXo provides a flexible implementation of its OrganizationService on top of LDAP. It can be used on any LDAP compliant directory and even Active Directory. This page will guide you how to configure eXo Platform to work with your directory.

## Quickstart

If you just want to have a look at how eXo works with ldap. eXo comes with a predefined ldap configuration. You just need to activate it and eXo will create all it needs to work at startup.

You need to have a working ldap server and a user with write permissions.

- Open exo-tomcat/webapps/portal/WEB-INF/conf/configuration.xml and replace:

    <import>war:/conf/organization/hibernate-configuration.xml</import>

With

    <import>war:/conf/organization/ldap-configuration.xml</import>

- 0pen ldap-configuration.xml and update the providerURL, rootdn and password settings according to your environment

    <field name="providerURL"><string>ldap://127.0.0.1:389</string></field>

    <field name="rootdn"><string>CN=Manager,DC=MyCompany,DC=com</string></field>

    <field name="password"><string>secret</string></field>

- Delete exo-tomcat/temp/* to have a clean database and then start tomcat.

eXo starts and autocreates its organization model in your directory tree. Finally, the structure of the default LDAP schema looks like:

That's it! Now eXo uses your LDAP directory as its org model storage. Users, groups and memberships are now stored and retrieved from there. We suggest that you complete some guideline functions with eXo user management portlet and see what it changes in your directory tree.

## Configuration

If you have an existing LDAP server, the eXo predefined settings will likely not match your directory structure. eXo LDAP organization service implementation was written with flexibility in mind and can certainly be configured to meet your requirements.

The configuration is done in ldap-configuration.xml file, and this chapter will explain the numerous parameters it contains.

### Connection Settings

Firstly, start by connection settings which will tell eXo how to connect to your directory server. These settings are very close to JNDI API context parameters. This configuration is activated by the init-param ldap.config of service LDAPServiceImpl.

    <component>

      <key>org.exoplatform.services.ldap.LDAPService</key>

      <type>org.exoplatform.services.ldap.impl.LDAPServiceImpl</type>

      <init-params>

        <object-param>

          <name>ldap.config</name>

          <description>Default ldap config</description>

          <object type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig">

            <field name="providerURL"><string>ldap://127.0.0.1:389,10.0.0.1:389</string></field>

            <field name="rootdn"><string>CN=Manager,DC=exoplatform,DC=org</string></field>

            <field name="password"><string>secret</string></field>

            <!-- field  name="authenticationType"><string>simple</string></field-->

            <field name="version"><string>3</string></field>

            <field  name="referralMode"><string>follow</string></field>

            <!-- field  name="serverName"><string>active.directory</string></field-->

            <field name="minConnection"><int>5</int></field>

            <field name="maxConnection"><int>10</int></field>

            <field name="timeout"><int>50000</int></field>

          </object>

        </object-param>

      </init-params>

    </component>

- providerURL: LDAP server URL (see PROVIDER_URL). For multiple ldap servers, use comma separated list of host:port (Ex. ldap://127.0.0.1:389,10.0.0.1:389).

- rootdn: dn of user that will be used by the service to authenticate on the server (see SECURITY_PRINCIPAL).

- password: password for user rootdn (see SECURITY_CREDENTIALS).

- authenticationType: type of authentication to be used (see SECURITY_AUTHENTICATION). Use one of none, simple, strong. Default is simple.

- version: LDAP protocol version (see java.naming.ldap.version). Set to 3 if your server supports LDAP V3.

- referalMode: one of follow, ignore,throw (see REFERRAL).

- serverName: you will need to set this to active.directory in order to work with Active Directory servers. Any other value will be ignore and the service will act as on a standard LDAP.

- maxConnection: the maximum number of connections per connection identity that can be maintained concurrently.

- minConnection: the number of connections per connection identity to create when initially creating a connection for the identity.

- timeout: the number of milliseconds that an idle connection may remain in the pool without being closed and removed from the pool.

### Organization Service Configuration

Next, you need to configure the eXo OrganizationService to tell him how the directory is structured and how to interact with it. This is managed by a couple of of init-params : ldap.userDN.key and ldap.attribute.mapping in file ldap-configuration.xml (by default located at portal.war/WEB-INF/conf/organization)

    <component>

      <key>org.exoplatform.services.organization.OrganizationService</key>

      <type>org.exoplatform.services.organization.ldap.OrganizationServiceImpl</type>

      [...]

      <init-params>

        <value-param>

          <name>ldap.userDN.key</name>

          <description>The key used to compose user DN</description>

          <value>cn</value>

        </value-param>

        <object-param>

          <name>ldap.attribute.mapping</name>

          <description>ldap attribute mapping</description>

          <object type="org.exoplatform.services.organization.ldap.LDAPAttributeMapping">

          [...]

        </object-param>

      </init-params>

      [...]

    </component>

ldap.attribute.mapping maps your ldap to eXo. At first there are two main parameters to configure in it:

    <field name="baseURL"><string>dc=exoplatform,dc=org</string></field>

    <field name="ldapDescriptionAttr"><string>description</string></field>

- baseURL: root dn for eXo organizational entities. This entry can't be created by eXo and must preexist in directory.

- ldapDescriptionAttr (since core 2.2+) : Name of a common attribute that will be used as description for groups and membership types.

### Note

(since core 2.2+) : Name of a common attribute that will be used as description for groups and membership types.

Other parameters are discussed in the following sections.

#### Users

##### Main parameters

Here are the main parameters to map eXo users to your directory :

    <field name="userURL"><string>ou=users,ou=portal,dc=exoplatform,dc=org</string></field>

    <field name="userObjectClassFilter"><string>objectClass=person</string></field>

    <field name="userLDAPClasses"><string>top,person,organizationalPerson,inetOrgPerson</string></field>

- userURL : base dn for users. Users are created in a flat structure under this base with a dn of the form: ldap.userDN.key=username,userURL

Example :

    uid=john,cn=People,o=MyCompany,c=com

However, if users exist deeply under userURL, eXo will be able to retrieve them.

Example :

    uid=tom,ou=France,ou=EMEA,cn=People,o=MyCompany,c=com

- userObjectClassFilter: Filter used under userURL branch to distinguish eXo user entries from others.

Example : john and tom will be recognized as valid eXo users but EMEA and France entries will be ignored in the following subtree :

    uid=john,cn=People,o=MyCompany,c=com
      objectClass: person
      …
    ou=EMEA,cn=People,o=MyCompany,c=com
      objectClass: organizationalUnit
      …
        ou=France,ou=EMEA,cn=People,o=MyCompany,c=com
          objectClass: organizationalUnit
          …
            uid=tom,ou=EMEA,cn=People,o=MyCompany,c=com
              objectClass: person
              …

- userLDAPClasses : comma separated list of classes used for user creation.

When creating a new user, an entry will be created with the given objectClass attributes. The classes must at least define cn and any attribute refernced in the user mapping.

Example : Adding the user Marry Simons could produce :

    uid=marry,cn=users,ou=portal,dc=exoplatform,dc=org
      objectclass: top
      objectClass: person
      objectClass: organizationalPerson
      objectClass: inetOrgPerson
      …

##### User mapping

The following parameters maps ldap attributes to eXo User java objects attributes.

    <field name="userUsernameAttr"><string>uid</string></field>

    <field name="userPassword"><string>userPassword</string></field>

    <field name="userFirstNameAttr"><string>givenName</string></field>

    <field name="userLastNameAttr"><string>sn</string></field>

    <field name="userDisplayNameAttr"><string>displayName</string></field>

    <field name="userMailAttr"><string>mail</string></field>

- userUsernameAttr: username (login)

- userPassword: password (used when portal authentication is done by eXo login module)

- userFirstNameAttr: firstname

- userLastNameAttr: lastname

- userDisplayNameAttr: displayed name

- userMailAttr: email address

Example : In the previous example, user Marry Simons could produce :

    uid=marry,cn=users,ou=portal,dc=exoplatform,dc=org
      objectclass: top
      objectClass: person
      objectClass: organizationalPerson
      objectClass: inetOrgPerson
      …

#### Groups

eXo groups can be mapped to organizational or applicative groups defined in your directory.

    <field name="groupsURL"><string>ou=groups,ou=portal,dc=exoplatform,dc=org</string></field>

    <field name="groupLDAPClasses"><string>top,organizationalUnit</string></field>

    <field name="groupObjectClassFilter"><string>objectClass=organizationalUnit</string></field>

- groupsURL : base dn for eXo groups

Groups can be structured hierarchically under groupsURL.

Example: Groups communication, communication/marketing and communication/press would map to :

    ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org
    …
      ou=marketing,ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org
      …
      ou=press,ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org
      …

- groupLDAPClasses: comma separated list of classes used for group creation.

When creating a new group, an entry will be created with the given objectClass attributes. The classes must define at least the required attributes: ou, description and l.

### Note

l attribute corresponds to the City property in OU property editor

Example : Adding the group human-resources could produce:

    ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
      objectclass: top
      objectClass: organizationalunit
      ou: human-resources
      description: The human resources department
      l: Human Resources
      …

- groupObjectClassFilter: filter used under groupsURL branch to distinguish eXo groups from other entries. You can also use a complex filter if you need.

Example : groups WebDesign, WebDesign/Graphists and Sales could be retrieved in :

    l=Paris,dc=sites,dc=mycompany,dc=com
      …
      ou=WebDesign,l=Paris,dc=sites,dc=mycompany,dc=com
      …
        ou=Graphists,WebDesign,l=Paris,dc=sites,dc=mycompany,dc=com
        …
    l=London,dc=sites,dc=mycompany,dc=com
      …
      ou=Sales,l=London,dc=sites,dc=mycompany,dc=com
      …

#### Membership Types

Membership types are the possible roles that can be assigned to users in groups.

    <field name="membershipTypeURL"><string>ou=memberships,ou=portal,dc=exoplatform,dc=org</string></field>

    <field name="membershipTypeLDAPClasses"><string>top,organizationalRole</string></field>

    <field name="membershipTypeNameAttr"><string>cn</string></field>

- membershipTypeURL : base dn for membership types storage.

eXo stores membership types in a flat structure under membershipTypeURL.

Example : Roles manager, user, admin and editor could by defined by the subtree :

    ou=roles,ou=portal,dc=exoplatform,dc=org
    …
      cn=manager,ou=roles,ou=portal,dc=exoplatform,dc=org
      …
      cn=user,ou=roles,ou=portal,dc=exoplatform,dc=org
      …
      cn=admin,ou=roles,ou=portal,dc=exoplatform,dc=org
      …
      cn=editor,ou=roles,ou=portal,dc=exoplatform,dc=org
      …

- membershipTypeLDAPClasses: comma separated list of classes for membership types creation.

When creating a new membership type, an entry will be created with the given objectClass attributes. The classes must define the required attributes : description, cn

Example : Adding membership type validator would produce :

    cn=validator,ou=roles,ou=portal,dc=exoplatform,dc=org
      objectclass: top
      objectClass: organizationalRole
      …

- membershipTypeNameAttr : Attribute that will be used as the name of the role

Example : If membershipTypeNameAttr is 'cn', then role name is 'manager' for the following membership type entry :

    cn=manager,ou=roles,ou=portal,dc=exoplatform,dc=org </pre>

#### Memberships

Memberships are used to assign a role within a group. They are entries that are placed under the group entry of their scope group. Users in this role are defined as attributes of the membership entry.

Example: To designate tom as the manager of the group human-resources:

    ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
      …
      cn=manager,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
        member: uid=tom,ou=users,ou=portal,dc=exoplatform,dc=org
        …

The parameters to configure memberships are:

    <field name="membershipLDAPClasses"><string>top,groupOfNames</string></field>

    <field name="membershipTypeMemberValue"><string>member</string></field>

    <field name="membershipTypeRoleNameAttr"><string>cn</string></field>

    <field name="membershipTypeObjectClassFilter"><string>objectClass=organizationalRole</string></field>

- membershipLDAPClasses : comma separated list of classes used to create memberships.

When creating a new membership, an entry will be created with the given objectClass attributes. The classes must at least define the attribute designated by membershipTypeMemberValue.

Example : Adding membership validator would produce :

    cn=validator,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
      objectclass: top
      objectClass: groupOfNames
      …

<pre> cn=validator,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org objectclass: top objectClass: groupOfNames ... </pre>

- membershipTypeMemberValue: Multivalued attribute used in memberships to reference users that have the role in the group.

Values should be a user dn.

Example: james and root have admin role within the group human-resources, would give:

    cn=admin,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
      member: cn=james,ou=users,ou=portal,dc=exoplatform,dc=org
      member: cn=root,ou=users,ou=portal,dc=exoplatform,dc=org
      …

- membershipTypeRoleNameAttr: Attribute of the membership entry whose value references the membership type.

Example : In the following membership entry:

<pre> cn=manager,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org </pre>

'cn' attribute is used to designate the 'manager' membership type. Which could also be said : The name of the role is given by 'cn' the attribute.

- membershipTypeObjectClassFilter : Filter used to distinguish membership entries under groups.

You can use rather complex filters.

Example: Here is a filter we used for a customer that needed to trigger a dynlist overlay on openldap.

    (&amp;(objectClass=ExoMembership)(membershipURL=*))

Note: Pay attention to the xml escaping of the '&' (and) operator

#### User Profiles

eXo User profiles also have entries in the ldap but the actual storage is still done with the hibernate service. You will need the following parameters:

    <field name="profileURL"><string>ou=profiles,ou=portal,dc=exoplatform,dc=org</string></field>

    <field name="profileLDAPClasses"><string>top,organizationalPerson</string></field>

- profileURL: base dn to store user profiles

- profileLDAPClasses: Classes used to when creating user profiles

## Advanced topics

### Automatic directory population

At startup, eXo can populate the organization model based on

eXo organizational model has User,Group,Membership and Profile entities. For each, we define a base dn that should be below baseURL. At startup, if one of userURL, groupsURL, membershipTypeURL or profileURL does not exist fully, eXo will attempt to create the missing subtree by parsing the dn and creating entries on-the-fly. To determine the classes of the created entries, the following rules are applied :

- ou=... : objectClass=top,objectClass=organizationalUnit

- cn=... : objectClass=top,objectClass=organizationalRole

- c=... : objectClass=country

- o=... : objectClass=organization

- dc=.. : objectClass=top,objectClass=dcObject,objectClass=organization

Example:

If baseURL is o=MyCompany,c=com and groupsURL is dc=groups,cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com then, the following subtree will be created :

    ou=EMEA,o=MyCompany,c=com
      objectClass: top
      objectClass: organizationalUnit
      …
        c=France,ou=EMEA,o=MyCompany,c=com
          objectClass: top
          objectClass: country
          …
          cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com
            objectClass: top
            objectClass: organizationalRole
            …
            dc=groups,cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com
              objectClass: top
              objectClass: dcObject
              objectClass: organization
              …

### Active Directory sample configuration

Here is an alternative configuration for active directory that you can find in activedirectory-configuration.xml

### Note

There is a microsoft limitation: password can't be set in AD via unsecured connection you have to use the ldaps protocol

here is how to use LDAPS protocol with Active Directory :

    1 setup AD to use SSL:

        * add Active Directory Certificate Services role
        * install right certificate for DC machine

    2 enable Java VM to use certificate from AD:

        * import root CA used in AD, to keystore, something like

          keytool -importcert -file 2008.cer -keypass changeit -keystore /home/user/java/jdk1.6/jre/lib/security/cacerts

        * set java options

          JAVA_OPTS="${JAVA_OPTS} -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStore=/home/user/java/jdk1.6/jre/lib/security/cacerts"

    [...]

      <component>

      <key>org.exoplatform.services.ldap.LDAPService</key>

    [..]

            <object type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig">

             <!-- for multiple ldap servers, use comma seperated list of host:port (Ex. ldap://127.0.0.1:389,10.0.0.1:389) -->

        <!-- whether or not to enable ssl, if ssl is used ensure that the javax.net.ssl.keyStore & java.net.ssl.keyStorePassword properties are set -->

        <!-- exo portal default installed javax.net.ssl.trustStore with file is java.home/lib/security/cacerts-->

        <!-- ldap service will check protocol, if protocol is ldaps, ssl is enable (Ex. for enable ssl: ldaps://10.0.0.3:636 ;for disable ssl: ldap://10.0.0.3:389 ) -->

        <!-- when enable ssl, ensure server name is *.directory and port (Ex. active.directory) -->

        <field  name="providerURL"><string>ldaps://10.0.0.3:636</string></field>

        <field  name="rootdn"><string>CN=Administrator,CN=Users, DC=exoplatform,DC=org</string></field>

        <field  name="password"><string>site</string></field>

        <field  name="version"><string>3</string></field>

           <field  name="referralMode"><string>ignore</string></field>

           <field  name="serverName"><string>active.directory</string></field>

             </object>

    [..]

      <component>

        <key>org.exoplatform.services.organization.OrganizationService</key>

        [...]

            <object type="org.exoplatform.services.organization.ldap.LDAPAttributeMapping">

              [...]

              <field  name="userAuthenticationAttr"><string>mail</string></field>

              <field  name="userUsernameAttr"><string>sAMAccountName</string></field>

              <field  name="userPassword"><string>unicodePwd</string></field>

              <field  name="userLastNameAttr"><string>sn</string></field>

              <field  name="userDisplayNameAttr"><string>displayName</string></field>

              <field  name="userMailAttr"><string>mail</string></field>

              [..]

              <field  name="membershipTypeLDAPClasses"><string>top,group</string></field>

              <field  name="membershipTypeObjectClassFilter"><string>objectClass=group</string></field>

              [..]

              <field  name="membershipLDAPClasses"><string>top,group</string></field>

              <field  name="membershipObjectClassFilter"><string>objectClass=group</string></field>

            </object>

            [...]

    </component>

### OpenLDAP dynlist overlays

If you use OpenLDAP, you may want to use the overlays. Here is how you can use the dynlist overlay to have memberships dynamically populated.

The main idea is to have your memberships populated dynamically by an ldap query. Thus, you no longer have to maintain manually the roles on users.

To configure the dynlist, add the following to your slapd.conf :

    dynlist-attrset         ExoMembership membershipURL member

This snipet means : On entries that have ExoMembership class, use the URL defined in the value of attribute membershipURL as a query and populate results under the multivalues attribute member.

Now let's declare the corresponding schema (replace XXXXX to adapt to your own IANA code):

    attributeType ( 1.3.6.1.4.1.XXXXX.1.59 NAME 'membershipURL' SUP memberURL )

membershipURL inherits from memberURL.

    objectClass ( 1.3.6.1.4.1.XXXXX.2.12  NAME 'ExoMembership' SUP top MUST ( cn ) MAY (membershipURL $ member $ description ) )

ExoMembership must define cn and can have attributes :

- membershipURL: trigger for the dynlist

- member : attribute populated by the dynlist

- description : used by eXo for display

    # the TestGroup group
    dn: ou=testgroup,ou=groups,ou=portal,o=MyCompany,c=com
    objectClass: top
    objectClass: organizationalUnit
    ou: testgroup
    l: TestGroup
    description: the Test Group

On this group, we can bind an eXo membership where the overlay will occur:

    # the manager membership on group TestGroup
    dn: cn=manager, ou=TestGroup,ou=groups,ou=portal,o=MyCompany,c=com
    objectClass: top
    objectClass: ExoMembership
    membershipURL: ldap:///ou=users,ou=portal,o=MyCompany,c=com??sub?(uid=*)
    cn: manager

This dynlist assigns the role manager:/testgroup to any user.