I have troubleshot this for days now, and can't really discern what I am doing wrong and no previous posts have really shed light on the issue, so I am reaching out for help or to report a bug :).

Drupal 7 out of the box, unstable5. Configured an LDAP server as such (see ldapconfig pic). Configured Authentication. Configured a role mapping to test. Group object in LDAP defines role with member attribute pointing to person object with proper DN, have tested this with 3rd party tools. All is fine.

But, users never are mapped to this role despite LDAP being accurate. Looking into the LDAP server logs the Drupal server *is* binding and even searching for each user when appropriate, but it never does a search/retrieval of the Group object to try and determine membership. That to me seems telling and a bit suspicious. I have it configured to go check membership on a group object, so shouldn't it need to go pull this object everytime to make that mapping decision - why isn't it? I cannot figure out why this would not be happening and seems to be the crux of the issue. No obvious error messages on screen or in any logs.

The user Basit Mustafa should map to cn=Basit Mustafa,ou=people,dc=wu-way,dc=com. This appears to work.

Then the module should, according to the Content Editors mapping, check the ou=content editors, ou = groups , dc=wu-way,dc=com role object by looking for a member that is the DN cn=Basit Mustafa, ou=people,dc=wu-way,dc=com. That member attribute exists and is a valid entry (checked with 3rd party tools).

I see BINDs for the queries and even a SEARCH for the cn=Basit Mustafa object, but I don't see any SEARCH for the ou=Content Editors object. I find that very weird, almost like the module isn't taking my configuration from Part III in telling it to go check this object for membership.

Comments

johnbarclay’s picture

Title: Role Mappings/Authorizations Not Working Out Of The Box? » Ldap authorization: IIC Derive Drupal Roles not implemented
Assigned: Unassigned » johnbarclay
Category: support » bug

Sorry for your frustration and thanks for taking the time to well document this. Your timing is uncanny as I just made a comment about this http://drupal.org/node/806068#comment-4097492 feature's implementation. I'm changing this to a bug report since this II.C. is simply not implemented yet.

Can you help me understand what this option does? I've never used it in ldapgroups for drupal 6 so don't understand what it should do and haven't implemented it. I'm working on ldap_authorization the next week so any insight would be appreciated.

Given:
- Option IIC Derive Drupal Roles from Entry
- IIC. checkbox checked
- IIC. LDAP DNs containing roles: ou=content editors, ou = groups , dc=wu-way,dc=com
- IIC. Attribute holding members: member

Expected Behavior:

- find ou=content editors, ou = groups , dc=widgets,dc=com ldap object
- look for the string cn=Basit Mustafa, ou=people,dc=widgets,dc=com in the member attribute/collection of the ldap object.
- if it finds it, use the string ou=content editors, ou = groups , dc=widgets,dc=com for any mapping in part III.

Thanks

annaylop’s picture

Hahaha, great timing. Sometimes the world works in neat ways :).

I haven't used this option in Drupal before, but I have used similar methods of group membership mappings in other applications. So, I think you really have it down pretty well. The behavior you documented above is exactly what I would expect with my experience in other systems but also reading the docs for the D6 implementation.

I wish I was better with PHP, I'd help :). I should bone up!

I'd be happy to test!

johnbarclay’s picture

Priority: Normal » Major
thatoneguy’s picture

Version: 7.x-1.0-unstable5 » 7.x-1.x-dev
StatusFileSize
new2.75 KB

Here is a patch that fixes this. It also corrects a misspelling ($deug instead of $debug) earlier in the same file. I updated the version since this has not yet been fixed in the latest dev release, either. This has been tested against a live LDAP server.

The patch uses the first value of the 'cn' attribute for the name of the role, if it is available; otherwise, it defaults to the group object's DN as in the original comments. The attribute used should probably be configurable at some point. Or I suppose it could be rewritten to use the value of the group's naming attribute...

johnbarclay’s picture

Status: Active » Needs review

Great. Thank you. Could people test this patch out?

Also, this seems different than workflow in comment #1. Can you confirm that it is the same? If its different can you or someone else say if this is about what ldap_groups accomplished?

Also, The mapping dialog should convert from the full ldap address to a drupal group. Do you think the step "The patch uses -- A. -- the first value of the 'cn' attribute for the name of the role, if it is available; otherwise, -- B. -- it defaults to the group object's DN as in the original comments. " can be taken care of there, or will the site admin not know if -- A. -- or -- B. -- will be appropriate ahead of time.

Daeluin’s picture

Hello, I've applied the patch to the latest dev version. My settings are nearly identical to annaylop's, though I have "only apply mappings to ldap authenticated users" enabled, and the attribute containing role ids is "memberUid".

The ldap server tests fine, but if I attempt to login with the same user as the test it fails to authenticate.

Thanks for hard and speedy work on getting this module together for D7.

johnbarclay’s picture

I through the patch in #4. It should go out with unstable 6. The login failure in #6 is likely related to the binding issues recently resolved in ldap authentication.

johnbarclay’s picture

I applied the patch wrong. The correct one is pushed out now. I also have this in the ldap authorization simpletest cases. Can someone check if the simpletest is correct?

The simpletest parameters are:

  $test_data['ldap_authorization_conf']['consumer_conf']['deriveFromEntry'] = 1;
  $test_data['ldap_authorization_conf']['consumer_conf']['deriveFromEntryEntries'] = array('ou=groups,dc=ad,dc=myuniveristy,dc=edu');
  $test_data['ldap_authorization_conf']['consumer_conf']['deriveFromEntryAttr'] = 'member';

  $test_data['ldap_authorization_conf']['consumer_conf']['mappings'][] = array('ou=content editors,ou=groups,dc=ad,dc=myuniveristy,dc=edu', 'content editors');
  $test_data['ldap_authorization_conf']['consumer_conf']['mappings'][] = array('ou=content approvers,ou=groups,dc=ad,dc=myuniveristy,dc=edu', 'content approvers');


$test_data['server']['search_results']['member=cn=verykool,ou=special guests,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu']['ou=groups,dc=ad,dc=myuniveristy,dc=edu'] = array(
    0 => array('count' => 1, 'dn' => 'ou=content editors,ou=groups,dc=ad,dc=myuniveristy,dc=edu'),
    1 => array('count' => 1, 'dn' => 'ou=content approvers,ou=groups,dc=ad,dc=myuniveristy,dc=edu'),
    'count' => 2,
  );

