09-03-2013 02:32 PM
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:
(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>(&(sn=toto*)(myCustomAttribute=somevalue))</searchFilter>
Beware that "&" writes "&" 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.
09-05-2013 05:13 AM
Hi,
The group configuration is not right. That's why this not works (you have guessed).
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.
09-05-2013 05:13 AM
Hi,
The group configuration is not right. That's why this not works (you have guessed).
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.
Find what you came for
We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.