We have an Active Directory domain with >6000 users and several hundred groups. The group hierarchy is usually nested 4-5 levels deep. Queries for the full set of nested groups for a user take > 10 seconds each. We have an app (Nexus OSS) that asks for a user's nested groups on every interaction (e.g. for each dependency needed to perform a maven build) and does not perform local caching.
I am trying to implement a slapd + meta + pcache solution that will proxy the LDAP query, cache the results, and significantly speed up user interactions with this app. I have tried many configurations. I can always proxy the request, but I haven't yet been able to fully cache the results. I have had the most success with the passthru module from https://github.com/cbueche/openldap-passthru and rwm. In this configuration, slapd proxies inbound filters like "(member=CN=my name,ou=users,dc=some,dc=structure)" and passes that on to AD as "member:1.2.840.113556.1.4.1941:=CN=my name,ou=userss,dc=some,dc=structure)". AD returns the group DNs but slapd partially caches the result. The cached results are the direct group memberships, not the complete set of nested groups.
Is what I want to do possible? If so, can someone please point me in the right direction?
Here is my slapd.conf file: ----------------------------- ### Logging ################################################################### loglevel -1 logfile /var/log/openldap.log
### Schema includes ########################################################### include /etc/openldap/schema/microsoftattributetype.schema include /etc/openldap/schema/microsoftattributetypestd.schema include /etc/openldap/schema/corba.schema include /etc/openldap/schema/core.schema include /etc/openldap/schema/cosine.schema include /etc/openldap/schema/duaconf.schema include /etc/openldap/schema/dyngroup.schema include /etc/openldap/schema/inetorgperson.schema include /etc/openldap/schema/java.schema include /etc/openldap/schema/misc.schema include /etc/openldap/schema/nis.schema include /etc/openldap/schema/openldap.schema include /etc/openldap/schema/ppolicy.schema include /etc/openldap/schema/collective.schema include /etc/openldap/schema/microsoftobjectclass.schema
## Module paths ############################################################## modulepath /usr/local/libexec/openldap moduleload back_meta moduleload back_ldap moduleload back_bdb moduleload mr_passthru moduleload pcache moduleload rwm
# Main settings ############################################################### pidfile /var/run/openldap/slapd.pid argsfile /var/run/openldap/slapd.args
### Database definition (Proxy to AD) ######################################### database meta chase-referrals yes suffix "dc=some,dc=structure" uri "ldap://a.b.c.d:3268/dc=some,dc=structure" readonly yes protocol-version 3 rebind-as-user yes rootdn "CN=zNexus,OU=Service Accounts,OU=myorg,DC=some,DC=structure" rootpw "--obfuscated--"
idassert-bind binddn="CN=zNexus,OU=Service Accounts,OU=myorg,DC=some,DC=structure" credentials="--obfuscated--" bindmethod=simple mode=none idassert-authzFrom "*"
rewriteEngine on #rewrite searches rewriteContext searchFilter rewriteRule "member=(.*)" "(member:1.2.840.113556.1.4.1941:=%1" ":" rewriteRule "memberOf=(.*)" "(memberOf:1.2.840.113556.1.4.1941:=%1" ":"
overlay pcache pcache bdb 100000 2 10000 600 directory /var/tmp/openldap-cache cachesize 20000 pcacheMaxQueries 10000 index objectClass eq,pres index userAccountControl eq index member eq index memberOf eq index ou,cn,mail,surname,givenname eq,pres,sub index objectCategory,sAMAccountName eq,pres,sub
pcacheAttrset 0 cn pcacheTemplate (&(objectClass=)(&(cn=)(member=))) 0 600 60 pcacheTemplate (member=) 0 600 60 pcacheTemplate (memberOf=) 0 600 60 pcacheTemplate (&(cn=*)(member=)) 0 600 60 pcacheTemplate (&(objectClass=)(sAMAccountName=)(&(objectCategory=)(userAccountControl=))) 0 600 60
pcacheAttrset 1 sAMAccountName cn mail labeledUri memberOf member objectClass pcacheTemplate (&(objectClass=)(sAMAccountName=)(&(objectCategory=)(userAccountControl=))) 1 600 60 pcacheTemplate (&(objectClass=)(sAMAccountName=*)(&(objectCategory=)(userAccountControl=))) 1 600 60 -----------------------------
Here is what the client sees the first and second time the query is run for a user that is directly in one group but in many groups via nesting. (The group DNs have been obfuscated but in reality they are all unique.) On the first run, ldapsearch correctly returns 158 total (nested and direct) groups. On the second run, ldapsearch only returns the one direct group.
### RUN 1 ### ldap_initialize( ldap://127.0.0.1 ) filter: (member=cn=Some User,ou=Users,ou=External,dc=some,dc=structure) requesting: cn dn: cn=TT-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: TT-RndGroup-Read
dn: cn=IO-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: IO-RndGroup-Read
dn: cn=Vi-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: Vi-RndGroup-Read
dn: cn=SE-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: SE-RndGroup-Read
<snip 154 more CNs....>
real 0m14.167s user 0m0.003s sys 0m0.025s
### RUN 2 ### ldap_initialize( ldap://127.0.0.1 ) filter: (member=cn=Some User,ou=Users,ou=External,dc=some,dc=structure) requesting: cn dn: cn=Vi-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: Vi-RndGroup-Read
real 0m4.310s user 0m0.000s sys 0m0.004s
-----------------------------
Thanks, Ryan
Ryan Hammond wrote:
We have an Active Directory domain with >6000 users and several hundred groups. The group hierarchy is usually nested 4-5 levels deep. Queries for the full set of nested groups for a user take > 10 seconds each. We have an app (Nexus OSS) that asks for a user's nested groups on every interaction (e.g. for each dependency needed to perform a maven build) and does not perform local caching.
I am trying to implement a slapd + meta + pcache solution that will proxy the LDAP query, cache the results, and significantly speed up user interactions with this app. I have tried many configurations. I can always proxy the request, but I haven't yet been able to fully cache the results. I have had the most success with the passthru module from https://github.com/cbueche/openldap-passthru and rwm. In this configuration, slapd proxies inbound filters like "(member=CN=my name,ou=users,dc=some,dc=structure)" and passes that on to AD as "member:1.2.840.113556.1.4.1941:=CN=my name,ou=userss,dc=some,dc=structure)". AD returns the group DNs but slapd partially caches the result. The cached results are the direct group memberships, not the complete set of nested groups.
Is what I want to do possible? If so, can someone please point me in the right direction?
Without actually investigating anything, I'd guess pcache ignores the returned entries because it doesn't know what your extended match filter means. You'll probably need to write some code to enhance the pcache module to make this work.
Here is what the client sees the first and second time the query is run for a user that is directly in one group but in many groups via nesting. (The group DNs have been obfuscated but in reality they are all unique.) On the first run, ldapsearch correctly returns 158 total (nested and direct) groups. On the second run, ldapsearch only returns the one direct group.
### RUN 1 ### ldap_initialize( ldap://127.0.0.1 http://127.0.0.1 ) filter: (member=cn=Some User,ou=Users,ou=External,dc=some,dc=structure) requesting: cn dn: cn=TT-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: TT-RndGroup-Read
dn: cn=IO-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: IO-RndGroup-Read
dn: cn=Vi-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: Vi-RndGroup-Read
dn: cn=SE-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: SE-RndGroup-Read
<snip 154 more CNs....>
real0m14.167s user0m0.003s sys0m0.025s
### RUN 2 ### ldap_initialize( ldap://127.0.0.1 http://127.0.0.1 ) filter: (member=cn=Some User,ou=Users,ou=External,dc=some,dc=structure) requesting: cn dn: cn=Vi-RndGroup-Read,ou=...,ou=External,dc=some,dc=structure cn: Vi-RndGroup-Read
real0m4.310s user0m0.000s sys0m0.004s
Thanks, Ryan
openldap-technical@openldap.org