$test_data['server']['search_results']['member=cn=jkool,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu']['ou=groups,dc=ad,dc=myuniveristy,dc=edu'] = array(
    0 => array('count' => 1, 'dn' => 'ou=content editors,ou=groups,dc=ad,dc=myuniveristy,dc=edu'),
    'count' => 1,
  );

$test_data['server']['users']['cn=jkool,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu']['attr'] = array(
    'dn' => 'cn=jkool,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu',
    'mail' => array( 0 => 'jkool@guests.myuniversity.edu', 'count' => 1),
    'sAMAccountName' => array( 0 => 'jkool', 'count' => 1),
    'password' => array( 0 => 'goodpwd', 'count' => 1),
    'memberOf' => array( 0 => 'cn=sysadmins,ou=it,dc=ad,dc=myuniveristy,dc=edu', 'count' => 1),
  );

$test_data['server']['users']['cn=verykool,ou=special guests,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu']['attr'] = array(
    'dn' => 'cn=verykool,ou=special guests,ou=guest accounts,dc=ad,dc=myuniveristy,dc=edu',
    'mail' => array( 0 => 'verykool@myuniversity.edu', 'count' => 1),
    'sAMAccountName' => array( 0 => 'verykool', 'count' => 1),
    'password' => array( 0 => 'goodpwd', 'count' => 1),
    'meMBErof' => array(
      0 => 'cn=sysadmins,ou=it,dc=ad,dc=myuniveristy,dc=edu',
      1 => 'CN=NETadmins,ou=it,dc=ad,dc=myuniveristy,dc=edu',
      'count' => 2,
      ),
  );

With the expected results that user 'jkool' is granted 'content editors' and user 'verycool' is granted 'content editors' and 'content approvers'.

johnbarclay’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

johnbarclay’s picture

Title: Ldap authorization: IIC Derive Drupal Roles not implemented » LDAP Authorization: II.C. Derive Drupal Roles not implemented
Version: 7.x-1.x-dev » 7.x-2.x-dev
Status: Closed (fixed) » Active

Making all bug/feature requests on LDAP Authorization: II.C. active for now.

Daeluin’s picture

Tried this again using beta9.
Still not applying group, and test isn't working.
Everything is setup identical to the D6 module.
Using Open LDAP profile.

Any way I can help test?

johnbarclay’s picture

Nearly finished with IIB and IIC including nested groups and test coverage during drupalcon. Should wrap things up this weekend.

johnbarclay’s picture

I'm merging #1412076: LDAP Authorization: Rework Strategy 3: groups as entries to meet more use cases with this since basically II.C. has been completely reworked. After adding documentation and checking everything in, I'll update this.

johnbarclay’s picture

Version: 7.x-2.x-dev » 7.x-1.x-dev
StatusFileSize
new75.9 KB

The UI and code for strategy IIC including nested groups is nearly finished. Can those of you using this, look through the following and see if it makes sense for your LDAP implementations:

johnbarclay’s picture

Status: Active » Needs review
CAPSLOCK2000’s picture

FWIW: I'm new to Drupal & LDAP and I haven't tested any of the new code but your analysis matches my expectations.

johnbarclay’s picture

Status: Needs review » Fixed
jdickmann’s picture

StatusFileSize
new2.43 KB

Finally sussed out the issues I was having with my first D7+project LDAP setup. We use OpenDirectory, but I don't think this issue would be specific to our setup. I'm using ldap-7.x-1.0-beta10 but I verified that the same code/issue exists in the current 7.x-1.x-dev and 7.x-2.x-dev branches.

The issue lies with this option:
User LDAP Entry attribute held in "Attribute holding drupal roles members"

The current code expects 'dn' but if you put in anything else (which my situation requires) it fails silently because two calls don't account for the 'attr' array returned by user_lookup (e.g. $user_ldap_entry[$user_ldap_attr][0] vs $user_ldap_entry['attr'][$user_ldap_attr][0]). I've attached a patch that corrects the two lines as well as a couple of misspellings.

Daeluin’s picture

Status: Fixed » Active

I'm still stuck. Upgraded to 1.0-beta10 yesterday and tried all the configurations that made sense.

My LDAP Groups are DNS: cn=staff,ou=group,dc=example,dc=com

Attribute Holding Previous List of Values: dn
Attribute holding drupal roles members: memberUid
User LDAP Entry attribute held in "Attribute holding drupal roles members": uid

Since I clearly need the Role Attribute "memberUid" to work I tried jdickmann's patch, but this didn't help.

For the last option, memberUid contains a list of "uid"s. In my setup every user's DN starts with uid=
However, the same values exist for cn, so I tried that too, but no dice.

Also, guess this is a separate bug, but when using the Authorization test feature, the AUTHORIZATION IDS field is always blank, unless I add a bogus user... then it generates a NEW user test entry under the bogus user's line saying "LDAP entry for drupal user not found." This tells me the other users are being found correctly, but I'm still not sure if there are other bugs so I keep testing independent logins as well.

Thanks!

johnbarclay’s picture

I committed #19, but am leaving this as needs review until the ldap authorization bugs in beta10 are worked through.

@Daeluin, I would just wait a couple days until the ldap authorization bugs and simpletests are worked through. Seems a bit of a mess right now.

johnbarclay’s picture

Status: Active » Needs review
electrickite’s picture

I recently ran up against this issue while testing the LDAP module on a new D7 deployment. I did manage to get it working eventually, but I'm not sure that it is working as expected.

My LDAP directory looks like this:

ou=Users,dc=blah,dc=edu
  cn=test_user,ou=Users,dc=blah,dc=edu
    [cn] = Test User
    [uid] = test_user

ou=Groups,dc=blah,dc=edu
  cn=admins,ou=Groups,dc=blah,dc=edu
    [cn] = admins
    [memberUid] = test_user

The configuration that worked for me was:

STRATEGY II.C.

  • LDAP DNs containing roles (one per line): admins
  • Attribute holding the previous list of values. e.g. cn, dn: cn
  • Attribute holding drupal roles members: memberUid
  • User LDAP Entry attribute held in "Attribute holding drupal roles members": uid

