Hi!
From reading the FAQ entry on dynlist (http://www.openldap.org/faq/data/cache/1209.html) it would seem that dynlist with member DN expansion lets me operate in two directions:
1. have an attribute dynamically expanded (e.g. for mapping a group to its members), e.g. '(cn=somedynamicgroup)' -> { member: uid=someuser,ou=People,o=SomeOrg, member: uid=otheruser,ou=People,o=SomeOrg } 2. search for dynamic objects whose dynamic attribute expands to given DN (e.g. for location all groups a given user is a member of), e.g. '(member=uid=someuser,ou=People,o=SomeOrg)' -> { dn: cn=somedynamicgroup,ou=Groups,o=MyOrg, dn: cn=somestaticgroup,ou=Groups,o=MyOrg}
To be specific, this fragment in the FAQ describes it:
--- SNIP ---
dynlist-attrset groupOfURLs memberURL member
it behaves much like the dyngroup overlay; the <attrs> portion of the URI must be absent, and the DN of the entries resulting from the search is added as value of the member attribute defined above. *For compare operations on the member attribute, all the values of the memberURL attribute of groupOfURLs objects are compared until a match is found; this exploits slapd group caching capabilities. *--- SNIP ---
Also, the slapo-dynlist manual states:
--- SNIP --- Compares that assert the value of the <member-ad> attribute of entries with <group-oc> objectClass apply as if the DN of the entries resulting from the expansion of the URI were present in the <group-oc> entry as values of the <member-ad> attribute. --- SNIP ---
I have the following configuration:
--- fragment of BDB instance config --- index member eq,pres
overlay dynlist dynlist-attrset groupOfURLs memberURL member --- end fragment of BDB instance config ---
The member expansion works:
ldapsearch -b 'o=MyOrg' -x -D 'cn=Manager,o=MyOrg' -H 'ldap://localhost' -y ~/ldappass 'cn=somedynamicgroup'
.... member: uid=someuser,ou=People,o=SomeOrg member: uid=otheruser,ou=People,o=SomeOrg ...
But searching for groups a user is a member of doesn't work for dynamic groups:
ldapsearch -b 'o=MyOrg' -x -D 'cn=Manager,o=MyOrg' -H 'ldap://localhost' -y ~/ldappass 'member=uid=someuser,ou=People,o=SomeOrg'
dn: cn=somestaticgroup,ou=Groups,o=SomeOrg ....
As a result no dynamic groups are found, only static ones.
Am I missing something in the configuration?* *
Probably you didn't understand how dynamic groups work. They are intended to check group membership, namely if a DN is in a group when the group is known and selected otherwise (e.g. by "DN" in the search base, or by "cn" or whatever in the search filter).
You can't put in the filter information that has to be generated dynamically, like dynamic group membership. Or, you could, but then any search would need to be split into:
- search the whole database for (objectClass=*) to trigger dynamic expansion of data; then - search the (at this point, unindexed) dynamically generated data. This could be implemented, but probably it's not what users want...
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it --------------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Email: pierangelo.masarati@sys-net.it ---------------------------------------
Pierangelo Masarati pisze:
You can't put in the filter information that has to be generated dynamically, like dynamic group membership. Or, you could, but then any search would need to be split into:
- search the whole database for (objectClass=*) to trigger dynamic
expansion of data; then
- search the (at this point, unindexed) dynamically generated data.
This could be implemented, but probably it's not what users want...
I thought that it works exactly like this, and I think this is what users want and expect (e.g. see the post "Dynamic Group overlay with ldapsearch for uniquemember oddity" from march 2006 by Michael Heep).
Groups are almost unusable if they don't work both ways since the necessary operations for a group-based authorization subsystem are both: mapping a group to member users and mapping a user to groups he's a member of.
For example, see Zope/Plone LDAP Multi Plugin (http://plone.org/products/ploneldap): it needs the following functionalities for LDAP groups to work properly (the names should be self-explanatory): enumerateGroups, getGroupsForPrincipal, enumerateUsers.
I believe that nss_ldap also does both types of search.
I imagined that OpenLDAP maintained a cache for dynamic groups (that's how I understood "this exploits slapd group caching capabilities" in the FAQ) in order to do a search on (member=member'sDN). Such a cache would only need updating in only two cases:
1. when there's a change in an object's DN if the object has an attribute used in any memberURL 2. when there's a change in any object in any attribute that's used in a filter in any memberURL in the directory (sorry for convoluted sentence, but it's a convoluted subject...).
When I think about it, this data should be permanent, so it should be kept in an index, not in memory cache.
Yes, there's some complex logic involved here (e.g. there needs to be a list kept updated with names of all the attributes that are used in memberURL filters) and it cannot posibly work for non-local memberURLs (those that specify a different LDAP server). But this is theoretically possible and would make dynlist usable for group memberships, not only for mail aliases (like currently).
Aleksander Adamowski wrote:
Groups are almost unusable if they don't work both ways since the necessary operations for a group-based authorization subsystem are both: mapping a group to member users and mapping a user to groups he's a member of.
No, one is enough for functionality. The reverse is not strictly required.
For example, see Zope/Plone LDAP Multi Plugin (http://plone.org/products/ploneldap): it needs the following functionalities for LDAP groups to work properly (the names should be self-explanatory): enumerateGroups, getGroupsForPrincipal, enumerateUsers.
Then it's not designed to exploit LDAP groups.
I believe that nss_ldap also does both types of search.
No it doesn't. It is designed check presence of user's DN in well-specified groups.
I imagined that OpenLDAP maintained a cache for dynamic groups (that's how I understood "this exploits slapd group caching capabilities" in the FAQ) in order to do a search on (member=member'sDN).
Yes it does. If a DN is found to be member of a group within the lifespan of an operation, so that the identity that performed the membership check doesn't change, membership information is cached, mainly to improve access checking efficiency.
Such a cache would only need updating in only two cases:
- when there's a change in an object's DN if the object has an attribute used in any memberURL
- when there's a change in any object in any attribute that's used in a filter in any memberURL in the directory (sorry for convoluted sentence, but it's a convoluted subject...).
When I think about it, this data should be permanent, so it should be kept in an index, not in memory cache.
Yes, there's some complex logic involved here (e.g. there needs to be a list kept updated with names of all the attributes that are used in memberURL filters) and it cannot posibly work for non-local memberURLs (those that specify a different LDAP server). But this is theoretically possible and would make dynlist usable for group memberships, not only for mail aliases (like currently).
What you're thinking of is not implemented in OpenLDAP. If you think it's so easy and so much required, feel free to submit a patch. Patches that provide generally useful functionalities are always welcome.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it --------------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Email: pierangelo.masarati@sys-net.it ---------------------------------------
Pierangelo Masarati wrote:
I believe that nss_ldap also does both types of search.
No it doesn't. It is designed check presence of user's DN in well-specified groups.
Well, on Debian 4.0 with libnss-ldap 251-7.5 I can see that it _does_ search for memberUID:
Aug 22 07:55:01 myserver slapd[3617]: conn=0 op=4719 SRCH base="o=MyOrg" scope=2 deref=0 filter="(&(objectClass=posixGroup)(memberUid=www-data))"
If the www-data user would belong to any dynamic groups, nss-ldap wouldn't find it out.
What you're thinking of is not implemented in OpenLDAP. If you think it's so easy and so much required, feel free to submit a patch. Patches that provide generally useful functionalities are always welcome.
I don't claim it is easy. In fact, I know this problem is quite hard - that's why I was hesitant to try out dynlist since I didn't expect it would work this way. The documentation mislead me to think it works, however.
OTOH, this functionality would be so useful, that I might give it a shot. But I didn't work with OpenLDAP codebase yet, so obviously I'll need some guidance.
A couple of initial questions spring to my mind:
1. I could use the backends' already present indexing mechanism for doing the hard work, but I need dynlist to be able order the backend to update indexes on member attribute for specific dynamic group objects, which could have their member lists changed. Is it possible with the current overlays/backends architecture? * Example scenario: * dynlist detects that a user has his DN changed from uid=phil,l=Brighton,o=MyOrg to uid=phil,l=London,o=MyOrg * dynlist determines which dynamic lists can potentially have him as a member: looks for a logical conjunction of two conditions: 1) the base DN of a memberURL is a prefix to either the old DN or new DN of the user, 2) any attribute in the LDAP filter of that memberURL is present in either the new or old version of the entry (or both). Such a dynamic list could either have the entry as a member or could gain this entry if it didn't have it previously so its member list needs to be reindexed. 2. dynlist overlay needs to keep track of base DNs and filter atrributes of all memberURLs present the backend database in two (or more) dictionary-type data structures. So it either needs to store data about memberURL's permanently (not possible for overlays?), or scan the whole backend's database at each startup (slow). Is it possible to implement the first variant - permanent data storage for dynlist overlay? I understand that overlays cannot assume that they are used by a specific backend (e.g. bdb) and cannot order the backend to store arbitrary data, AFAIK. Am I right? 3. A significant speed optimization could be made if the overlay could affect backend's indexing operation more directly. I mean, when changing a potential member entry, for a given potential dynamic list affected, either only one entry in its member index is affected (added, removed or DN change), or the index is left unchanged. If dynlist could simply test if the old and new verions of the entry matched the memberURL's filter (possibly a "scope one" search, but for the new verision it should be on a "virtual", non-existing-yet entry), then it could determine immediately which kind of low-level index operation needs to be performed - we have three possible cases that would only affect at most one index leaf. So the questions are: is it possible for the dynlist overlay to test filters on the old and new versions of an entry for the current transaction? Is it possible for the overlay to affect the backend's indexing operation on single index entry level and would it give a speed gain?
Ad 1. - I'm think that dynlist would have to keep track memberURLs in 2 dictionaries: one that maps base DN's from memberURL's to objects that have those memberURLs, second that maps attributes mentioned in filters to to objects that have those memberURLs. The first dictionary should be able to effectively search using a reverse-postfix-string match, that is "find all the keys which are prefixes of the given DN (the predecessors in LDAP hierarchy)".
Then to determine whether the memberURL is possibly affected, we have to determine the intersection of sets that result from lookup in both dictionaries - which could be implemented quite effectively if the dictionaries would keep the values ordered.
Now the answers to Howard Chu:
Howard Chu wrote:
If you make the data permanent, then you may as well just use static groups.
The difference is, static groups are human-managed (or require a special application to be written to maintain their definitions algoritmically and refresh them on a regular basis).
The data would just be helper data that would let dynlist optimize its work for speed by eliminating unneeded memberURL tests be deciding which memberURLs could potentially be affected by a ADD/MOD/MODRDN/DEL operation.
Tracking "any memberURL in the directory" is either memory intensive and/or CPU intensive. There's no good way to do this without sacrificing one or both.
Well, the server administrator should find the information on the speed sacrifice and decide whether the feature is viable or not.
I think that my scheme is not so memory intensive (especially if implemented with an on-disk dictionary structure) and it's CPU intensive only for worst-case scenarios (memberURL's anchored in directory's base DN and filtering on objectclass attribute) and only for direcotry update operations, which are rare for LDAP directories by definition (quoting IBM's "Understanding LDAP": "One special characteristic of directories is that they are accessed (read or searched) much more often than they are updated (written)"). There would be a warning in the documentation advising to avoid ussage of too generic LDAP attributes in memberURL filters (e.g. objectClass, cn) and too short base DNs.
Aleksander Adamowski wrote:
Pierangelo Masarati wrote:
I believe that nss_ldap also does both types of search.
No it doesn't. It is designed check presence of user's DN in well-specified groups.
Well, on Debian 4.0 with libnss-ldap 251-7.5 I can see that it _does_ search for memberUID:
Aug 22 07:55:01 myserver slapd[3617]: conn=0 op=4719 SRCH base="o=MyOrg" scope=2 deref=0 filter="(&(objectClass=posixGroup)(memberUid=www-data))"
If the www-data user would belong to any dynamic groups, nss-ldap wouldn't find it out.
My mistake: I was thinking of pam_ldap.
I'd like to move the discussion of the rest to openldap-devel; a separate response follows.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it --------------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Email: pierangelo.masarati@sys-net.it ---------------------------------------
Aleksander Adamowski wrote:
I imagined that OpenLDAP maintained a cache for dynamic groups (that's how I understood "this exploits slapd group caching capabilities" in the FAQ) in order to do a search on (member=member'sDN). Such a cache would only need updating in only two cases:
- when there's a change in an object's DN if the object has an attribute used in any memberURL
- when there's a change in any object in any attribute that's used in a filter in any memberURL in the directory (sorry for convoluted sentence, but it's a convoluted subject...).
When I think about it, this data should be permanent, so it should be kept in an index, not in memory cache.
If you make the data permanent, then you may as well just use static groups.
Tracking "any memberURL in the directory" is either memory intensive and/or CPU intensive. There's no good way to do this without sacrificing one or both.
Aleksander Adamowski wrote:
I imagined that OpenLDAP maintained a cache for dynamic groups (that's how I understood "this exploits slapd group caching capabilities" in the FAQ) in order to do a search on (member=member'sDN).
Note that the FAQ statement that you misquoted actually says:
For compare operations on the member attribute, all the values of the memberURL attribute of groupOfURLs objects are compared until a match is found; this exploits slapd group caching capabilities.
I.e., this only applies to the LDAP Compare operation, not to Search operations. Frankly the mention of slapd group caching here is bogus, since group caching only benefits ACL performance when processing multiple responses in a Search operation.
openldap-software@openldap.org