LDAP Authentication with MS Active Directory and Groups.

After several days of fruitless searching, I am now turning to the community for an answer. My company is evaluating Nuxeo as a possible ECM system and I have been tasked with mocking up an installation. The platform I am running is:

  1. Nuxeo 5.7.2
  2. Running on Ubuntu Server 13.04
  3. Integrated with an Microsoft Server 2012 Active Directory environment FOR LOGON AUTHENTICATION ONLY. Based on: Using a LDAP Directory

(I think that covers it.) However, the following question was posed to me: Can we use Active Directory Groups to restrict/grant access in Nuxeo?

I found this regarding Extension point userManager and I think I'm on the correct track, however, I'm still not able to have Nuxeo assign a user based on their AD group membership.

I have a test user called USITest and this user is part of the Test group in AD. I can log on to Nuxeo with this user's credentials, however, they are still put in the members group and not the Test group in Nuxeo.

edit Here is my default-ldap-users-directoy-config.xml file:

<?xml version="1.0"?>
<component name="org.nuxeo.ecm.directory.ldap.storage.users">

  <require>org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory</require>

  <!-- the groups SQL directories are required to make this bundle work -->
  <require>org.nuxeo.ecm.directory.sql.storage</require>

  <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
    point="servers">

    <!-- Configuration of a server connection
      A single server declaration can point to a cluster of replicated
      servers (using OpenLDAP's slapd + sluprd for instance). To leverage
      such a cluster and improve availability, please provide one
      <ldapUrl/> tag for each replica of the cluster.
    -->
    <server name="default">
      <ldapUrl>ldap://dca:3268</ldapUrl>
      <ldapUrl>ldap://dcb:3268</ldapUrl>
      <!-- Optional servers from the same cluster for failover
        and load balancing:

        <ldapUrl>ldap://server2:389</ldapUrl>
        <ldapUrl>ldaps://server3:389</ldapUrl>

        "ldaps" means TLS/SSL connection.
      -->

      <!-- Credentials used by Nuxeo5 to browse the directory, create
        and modify entries.

        Only the authentication of users (bind) use the credentials entered
        through the login form if any.
      -->
      <bindDn>CN=(CN_CHANGED),OU=Robots,DC=company,DC=com</bindDn>
      <bindPassword>********************</bindPassword>
    </server>
  </extension>

  <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
    point="directories">
    <directory name="userDirectory">
      <server>default</server>
      <schema>user</schema>
      <idField>username</idField>
      <passwordField>password</passwordField>

      <searchBaseDn>ou=Employees,dc=company,dc=com</searchBaseDn>
      <searchClass>person</searchClass>
      <!-- To additionally restricte entries you can add an
        arbitrary search filter such as the following:

        <searchFilter>(&amp;(sn=toto*)(myCustomAttribute=somevalue))</searchFilter>

        Beware that "&" writes "&amp;" in XML.
      -->

      <!-- use subtree if the people branch is nested -->
      <searchScope>subtree</searchScope>

      <!-- using 'subany', search will match *toto*. use 'subfinal' to
        match *toto and 'subinitial' to match toto*. subinitial is the
        default  behaviour-->
      <substringMatchType>subany</substringMatchType>

      <readOnly>false</readOnly>

      <!-- comment <cache* /> tags to disable the cache -->
      <!-- cache timeout in seconds -->
      <cacheTimeout>3600</cacheTimeout>

      <!-- maximum number of cached entries before global invalidation -->
      <cacheMaxSize>1000</cacheMaxSize>

      <!--
           If the id field is not returned by the search, we set it with the searched entry, probably the login.
           Before setting it, you can change its case. Accepted values are 'lower' and 'upper',
           anything else will not change the case.
      -->
      <missingIdFieldCase>lower</missingIdFieldCase>

      <!-- Maximum number of entries returned by the search -->
      <querySizeLimit>200</querySizeLimit>

      <!-- Time to wait for a search to finish. 0 to wait indefinitely -->
      <queryTimeLimit>0</queryTimeLimit>

      <creationBaseDn>ou=people,dc=example,dc=com</creationBaseDn>
      <creationClass>top</creationClass>
      <creationClass>person</creationClass>
      <creationClass>organizationalPerson</creationClass>
      <creationClass>inetOrgPerson</creationClass>

      <rdnAttribute>uid</rdnAttribute>
      <fieldMapping name="username">sAMAccountName</fieldMapping>
      <fieldMapping name="password">userPassword</fieldMapping>
      <fieldMapping name="firstName">givenName</fieldMapping>
      <fieldMapping name="lastName">sn</fieldMapping>
      <!--
      <fieldMapping name="company">o</fieldMapping>
      -->
      <fieldMapping name="email">mail</fieldMapping>

      <references>
        <inverseReference field="groups" directory="groupDirectory"
        dualReferenceField="members" />
      </references>
    </directory>
  </extension>

  <extension target="org.nuxeo.ecm.platform.usermanager.UserService" point="userManager">
    <userManager>
    <!--        <administratosGroup>Domain Admins</administratorsGroup> -->
    <defaultAdministratorId>User1</defaultAdministratorId>
    <defaultAdministratorId>User2</defaultAdministratorId>
    <defaultAdministratorId>User3</defaultAdministratorId>
      <defaultGroup>members</defaultGroup>
      <!--      <groups>
          <directory>Test</directory>
          <membersField>Test</membersField>
      </groups> -->
    </userManager>
  </extension>
</component>

I'm not able to assign the “Domain Admins” AD group to the Administrators group in Nuxeo either, so I have to call out each Administrator on their own. /edit

Any insight or assistance is greatly appreciated. Thank you.

1 votes

1 answers

8269 views

ANSWER



Hi,

The group configuration is not right. That's why this not works (you have guessed).

  • So in the first part of your XML you define the ldap cluster.
  • The second par you define the configuration for the usermanager to fetch users profiles with the field mapping (binding between Nuxeo Profile metadata and LDAP Object attribute) and groups definition.

If you read well this last part you see that :

<references>
    <inverseReference field="groups" directory="groupDirectory"
    dualReferenceField="members" />
</references>

Here you express that groups are referenced in another directory named groupDirectory and the list groups define in the user profile is stored into the groups metadata for the Nuxeo profile and the inverse refenrence users in groups are expressed into the members metadata.

But you never expressed that group is no more locally (by default in Nuxeo) but remotly stored into the LDAP.

So you must add a contribution like that:

 <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
point="directories">

<directory name="groupLdapDirectory">

  <!-- Reuse the default server configuration defined for userLdapDirectory -->
  <server>default</server>

  <schema>group</schema>
  <idField>groupname</idField>

  <searchBaseDn>ou=groups,dc=example,dc=com</searchBaseDn>
  <searchFilter>
    (|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))
  </searchFilter>
  <searchScope>subtree</searchScope>

  <readOnly>false</readOnly>

  <!-- comment <cache* /> tags to disable the cache -->
  <!-- cache timeout in seconds -->
  <cacheTimeout>3600</cacheTimeout>

  <!-- maximum number of cached entries before global invalidation -->
  <cacheMaxSize>1000</cacheMaxSize>

  <creationBaseDn>ou=groups,dc=example,dc=com</creationBaseDn>
  <creationClass>top</creationClass>
  <creationClass>groupOfUniqueNames</creationClass>

  <!-- Maximum number of entries returned by the search -->
  <querySizeLimit>200</querySizeLimit>

  <!-- Time to wait for a search to finish. 0 to wait indefinitely -->
  <queryTimeLimit>0</queryTimeLimit>

  <rdnAttribute>cn</rdnAttribute>
  <fieldMapping name="groupname">cn</fieldMapping>
  <!-- Add another field to map reel group label
  <fieldMapping name="grouplabel">sn</fieldMapping>
  -->

  <references>


    <!-- LDAP reference resolve DNs embedded in uniqueMember attributes

      If the target directory has no specific filtering policy, it is most
      of the time not necessary to enable the 'forceDnConsistencyCheck' policy.

      Enabling this option will fetch each reference entry to ensure its
      existence in the target directory.
    -->

    <ldapReference field="members" directory="userLdapDirectory"
      forceDnConsistencyCheck="false" staticAttributeId="uniqueMember"
      dynamicAttributeId="memberURL" />

    <ldapReference field="subGroups" directory="groupLdapDirectory"
      forceDnConsistencyCheck="false" staticAttributeId="uniqueMember"
      dynamicAttributeId="memberURL" />

    <inverseReference field="parentGroups" directory="groupLdapDirectory"
      dualReferenceField="subGroups" />

    <!-- LDAP tree reference resolves children following the ldap tree
      structure.

      Available scopes are "onelevel" (default), "subtree". Children with
      same id than parent will be filtered.

      Enabling this option will fetch each reference entry to ensure its
      existence in the target directory.

      WARNING: Edit is NOT IMPLEMENTED: modifications to this field will be
      ignored when saving the entry.
    -->
    <ldapTreeReference field="directChildren" directory="unitDirectory"
      scope="onelevel" />
    <ldapTreeReference field="children" directory="unitDirectory"
      scope="subtree" />

  </references>

</directory>

This an example but without an LDIF export of a groups and a user, you have to find alone the right values.

2 votes