III. LDAP to drupal role mapping and filtering

  • Mapping of LDAP to drupal role (one per line): admins|administrator

I orginally tried to use DNs in both sections II and III, however this never produced a match. changing everything to CNs solved the issue, but it seems as though using DNs should work as long as 'Attribute holding the previous list of values. e.g. cn, dn' is set to dn.

Additionally, while testing I discovered that if 'Convert full dn to value of first attribute.' is checked, running a test of that LDAP authorization configuration results in an error message of

'Notice: Undefined offset: 1 in _ldap_authorization_ldap_authorization_maps_alter() (line 513 of /sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).'

The test completes successfully, however.

geste’s picture

electrickite,

Thanks for your example. I had LDAP group synch/authorization working with Beta 7 but it stopped working in beta 10. This AM I installed dev version dated Jun 17, and, while it did fix another issue (saving of role mapping/filters) new role assignments are not assigned in Drupal on user login.

Allow me to extend your example a bit so I can ask a question (I'll use an imaginary SSO uid "jimbo" in the axample). Say our users and groups look like:

ou=Users,dc=blah,dc=edu
  cn=jimbo,ou=Users,dc=blah,dc=edu
    [cn] = jimbo
    [uid] = jimbo

ou=Groups,dc=blah,dc=edu
  cn=admins,ou=Groups,dc=blah,dc=edu
    [cn] = admins
    [memberUid] = jimbo
 cn=total-slackers,ou=Groups,dc=blah,dc=edu
    [cn] = total-slackers
    [memberUid] = jimbo

What your post seemed to suggest is that you needed to put both of these entries in the "LDAP DNs containing roles (one per line)" like:

cn=admins,ou=Groups,dc=blah,dc=edu
cn=total-slackers,ou=Groups,dc=blah,dc=edu

Where in past it worked for me to simply put the single entry of

ou=Groups,dc=blah,dc=edu

Is that correct?

I have tried most permutations of II.C including using "'Attribute holding drupal roles members': uid" but no luck yet.

To me the utility of "LDAP DNs containing roles (one per line)" was to be able to specify mutiple containers, not to have to specify every possible group (as done in the mapping/filters.

Any thoughts appreciated.

Jim

geste’s picture

I should also add that I remembered to run the LDAP Authorization test and no matter the configuration, the test displays 10 random users but displays no roles whatsoever.

Jim

electrickite’s picture

What your post seemed to suggest is that you needed to put both of these entries in the "LDAP DNs containing roles (one per line)

That was the configuration that worked for me. My example was actually simpler than our environment: we have several LDAP groups that are granted different Drupal roles. To get this to work I did have to enter each group, one per line. The real thrust of my post was that I could not use cn=admins,ou=Groups,dc=blah,dc=edu to select the group, I had to use admins. (ie. the CN, contrary to the field's help text)

I agree that simply entering the conatiner that holds the groups would be preferable, so if I enter ou=Groups,dc=blah,dc=edu it will pull users from every group in that container.

@geste
You said that you had set "'Attribute holding drupal roles members:" to uid. In the LDAP example above, it should be set to memberUid. It should be the LDAP attribute in the group that contains either the CN or DN of the group's members.

geste’s picture

Electrickite,

I flubbed that last part. I meant to say the "set User LDAP Entry attribute held in "Attribute holding drupal roles members to uid. Yes using memberUid for "Attribute holding drupal roles members"

I have some time this afternoon. I think I'll try your configuration again.

John, I can attach my configuration again but if you can think of anything more I can do to debug this, please let me know. Electrickite's configuration works but seems to have to tread pretty far outside of traditional configuration for this component.

Jim

geste’s picture

I should clarify that when I said "Electrickite's configuration works" I meant "Electrickite's configuration works for him. I have run the authorization test against a number of variations of his configuration and what I typically see is:

1) A green check indicating test success.

2) A yellow Krumo-generated warning-ish block (doesn't explicitly say "warning") for any user entered into the test referencing (object)stdClass (and which will display the User object when clicked) along with the following line:

Called from /var/www/html/sites/all/modules/ldap/ldap_authorization/ldap_authorization.admin.test.inc, line 145

3) No roles returned for any users

Another note: I have 2 users in Drupal who are no longer in LDAP (left our department) and the Test does show "LDAP entry for drupal user not found." for those 2 users, so the LDAP module is handling those correctly.

johnbarclay’s picture

I'm not certain that IIC is working in 7.x-1.x-dev as I've only tried it via simpletests with a mock server. The most detailed narrative on how it is supposed to work is at: http://drupal.org/node/1499172

geste’s picture

I'm off for a week's quasi-vacation in a boatyard, but thought I'd try a few things before leaving. First I looked at the server configuration in beta-10 and supplied new elements like "organizationalUnit" for the group ObjectClass. That seemed to have no effect.

A few minutes ago, I reverted to the beta-7 LDAP code (did not fiddle with tables), and the LDAP group test worked immediately using II.C configuration. So, the simpler Authorization configuration for II.C in beta-7 (with fewer fields reuiring specification of dn versus cn) seems to work fine.

I presume the additional fields in II.C were added to support different use cases or LDAP configs.

Any thoughts on how to help debug?

Jim

johnbarclay’s picture

Its helpful to know beta-7 worked for case II.C. My only thoughts are to gradually go from beta-7 to beta-10 and see where it breaks. all the relevant code should be within the ldap_authorization module.

My approach is to setup an ldap is designed for II.C. then debug it.

thatoneguy’s picture

I need this as well and I'd be happy to take a look into this and help out, given that I have an environment setup that already requires this scenario. In fact, it previously worked in beta5 (yeah, haven't updated in a while, I know). The heart of the matter seems to be the introduction of a new configuration option and its use in constructing an utterly useless filter.

I have a container, ou=Web,ou=OPS,ou=EX,o=KPF, under which I have group objects. The cn=Editor group is of class organizationalRole. The attribute type roleOccupant contains the DN of users in this role. Trying to configure beta11 to support this is baffling. The purpose of the new field, "Attribute holding the previous list of values. e.g. cn, dn," is unclear. The previous list, mentioned, only contains DNs, so what else would I put here? Of course, putting 'dn' causes a filter to be constructed as follows in ldap_servers/LdapServer.class.php: (|(dn=ou=Web,ou=OPS,ou=EX,o=KPF)). And that would be the problem. You're not going to find a group with the requested DN. In fact, filtering on the DN attribute type is pretty useless, since you already know the DN.

