LDAP2010/2010-06-14
Done some improvements in LDAPConnection, some new broken stuff... work in progress, heh.
Resolved some questions with nested groups and doing with LDAPGroups in common, suggested to use 2 different backends for AD and LDAP installations without a support of nested groups.
LDAPGroups
Using a 'member' field of a group entry to find a members of that group. That way we can't recognize if a member is a user or it is another group, nested in first.
ADGroups
Using a 'memberOf' field of a member entry, to find groups, to which that member belongs, and we still could use 'member' attribute of a group entries if needed, while AD provides both.
Let me explain.
# Test2, Test, example.org dn: CN=Test2,OU=Test,DC=example,DC=org objectClass: group cn: Test2 # Test1, Test, example.org dn: CN=Test1,OU=Test,DC=example,DC=org objectClass: group memberOf: CN=Test2,OU=Test,DC=example,DC=org cn: Test1 # Test, Test, example.org dn: CN=Test,OU=Test,DC=example,DC=org objectClass: group memberOf: CN=Test1,OU=Test,DC=example,DC=org cn: Test dn: uid=User,OU=Test,DC=example,DC=org objectClass: user memberOf: CN=Test,OU=Test,DC=example,DC=org uid: User
User is a member of Test2, but memberOf didn't show it directly. So LDAPGroup should to find it himself, and there will be a some queries. Let me explain the algorithm in details — lets check, that user, called User, is member of group, called Test2.
For example, let ACL backend ask us 'Does User belongs to a Test2?', like a
if 'User1' in self.request.groups['Test2']:
What will be done then:
ADGroupsBackend.getitem returns a ADGroup(self.request, 'Test2', self)
- no queries
<ADGroup(Test2)>.contains search for distinguished name of User1
- (uid=User1)
<ADGroup(Test2)>.contains checks that distinguished name of User1 is not appears in a 'member' attribute values of group with name 'Test2'
(&(objectClass=group)(cn=Test2)(member=uid=User,OU=Test,DC=example,DC=org))
<ADGroup(Test2)>.contains retrieve an entries list of groups, nested in Test2 (got a Test1 group)
(&(objectClass=group)(memberOf=CN=Test2,OU=Test,DC=example,DC=org))
For all of retrieved groups (in that case, the only one, called 'Test1') lets check, if 'User1' in self.request.groups['Test1'] we got a recursion, executing until it found User1 in 'member' of 'Test'.
So, we got a several queries to LDAP server, of the order of hierarchy height, but it is acceptable. And in case we don't have the 'memberOf' attribute, then we need to execute a one query per 'member' value to check, is that member a user, or a group (and there may be thousands of members in group).