If someone could tell me exactly what scenario II.C should be fulfilling, I'd be happy to recommend a course of action (and quite possibly produce a patch) that fixes this.

johnbarclay’s picture

maybe it should be ""Attribute holding held in the previous list of values. e.g. cn, dn," I know the purpose of the field was the use case where the multivalued attribute contained something besides dn. Any help with the wording is also appreciated. There is some clarity in the simpletests also...perhaps.

thatoneguy’s picture

If that's the case, it's not how that option is being used. I see two problems.

First, the configuration no longer makes sense. The new method significantly changes the use of LDAP DNs containing roles to the point that it doesn't even make sense to list DNs there anymore. Consider the following:

  1. Group entries may be confined to a specific container, but not necessarily (configurable search base).
  2. Group entries are identified by certain attribute-value pairs (configurable object-class).
  3. Members are named in a specific attribute (configurable attribute type).
  4. The group's member may be identified by name or by DN (configurable attribute value).
  5. Groups may be nested (filters won't solve this).

Essentially, the portion of the UI related to the first criterion was repurposed with the second criterion in mind. Meanwhile, in the LDAP server UI, a new option was added to care for exactly the same criterion (Name of Group Object Class).

Second, filtering on the DN will not work; 'dn' is not an attribute in that sense. Overall, the change appears to be a result of trying to solve #1016728: LDAP Authorization: Nested group recognition for authorization in group strategy IIB and IIC (also referenced in #15 here), but since you can't filter on DN, the new approach is wrong. The correct approach is to set an appropriate base for a search operation. Incidentally, this is exactly what happened with the old code left in ldap_authorization.inc. There's a comment claiming it is "somewhat flawed," but it was correct.

thatoneguy’s picture

Oh, one more thing. The notes referenced in #15 use 'distinguishedName' as the filter. This is possible, but it does not work as the notes would suggest. This filter actually finds objects with attribute types based on 'distinguishedName' with the value specified. The 'member' attribute is a good example.

To demonstrate: Say I have a user, uid=user,o=org, and a group cn=group,o=org. The group entry has an attribute-value pair, member:uid=user,o=org. Filtering for distinguishedName=uid=user,o=org returns the object cn=group,o=org.

johnbarclay’s picture

The only flaws I see in the old code are that it can't account for members being listed by anything but dn and it has a double query, once with dn and once with username. So for 6 groups, 6 to 12 queries are executed for each base dn. With the new approach 1 query is executed. It also makes assumptions about the ldap schema that aren't in the ldap standard and don't match all implementations.

Here are 2 examples of what the code is attempting to do in the non nested case. Ignoring the implementation flaws and user interface issues, are the following correct approaches? If I know what I'm shooting for, I can fix the implementation flaws.

Derive From Entry walk-through NOT nested:


--- configuration ------
0. authorization.deriveFromEntry = 1
1. authorization.deriveFromEntryEntries = array('it', 'people')
1b. authorization.deriveFromEnryEntryAttribute' = 'cn'
2. authorization.deriveFromEntryMembershipAttr = 'uniquemember'
2a. authorization.deriveFromEntryAttrMatchingUserAttr = 'dn'
4. authorization.deriveFromEntrySearchAll = 0
5. authorization.deriveFromEntryNested = 0
6. authorization.deriveFromEntryUseFirstAttr = 0
7. server.groupObjectClass = 'groupOfUniqueNames'

user ldap entry in question:
  'dn' => 'uid=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu',
  'cn' => 'joeprogrammer',
  'uid' => 'joeprogrammer',
  'mail' => array( 0 => 'joeprogrammer@myuniversity.edu'),
  'uid' => array( 0 => 'joeprogrammer'),


--- walk-through ------
1). foreach base dn, execute the following query:

(&
(objectClass=groupOfUniqueNames)
(|(cn=it)(cn=people))
(uniquemember=cn=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu)
)

in psuedo code:
(&
(objectClass=[server.groupObjectClass])
(|([authorization.deriveFromEnryEntryAttribute]=[authorization.deriveFromEntryEntries[i]])...([authorization.deriveFromEnryEntryAttribute]=[authorization.deriveFromEntryEntries[n]]))
([authorization.deriveFromEntryMembershipAttr]=[user_ldap_entry[deriveFromEntryAttrMatchingUserAttr]])
)


2. All entries returned represent groups that user is a member of.
Their DNs are added to the list of authorizations or the first attribute value
if authorization.deriveFromEntryUseFirstAttr is true.


and another example

Example A: Derive From Entry walk-through NOT nested:

--- configuration ------
0. authorization.deriveFromEntry = 1
1. authorization.deriveFromEntryEntries = array('cn=it,cn=groups,dc=ad,dc=myuniversity,dc=edu', 'cn=people,cn=groups,dc=ad,dc=myuniversity,dc=edu')
1b. authorization.deriveFromEnryEntryAttribute' = 'distinguishedname'
2. authorization.deriveFromEntryMembershipAttr = 'uniquemember'
3. authorization.deriveFromEntryAttrMatchingUserAttr = 'dn'
4. authorization.deriveFromEntrySearchAll = 0
5. authorization.deriveFromEntryNested = 0
6. authorization.deriveFromEntryUseFirstAttr = 1
7. server.groupObjectClass = 'groupOfUniqueNames'

user ldap entry in question:
  'dn' => 'uid=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu',
  'cn' => 'joeprogrammer',
  'uid' => 'joeprogrammer',
  'mail' => array( 0 => 'joeprogrammer@myuniversity.edu'),
  'uid' => array( 0 => 'joeprogrammer'),


--- walk-through ------
1). foreach base dn, execute the following query:

(&
(objectClass=groupOfUniqueNames)
(|(distinguishedname=cn=it,cn=groups,dc=ad,dc=myuniversity,dc=edu)(distinguishedname=people,cn=groups,dc=ad,dc=myuniversity,dc=edu))
(uniquemember=cn=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu)
)

in psuedo code:
(&
(objectClass=[server.groupObjectClass])
(|([authorization.deriveFromEnryEntryAttribute]=[authorization.deriveFromEntryEntries[i]])...([authorization.deriveFromEnryEntryAttribute]=[authorization.deriveFromEntryEntries[n]]))
([authorization.deriveFromEntryMembershipAttr]=[user_ldap_entry[deriveFromEntryAttrMatchingUserAttr]])
)


2. All entries returned represent groups that user is a member of.
Their DNs are added to the list of authorizations or the first attribute value
if authorization.deriveFromEntryUseFirstAttr is true.

These are from my notes at:

http://drupalcode.org/project/ldap.git/blob_plain/bbf3e6a3c236fb9de74a43...

http://drupalcode.org/project/ldap.git/blob_plain/bbf3e6a3c236fb9de74a43...

which are what I was originially going for.

thatoneguy’s picture

The first example should work, but I think it would be better to use the "list of entries" as a search base or list of search bases, rather than a static list of entry RDNs. This saves the administrator the work of manually enumerating names of roles, and lets the server do the work for you. It also solves the fact that names may not be unique, depending on how a particular manager sets up his directory.

Suppose I have users in ou=Users,o=Org and groups in ou=Groups,o=Org, but I only want roles created for groups under ou=Drupal,ou=Groups,o=Org. Or, suppose I have more than one group with the same name. Suppose the organization has committees each having its own chairman, defined in a group entry under each committee. But perhaps I mean only to include cn=Chairman,ou=Editing,ou=Committees,o=Org.

The second example will not work. Remember, distinguishedName != dn; it is the parent of all attribute types that hold DNs (such as member, roleOccupant, etc.) You can't filter on dn, either, because it's not an attribute type. If you want to retrieve a specific entry by DN, use ldap_read.

johnbarclay’s picture

re #37, the dn issue needs to be fixed. Makes sense why the simpletests work, but not actual server implementations. I need to fix the fake testing ldap server also to behave correctly.

The "list of entries" option sounds like a 7.x-2.x patch.

I'm tagging this as a release blocker.

johnbarclay’s picture

I'm not having any trouble filtering on distinguishedName. Can some others try a filter like:

&(distinguishedName=CN=jdoe,OU=People,DC=ad,DC=kansasstate,DC=edu)

and

(&
(objectClass=groupOfUniqueNames)
(|(distinguishedname=cn=it,cn=groups,dc=ad,dc=myuniversity,dc=edu))
(uniquemember=cn=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu)
)

where cn=it,cn=groups,dc=ad,dc=myuniversity,dc=edu is replaced by the dn of a group
and cn=joeprogrammer,ou=it,dc=ad,dc=myuniversity,dc=edu is replaced by a member of that group.

in a search on your ldap?

Does anyone know of any ldap implementations that don't use "distinguishedName" as an attribute of all objects?

johnbarclay’s picture

I altered the simpltests to never filter on dn=? to avoid false successes on ldap queries and add distinguishedname attributes to fake ldap server entires. Simpletests still 100% working for 7.x-1.x-dev, but this will help avoid any false successes in the future.

Daeluin’s picture

StatusFileSize
new45.21 KB
new49.42 KB

Still not working....
"If I know what I'm shooting for, I can fix the implementation flaws."

I'll try to explain what my setup requires, which works in the D6 module.

First the user DN:
uid=joe,ou=staff,dc=example,dc=com

Authentication works great. However this LDAP user entry has no Group info; instead there are LDAP Group DN's for each Group:
cn=role1,ou=group,dc=example,dc=com
cn=role2,ou=group,dc=example,dc=com

Each of these Group DN's contain a "memberUid" attribute with a list of CN's.

So, in the Authorization config I use II.C.

First lets try values the config instructions ask for, using the latest dev branch of 1.x:
LDAP  II.C  #1

First I've used the full DN's of the groups, and in the next field noted they are of type "dn".
I've lised the "memberUid" as the attribute of these groups holding the members, and as advised by the instructions I've set the type of attribute as "cn".

However, my LDAP logs show the first search after authentication as:
SRCH base="ou=staff,dc=example,dc=com" scope=2 deref=0 filter="(&(|(?=undefined)(?=undefined))(memberUid=Joe Smith))"

It appears the two "?=undefined" filters are from the full Group DN's, and we actually have the CN stored as a full name value.

Also, it is not searching the base DN, but simply one level lower, "ou=staff,dc=example,dc=com". However the Group DNs are in a separate ou altogether, "ou=groups,dc=example,dc=com", so these aren't going to be found.

Here's the next config with some adjustments:
LDAP   II.C   #2

Here I've changed the DNs to CNs, and set the "memberUid" search to look for "uid"s.

Now the log shows:
SRCH base="ou=staff,dc=example,dc=com" scope=2 deref=0 filter="(&(|(cn=devs)(cn=staff))(memberUid=joe))"

Now the Group filters are no longer undefined, and the uid value matches what is in the memberUid attribute. However it is still searching base="ou=staff,dc=example,dc=com", which is not the real base.

This would probably work if it was searching base="dc=example,dc=com".

Tried to make this as clear as possible. Hope it helps with implementation!

johnbarclay’s picture

@Daeluin, thanks for the details. Seems like 2 problems:

1. Basedn in ldap server configuration is off. Do you have "ou=staff,dc=example,dc=com" set as one of the base dns in your ldap_server module configuration?

2. The second problem seems like a big bug.
(&(|(?=undefined)(?=undefined))(memberUid=Joe Smith))
should be
(&(|(distinguishedname=cn=role1,....)(distinguishedname=cn=role2,....))(memberUid=Joe Smith))
or
(&(|(dn=cn=role1,....)(dn=cn=role2,....))(memberUid=Joe Smith))
but I can't reproduce it.

Daeluin’s picture

Yep, sure enough, my base dn settings were set as the base for authorizations, but not for groups. It wasn't clear to me it would be used for both, but I should have tested that!

Now using the cn's for the groups and authorization II.C works for me.

For the (?=unknown) bug I'm using openldap version 2.3.43 if that helps.

Thanks!

johnbarclay’s picture

Status: Needs review » Needs work

OpenLDAP implementation has not distinguishedName attribute. This needs to be reworked to all setting the attribute holding the DN OR iterate through more ldap queries.

johnbarclay’s picture

Title: LDAP Authorization: II.C. Derive Drupal Roles not implemented » LDAP Authorization: II.C. Derive Drupal Roles not implemented correctly
leveldoc’s picture

Hi John,

I'm working with Paul (figureone) on a LDAP-enabled druapl7 site - I'm the one running the OpenLDAP server. The configuration options to integrate users into the drupal site are very ... strange; while we did eventually manage to get it working, it is neither intuitive nor desirable to configure users that way (we ended up configuring it like in #41). Below are my suggestions which are basically what every other product out there using LDAP looks like in its configuration.

Normally, you have two types of groups: posixGroup and groupOfNames / groupOfUniqueNames. They work differently in that the former only stores the uid's of the members, the latter stores the entire DN. Both should be supported by drupal and it is usually achieved by offering the following fields:

  • server / connection options, etc.
  • base DN for users (possibly multivalued) plus scope
  • base DN for groups (possibly multivalued) plus scope
  • user creds for anonymous search

Do NOT, under any circumstance, require (or even suggest!) to supply only the top DN as the base for everything in any other but the most basic LDAP deployment. There is a reason this thing is a tree, and one of them is to be able to specify which branch you start looking! It makes no sense whatsoever to assume a common base for both groups and people.

That's it. On to the groups membership determination. You do one of two things:

  1. for posixGroups, search the Base DN for groups, filtering by memberUid=%uid. On the command line, that looks something (note pseudocode) like this:

    $ ldapsearch -ZZLLLx -D 'cn=anonuser,dc=example,dc=org' -H 'ldap://ldap.example.org' -W -b 'ou=groups,dc=example,dc=org' -s ['one'|'sub'] '(memberUid=%uid)' gid

    This will return an array containing the gids that this uid is a member of.

  2. for groupOfNames, search the base DN for users, filtering by memberOf=%gid. On the command line, that looks something like this:

    $ ldapsearch -ZZLLLx -D 'cn=anonuser,dc=example,dc=org' -H 'ldap://ldap.example.org' -W -b 'ou=people,dc=example,dc=org' -s ['one'|'sub'] '(memberOf=%gid)' uid

    This will return an array of uids that are a member of a specific group.

The current configuration options make no sense to me. Requiring the admin to list the DN's of groups "containing the roles" (??? roles are something completely different in an LDAP context!) is almost mean-spirited. :-)

OK, I hope you take my comments as what they are - suggestions. I know I'm not the only one who's getting confused about the way that this is being configured, and it breaks with literally all other products that use LDAP for authentication and group membership purposes. One other example that is also written in PHP can be found in the owncloud project - they have a very basic, but highly effective configuration page. Hope this helps!

Aloha
Stephan

johnbarclay’s picture

Yes. The documentation needs a lot of work. The authorization part is partially about roles and groups as such though you are talking about a particular subset of that. Its also about mapping whatever to drupal objects; its these use cases that make things complex. I've literally given 10 people a jumpstart on helping with the documentation and none have come through.

I definately plan to clean up IIC Documentation though I don't recommend it because it doesn't scale well for nested groups without the memberOf overlay or an attribute analogous to dn in role and user entries.

pcharsle’s picture

Hi John,

I am using the second strategy 11C configuration shown in comment #41 above together with the best practice service account configuration in my server settings. The authorization and server tests all run and correctly display the authorizations and mappings that have been defined in our LDAP groups. We are using the ldap_authorization_drupal_role configuration and have tested with ldap-7.x-1.0-beta10 and beta12.

However, when logging in, authorizations are not granted correctly and an error message is displayed:

ldap_search() function error. LDAP Error: No such object, ldap_search() parameters: ldap_search() call: base_dn: ou=Users,dc=onehealthhub,dc=org, filter = (uid=p.charsley@massey.ac.nz), attributes: , attrsonly = 0, sizelimit = 0, timelimit = 0, deref = , scope = 3

I believe the problem occurs because although the Server has been defined to use a service account, the above search is being performed using the user's account which will always fail because only service accounts have read permission in our LDAP database. I verified that this is indeed the case by testing the login process using a service account and found that authorization worked correctly.
Is this a known issue? We do not wish to have to grant read permission to our user accounts in LDAP.

Thanks, Paul

johnbarclay’s picture

pcharsle’s picture

Hi John,

I found the problem in the function _ldap_authentication_user_login_authenticate_validate in ldap_authentication.inc. At the end of the foreach loop that loops through each enabledAuthenticationServer, the following code is provided to disconnect when the bind method is via a service account or anonymous:

if ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT ||
        $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON_USER) {
        $ldap_server->disconnect();
    }

However, this code is not called because at the end of a successful authentication there is a break statement that breaks out of the loop. The solution is to add this code just prior to the break statement. Should I submit a patch?

Paul

johnbarclay’s picture

A patch would be great. Does the change in #50 fix your issue is #48?

In that for loop looks like there are a number of places to disconnect before "continue"s or "break"s (http://drupalcode.org/project/ldap.git/blob_plain/refs/heads/7.x-1.x:/ld...)

pcharsle’s picture

Yes, the change in #50 fixes the problem in #48. We will submit a patch.

pcharsle’s picture

Hi John,

Attached is my patch which fixes the problem in #48. After looking at the code I don't believe it's necessary to add the disconnect in other places. The problem only happens because it wasn't being called after a successful user password test when the service account is being used.

Paul

johnbarclay’s picture

Thanks, I committed this and it will end up in 7.x-2.x on the next commit also, but am leaving this thread open as its not about authentication. I someone wants to continue the thread in 47-53, a new thread would be better.

johnbarclay’s picture

I have to believe that given distinguishedName cannot be relied on #1743474: LDAP_Authorization: distinguishedName attribute needs to go: not used in some LDAPs the best strategy for IIC is to go back to the tried and true method in the 6 version: http://drupalcode.org/project/ldap_integration.git/blob_plain/refs/heads... under "Strategy 3: groups as entries."

This would either need to be modified to support nested groups...or a 4th method used that relied on an attribute that mapping directly to an ldap group.

johnbarclay’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev

I'm changing this to 7.x-2.x because that is where I'm working.

I believe the following 2 changes are needed for IIC to work for everyone:

1. Per #37, get rid of the "list of entries" configuration option. Move the filtering aspect to the mapping/filtering section. This is how option IIB behaves. This will allow for a single query in the first iteration of groups in nested groups, or one query in the case of non nested groups.

2. Split IIC into two approaches.

  • IIC: One with where the attribute in member or uniqueMember DOES NOT exist as a user attribute. This is how IIC was implemented in drupal 6. Its quite query intensive, but works.
  • ID: One with where the attribute in member or uniqueMember exists as a user attribute. eg. member=[uid] and user entry has a uid attribute. or member=distinguishedName and user entry has a distinguishedName attribute.
johnbarclay’s picture

Status: Needs work » Needs review

Once the "list of entries" is removed, the IID option is no longer needed. The burden raised in issue#36 is no longer relevant. The workflow in IIA-IIC becomes the same and UI gets simpler. This is working out well. I haven't implemented these changes, but need feedback. IIC has been a pain in the but coming from an Active Directory background.

Please confirm that the walkthroughs for IIC for openLdap make sense:

Please let me know what you think of removing "list of entries" in ldap authorization strategy IIC

Renee S’s picture

The walkthroughs makes sense me me. (Our LDAP is set up the first way (group not as user attribute) so we haven't been able to use the Authorization component at all.) It certainly does simplify things.

leveldoc’s picture

I don't see posixGroups being mentioned anywhere in the walkthroughs. Don't make sense to me, therefore.

jzornig’s picture

Version: 7.x-2.x-dev » 7.x-1.x-dev
Status: Needs review » Needs work

The patch applied in #54 breaks profile mapping of LDAP attributes that are private to the user.
Up to this patch I could map any attributes in the LDAP record that were private to the user to profile fields. After the patch only LDAP attributes that are accessible to anon bind are successfully mapped.

jzornig’s picture

StatusFileSize
new867 bytes

Patch for above. Should retain the functionality for both Service account and anon/user bind methods.

jzornig’s picture

Status: Needs work » Needs review
bcodding’s picture

Running the latest HEAD (commit 875e704b1a4094500557b705dc3c38b55e6f72cb), with
cn=ben,ou=people,dc=dot,dc=com
uid: ben

cn=guys,ou=groups,dc=dot,dc=com
memberUid: ben
memberUid: stan
memberUid: frank

and groupMembershipsAttrMatchingUserAttr = 'uid'

roles are broken, because groupMembershipsFromEntryRecursive tries to pull groupMembershipsAttrMatchingUserAttr value from the group's DN. In this configuration, 'uid' doesn't exist in 'cn=guys,ou=groups,dc=dot,dc=com'.

Here's a patch - though it only fixes my problem. Looks like recursive group membership lookups may need an additional config - groupMembershipsAttrMatchingGroupAttr, or something along those lines.

thatoneguy’s picture

I'm not convinced that patch solves the actual problem in a sensible way. It effectively forces one to not only use 'cn', but include 'cn' in the RDN for the user object. I'd be interested in reviewing the code and offering up a better patch, but I'm not sure where this problem needs to be fixed. This issue has been switched between 7.x-1.x-dev and 7.x-2.x-dev several times, mostly without elaborating on the reason. If someone can tell tell me what version this issue is for, I'll be happy to contribute. I have to say, though, I'm a little baffled as to why there are two main versions out here, given that neither yet has a release candidate.

johnbarclay’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev

I don't expect any work to get done on 1.x from here on out. This issue should focus on 7.x-2.x.

mitjasvab’s picture

As bcodding said

roles are broken, because groupMembershipsFromEntryRecursive tries to pull groupMembershipsAttrMatchingUserAttr value from the group's DN. In this configuration, 'uid' doesn't exist in 'cn=guys,ou=groups,dc=dot,dc=com'.

If you look into groupUserMembershipsFromEntry, for example, the LDAP query is

$group_query = '(&(objectClass=' . $this->groupObjectClass . ')(' . $this->groupMembershipsAttr . "=$member_value))";
$group_entries = $this->search($base_dn, $group_query, array());

the query is something like this: (&(objectClass=posixgroup)(memberuid=my_userid))
this returns group objects.

$group_entries is passed to groupMembershipsFromEntryRecursive, so you already have group objects and you have not to search with memberuid=my_userid, but just to use these objects.

All these objects have defined a DN string. Just use it. So I guess that maybe this unnecessary buggy code is a copy&paste error???

I just deleted these lines, see the patch. And changed memberid with groupid for better comprehension. Tested with OpenLdap and AD, it works.

johnbarclay’s picture

Can someone test this patch for configuration with Active Directory memberOf or another ldap with the memberOf overlay? That is the other primary use case this needs to handle.

mitjasvab’s picture

Hi johnbarclay, I wish to explain better... I tested it with OpenLdap + memberuid=my_userid
test results:

  1. ldap_server->groupMembershipsFromUser - returns the correct list of groups
  2. ldap_server->groupUserMembershipsFromUserAttr - returns 'A user LDAP attribute such as memberOf exists that contains a list of their group' is not configured.
  3. ldap_server->groupUserMembershipsFromEntry - returns the correct list of groups

and with Active Directory + memberOf:

  1. ldap_server->groupMembershipsFromUser - returns the correct list of groups
  2. ldap_server->groupUserMembershipsFromUserAttr - returns the correct list of groups
  3. ldap_server->groupUserMembershipsFromEntry - returns 'Groups by entry not configured.'

If you configure AD withouth memberOf and with LDAP Group Entry Attribute Holding User's DN, CN, etc., you obtain the same result as with OpenLdap above.
If you configure AD with both approaches, all the three functions returns the correct list of groups.

But I'm not very experienced in Ldap/AD and I prefer another one test. I have no Nested groups, is there someone with nested groups to check the recursive function?

johnbarclay’s picture

Thanks for clarifying. Another test would help. I have some tests in the simpletests, but these use a fake ldap so aren't as useful. I will make an attempt to get the simpletests back in synch with dev.

mitjasvab’s picture

Today I spoke with the LDAP expert.
He notify me, that in our configuration, ldap module doesn't retrieve the primary group from our posix OpenLdap, only the secondary groups.

We have this configuration:
user object: inetOrgPerson (structural)
attributes:

  • uid = _username_
  • gidNumber = the number of the primary group for _username_

group object: posixGroup (structural)
attributes:

  • gidNumber = the number of this group
  • memberUid = the uid of a person that is member of this group, that is the secondary group.

Using the query in #66 you can obtain only the secondary groups.

To obtain the primary group too, you have to launch two queries. At first obtain the the gidNumber from the user attributes with this query
(&(objectClass=inetOrgPerson)(uid=_username_))

At second obtain the groups
(&(objectClass=posixGroup)(|(gidNumber=_gidNumber_from_previous_query_)(memberUid=_username_)))

As described in #66 groupUserMembershipsFromEntry retrieves the secondary groups with this query:
(&(objectClass=posixgroup)(memberuid=_username_))

There should be a way to obtain the primary group too. I think about it as a new option in LDAP Group Configuration form. Something like: "A user LDAP attribute such as gidNumber exists that contains the id of the user's primary group. Posix openLdap fit this model."

And the query can be this one:

(&(objectClass=inetOrgPerson)(AuthName-attribute=_username_)) to retrieve gidNumber followed by
(&(objectClass=posixGroup)(gidNumber-attribute=_gidNumber_from_previous_query_)) to retrieve the group DN

If this make sense, I can open a new feature request for the posix primary gorups. What are your opinion?

johnbarclay’s picture

Separate issue is better. I suspect it won't go anywhere in the 7 branch unless someone writes a good patch. The nested groups are just too complex to deal with another group structure especially an inconsistent one.

nicholas.alipaz’s picture

Status: Needs review » Needs work

I have just attempted patching 7.x-2.x-dev with the patch in #66 but the changes are rejected. I went to see if I could manually merge the changes in, unfortunately that didn't seem to help either. My ldap setup is:

dn: ou=user,dc=foo,dc=bar,dc=com
objectclass: organizationalUnit
ou: user

dn: cn=user1,ou=user,dc=foo,dc=bar,dc=com
cn: user1
entrydn: cn=user1,ou=user,dc=foo,dc=bar,dc=com
entryuuid: 956897aa-be4c-1032-81a5-637be50fbb72
memberof: cn=drupaladministrator,ou=groups,dc=foo,dc=bar,dc=com
uid: user1
objectclass: organizationalPerson
objectclass: person

dn: ou=groups,dc=foo,dc=bar,dc=com
objectclass: organizationalUnit
objectclass: top
ou: groups

dn: cn=drupaladministrator,ou=groups,dc=foo,dc=bar,dc=com
cn: drupaladministrator
member: cn=user1,ou=user,dc=foo,dc=bar,dc=com
member: cn=user2,ou=user,dc=foo,dc=bar,dc=com
objectclass: groupOfNames
objectclass: top

Seeing how the code differs in what I downloaded and the references in the patch there is really no good way to test with this patch.

kenorb’s picture

#66 patch is actually doing nothing apart of changing $member_id to $group_id and forcing to set value from $group_entry['dn'];
Tested (it doesn't apply cleanly) and it didn't work.

kenorb’s picture

jerrac’s picture

Unfortunately I don't have time to do any debugging, but I can confirm that as of jan-10-2014 dev version, ldap groups do not work as expected.

Specifically, if I do not check the "A user LDAP attribute such as memberOf exists that contains a list of their groups. Active Directory and openLdap with memberOf overlay fit this model. " box, and set the attribute to look for, roles do not get assigned when using authorization.

Which means that if I use a group scheme that doesn't also add an attribute to the users ldap entry, then authorization fails.

Like if I used posixGroup and the member attribute in the group. That does not create a groupMembership value on the users ldap entry. It keeps everything in the group ldap entry. That just will not work. Which is annoying since that's the method I want to use.

Anyway, if you have some quick tests I can do, I'd be happy to. If I ever get some free time for this, I'll dig into the code.

kenorb’s picture

I've managed to make the LDAP group working, see:
https://drupal.org/comment/8451171#comment-8451171

The title needs updating if the problem described in this issue still persist, as the section names are different now I think and it should be more specific.

kenorb’s picture

Title: LDAP Authorization: II.C. Derive Drupal Roles not implemented correctly » module is not checking the OU roles object by looking for a member that is the DN

  • johnbarclay committed 617948c on 8.x-3.x
    Issue #1066608.  Fixed inconsistency in walk through of IIC
    
  • johnbarclay committed 9f64ae8 on 8.x-3.x
    Issue #1066608.  Changes to walk through of IIC
    
grahl’s picture

Status: Needs work » Needs review

The last submitted patch, 4: derive_from_entry_authorizations.patch, failed testing.

The last submitted patch, 4: derive_from_entry_authorizations.patch, failed testing.

The last submitted patch, 4: derive_from_entry_authorizations.patch, failed testing.

The last submitted patch, 53: ldap_auth_disconnect_not_called-1066608-48.patch, failed testing.

The last submitted patch, 61: ldap_auth_dissconnect-1066608-60.patch, failed testing.

The last submitted patch, 19: ldap_authorization_iic.patch, failed testing.

The last submitted patch, 19: ldap_authorization_iic.patch, failed testing.

The last submitted patch, 19: ldap_authorization_iic.patch, failed testing.

The last submitted patch, 53: ldap_auth_disconnect_not_called-1066608-48.patch, failed testing.

The last submitted patch, 53: ldap_auth_disconnect_not_called-1066608-48.patch, failed testing.

The last submitted patch, 61: ldap_auth_dissconnect-1066608-60.patch, failed testing.

The last submitted patch, 61: ldap_auth_dissconnect-1066608-60.patch, failed testing.

The last submitted patch, 63: 0001-groupMembershipsAttrMatchingUserAttr-is-not-in-DN.patch, failed testing.

The last submitted patch, 63: 0001-groupMembershipsAttrMatchingUserAttr-is-not-in-DN.patch, failed testing.

The last submitted patch, 63: 0001-groupMembershipsAttrMatchingUserAttr-is-not-in-DN.patch, failed testing.

grahl’s picture

Status: Needs review » Closed (outdated)

Closing based on conflicting information above, please reopen if you still have an issue.