Dear OpenLDAP technical list,
I‘ve been running into a little problem with my permission structures – and was wondering if you could help me with it.
I want the members of a group to administer a tree structure, the group is member of it. I've tried some acl settings – I'll post my trials below the basic structure. Basic structure
The structure is somehow like that tree – behind an # symbol, there is a brief description what the entries are meant for.
dc=example,dc=com │ ├── cn=admin # OpenLDAP default admin user │ ├── ou=entities # organisational entities │ │
│ ├── o=e1 # first of these entities │ │ │ │ │ ├── cn=admin # groupOfNames – see bullet points below │ │ │ ┆ │ │ │ └ ┄▸ member: cn=admin,dc=example,dc=com │ │ │ └ ┄▸ member: uid=j.doe,ou=people,dc=example,dc=com │ │ │ │ │ ├── cn=role1 # groupOfNames to be reused below │ │ │ ┆ as recursive group members within │ │ │ ┆ permission groups │ │ │ ┆ │ │ │ └ ┄▸ member: cn=admin,o=e1,ou=entities,dc=example,dc=com │ │ │ │ │ └── cn=role2 │ │ ┆ │ │ └ ┄▸ member: cn=admin,o=e1,ou=entities,dc=example,dc=com │ │ │ └── o=e2 │ ├── cn=admin │ ├── cn=role1 │ └── cn=role2 │ ├── ou=groups # permission groups for applications │ │ that authenticate against OpenLDAP │ │ │ ├── cn=globaladmins # groupOfNames – superusers in all applications │ │ ┆ │ │ └ ┄▸ member: cn=admin,dc=example,dc=com │ │ │ ├── cn=ldapadmins # groupOfNames – same rights as admin user │ │ ┆ │ │ └ ┄▸ member: cn=globaladmins,ou=groups,dc=example,dc=com │ │ └ ┄▸ member: uid=l.dap,ou=people,dc=example,dc=com │ │ │ ├── cn=permissiongroup1 # groupOfNames – authentication group │ │ ┆ for specific application │ │ ┆ │ │ └ ┄▸ member: cn=globaladmins,ou=groups,dc=example,dc=com │ │ └ ┄▸ member: cn=role1,o=e1,ou=entities,dc=example,dc=com │ │ └ ┄▸ member: cn=role1,o=e2,ou=entities,dc=example,dc=com │ │ │ └── cn=permissiongroup2 │ ┆ │ └ ┄▸ member: cn=globaladmins,ou=groups,dc=example,dc=com │ └ ┄▸ member: cn=role2,o=e1,ou=entities,dc=example,dc=com │ └ ┄▸ member: cn=role2,o=e2,ou=entities,dc=example,dc=com │ └── ou=people # finally the "real people" accounts │ ├── uid=j.doe ├── uid=l.dap └── uid=m.muster
cn=admin,dc=example,dc=com is basic member of the admin groups (since every group needs at least one member). uid=l.dap,ou=people,dc=example,dc=com is member of the cn=ldapadmins,ou=groups,dc=example,dc=com group. Therefor every member should have same rights within LDAP structure as cn=admin,dc=example,dc=com ou=people is the only structure, (personal) accounts are maintained ou=groups is the only structure, authentication groups for (web)applications are maintained (with nested members)
The cn=admin,o=e1,ou=entities,dc=example,dc=com DN members should be able to admin everything below o=e1,ou=entities,dc=example,dc=com. e1 should be dynamic. The entity admins should not be able to administer other entities than the ones, they are admins from. Permission LDIF
I've tried some different things ... and none Regex was successful :( Since I'll post some fragments, I put every LDIF fragment within such a bash fragment:
touch /permissions.ldif
cat >/permissions.ldif <<EOF # first of all delete all permissions dn: olcDatabase={1}mdb,cn=config changetype: modify delete: olcAccess
######## ## LDIF blocks from below ########
# add general permissions add: olcAccess olcAccess: to * by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none EOF
ldapmodify -Q -Y EXTERNAL -H ldapi:/// ldapi:/// -f /permissions.ldif
trial 1
# add administrative access to LVe admin subgroups add: olcAccess olcAccess: to dn.regex="([^,]+,)?o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=$2,ou=entities,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The result is, that admin and any member of ldapadminscan edit, the members of specific entity admin subgroups cannot edit. The specific admin subgroups cannot even see the entities subtree. trial 2
# add administrative access to LVe admin subgroups add: olcAccess olcAccess: to dn.regex="o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=$1,ou=entities,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The same result as with trial 1 ... trial 3
Additional groups – as a tree:
dc=example,dc=com ┆ └── ou=entity_admins │ ├── cn=e1 │ ┆ │ └ ┄▸ member: cn=admin,o=e1,ou=entities,dc=example,dc=com │ └── cn=e2
And the LDIF:
# add administrative access to LVe admin subgroups add: olcAccess olcAccess: to dn.regex="o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=$1,ou=entity_admins,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The result is again: admin and any member of ldapadminscan edit, entity_admins subgroups user cannot edit – even not their "owned" entities. trial 4
If I put an by set="[cn=admin,o=e1,ou=entities,dc=example,dc=com]/member* & user" write for EVERY single olcAccess: to dn.regex="([^,]+,)?o=jpbay,ou=entities,dc=example,dc=com" (with all the other stuff from trial 1), everything works fine. BUT: that's not maintainable or dynamic. So that's no solution, I can accept. I do not know why set.expand doesn't work as expected (as explained within different online examples on openldap.com http://openldap.com/) – and was not able to find a proper documentation that could explain why. Or if there has to be some enablement of an OpenLDAP module? If you could support me with that problem – probably with a solution – it would be great =) Thanks a lot, Martin
On Tue, Aug 20, 2019 at 10:22:56PM +0200, Martin W. wrote:
Dear OpenLDAP technical list,
I‘ve been running into a little problem with my permission structures – and was wondering if you could help me with it.
I want the members of a group to administer a tree structure, the group is member of it. I've tried some acl settings – I'll post my trials below the basic structure.
I've tried some different things ... and none Regex was successful :( Since I'll post some fragments, I put every LDIF fragment within such a bash fragment:
olcAccess: to * by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none
trial 1
olcAccess: to dn.regex="([^,]+,)?o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=$2,ou=entities,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The result is, that admin and any member of ldapadminscan edit, the members of specific entity admin subgroups cannot edit. The specific admin subgroups cannot even see the entities subtree.
Hi Martin, what is the order of the above two olcAccess statements? If they apply in the order above, it seems the first one will always apply and processing will stop there. In that case you either want to add a "break" in the first one or split/move it to be checked later.
I assume you also know and use the slapacl tool (and loglevel acl) to test with? Does it show any additional information that might be helpful in diagnosing the issue?
Regards,
Am Wed, 21 Aug 2019 10:50:19 +0200 schrieb Ondřej Kuzník ondra@mistotebe.net:
On Tue, Aug 20, 2019 at 10:22:56PM +0200, Martin W. wrote:
Dear OpenLDAP technical list,
I‘ve been running into a little problem with my permission structures – and was wondering if you could help me with it.
I want the members of a group to administer a tree structure, the group is member of it. I've tried some acl settings – I'll post my trials below the basic structure.
I've tried some different things ... and none Regex was successful :( Since I'll post some fragments, I put every LDIF fragment within such a bash fragment:
olcAccess: to * by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none
trial 1
olcAccess: to dn.regex="([^,]+,)?o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=$2,ou=entities,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The result is, that admin and any member of ldapadminscan edit, the members of specific entity admin subgroups cannot edit. The specific admin subgroups cannot even see the entities subtree.
Hi Martin, what is the order of the above two olcAccess statements? If they apply in the order above, it seems the first one will always apply and processing will stop there. In that case you either want to add a "break" in the first one or split/move it to be checked later.
I assume you also know and use the slapacl tool (and loglevel acl) to test with? Does it show any additional information that might be helpful in diagnosing the issue?
With regard to 'set' here is some basic information. http://www.openldap.org/faq/data/cache/1133.html http://www.openldap.org/faq/data/cache/1134.html
-Dieter
Hi Ondřej, Hi Dieter,
Thanks for your replies! The basic links I've had already found and read through carefully and didn't find a correct solution for my problem =(
The olcAccess statements out of the trials were all placed in front of the asterisk * one. So the order should not be the problem =(
Within the little bash script, the LDIF-parts from the different trials are always replacing this block:
######## ## LDIF blocks from below ########
With slapacl I don’t really get a clue – I’ll attach one result below, that I would interpret like that my l.dap user is not allowed to change the description of entity e1 … but if I use JXplorer to connect to the directory as l.dap, I can – even submit. Is it wrong how I’m using slapacl? Or isn’t it reliable since I’m using RegEx?
Thank you for your help! Cheers, Martin
$ slapacl -v -U "uid=l.dap,ou=people,dc=example,dc=com" -b "o=e1,ou=entities,dc=example,dc=com" -d acl "description/write"
5d5db13a => access_allowed: search access to "cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn=module{0},cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={0}core,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={1}cosine,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={2}nis,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={3}inetorgperson,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={4}ppolicy,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={5}dhcp,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={6}dnszone,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={7}mail,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={8}mmc,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={9}openssh-lpk,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={10}quota,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={11}radius,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={12}samba,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "cn={13}zarafa,cn=schema,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "olcBackend={0}mdb,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "olcDatabase={-1}frontend,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) Backend ACL: access to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by * +0 break
Backend ACL: access to dn.base="" by * read
Backend ACL: access to dn.base="cn=subschema" by * read
5d5db13a => access_allowed: search access to "olcDatabase={0}config,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) Backend ACL: access to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by * +0 break
5d5db13a /etc/ldap/slapd.d: line 1: warning: cannot assess the validity of the ACL scope within backend naming context 5d5db13a => access_allowed: search access to "olcDatabase={1}mdb,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) Backend ACL: access to attrs=userPassword,shadowLastChange by self =wx by dn.base="cn=admin,dc=example,dc=com" =wx by set.exact="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" =wx by anonymous auth by * none
5d5db13a /etc/ldap/slapd.d: line 1: warning: cannot assess the validity of the ACL scope within backend naming context Backend ACL: access to * by self write by dn.base="cn=admin,dc=example,dc=com" write by set.exact="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none
5d5db13a /etc/ldap/slapd.d: line 1: warning: cannot assess the validity of the ACL scope within backend naming context Backend ACL: access to dn.regex="([^,]+,)?o=([^,]+),ou=lve,dc=example,dc=com" by self write by dn.base="cn=admin,dc=example,dc=com" write by set.exact="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=,ou=lve,dc=example,dc=com]/member* & user" write by set.exact="this/member* & user" read by * none
5d5db13a => access_allowed: search access to "olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) 5d5db13a => access_allowed: search access to "olcOverlay={1}refint,olcDatabase={1}mdb,cn=config" "objectClass" requested 5d5db13a <= root access granted 5d5db13a => access_allowed: search access granted by manage(=mwrscxd) Backend ACL: access to * by * none
5d5db13a config_back_db_open: line 0: warning: cannot assess the validity of the ACL scope within backend naming context authcDN: "uid=uid\3Dl.dap\2Cou\3Dpeople\2Cdc\3dexample\2Cdc\3Dcom,cn=auth" 5d5db13a => access_allowed: write access to "o=jpbay,ou=lve,dc=example,dc=com" "description" requested 5d5db13a => acl_get: [2] attr description 5d5db13a => acl_mask: access to entry "o=jpbay,ou=lve,dc=example,dc=com", attr "description" requested 5d5db13a => acl_mask: to all values by "uid=uid\3Dl.dap\2Cou\3Dpeople\2Cdc\3dexample\2Cdc\3Dcom,cn=auth", (=0) 5d5db13a <= check a_dn_pat: self 5d5db13a <= check a_dn_pat: cn=admin,dc=example,dc=com 5d5db13a <= check a_set_pat: [cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user 5d5db13a => mdb_entry_get: found entry: "cn=ldapadmins,ou=groups,dc=example,dc=com" 5d5db13a ACL set[0]=cn=globaladmins,ou=groups,dc=example,dc=com 5d5db13a => mdb_entry_get: found entry: "cn=globaladmins,ou=groups,dc=example,dc=com" 5d5db13a ACL set[0]=cn=globaladmins,ou=groups,dc=example,dc=com 5d5db13a ACL set[1]=cn=admin,dc=example,dc=com 5d5db13a ACL set[2]=uid=l.dap,ou=people,dc=example,dc=com 5d5db13a => mdb_entry_get: found entry: "cn=admin,dc=example,dc=com" 5d5db13a <= mdb_entry_get: failed to find attribute member 5d5db13a => mdb_entry_get: found entry: "uid=l.dap,ou=people,dc=example,dc=com" 5d5db13a <= mdb_entry_get: failed to find attribute member 5d5db13a ACL set: empty 5d5db13a <= check a_dn_pat: users 5d5db13a <= acl_mask: [4] applying read(=rscxd) (stop) 5d5db13a <= acl_mask: [4] mask: read(=rscxd) 5d5db13a => slap_access_allowed: write access denied by read(=rscxd) 5d5db13a => access_allowed: no more rules write access to description: DENIED
On 21. Aug 2019, at 19:14, Dieter Klünter dieter@dkluenter.de wrote:
Am Wed, 21 Aug 2019 10:50:19 +0200 schrieb Ondřej Kuzník <ondra@mistotebe.net mailto:ondra@mistotebe.net>:
On Tue, Aug 20, 2019 at 10:22:56PM +0200, Martin W. wrote:
Dear OpenLDAP technical list,
I‘ve been running into a little problem with my permission structures – and was wondering if you could help me with it.
I want the members of a group to administer a tree structure, the group is member of it. I've tried some acl settings – I'll post my trials below the basic structure.
I've tried some different things ... and none Regex was successful :( Since I'll post some fragments, I put every LDIF fragment within such a bash fragment:
olcAccess: to * by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none
trial 1
olcAccess: to dn.regex="([^,]+,)?o=([^,]+),ou=entities,dc=example,dc=com" by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by set.expand="[cn=admin,o=$2,ou=entities,dc=example,dc=com]/member* & user" write by set="this/member* & user" read by * none
The result is, that admin and any member of ldapadminscan edit, the members of specific entity admin subgroups cannot edit. The specific admin subgroups cannot even see the entities subtree.
Hi Martin, what is the order of the above two olcAccess statements? If they apply in the order above, it seems the first one will always apply and processing will stop there. In that case you either want to add a "break" in the first one or split/move it to be checked later.
I assume you also know and use the slapacl tool (and loglevel acl) to test with? Does it show any additional information that might be helpful in diagnosing the issue?
With regard to 'set' here is some basic information. http://www.openldap.org/faq/data/cache/1133.html http://www.openldap.org/faq/data/cache/1133.html http://www.openldap.org/faq/data/cache/1134.html http://www.openldap.org/faq/data/cache/1134.html
-Dieter
-- Dieter Klünter | Systemberatung http://sys4.de http://sys4.de/ GPG Key ID: E9ED159B 53°37'09,95"N 10°08'02,42"E
On Thu, Aug 22, 2019 at 09:10:24AM +0200, Martin W. wrote:
Hi Ondřej, Hi Dieter,
Thanks for your replies! The basic links I've had already found and read through carefully and didn't find a correct solution for my problem =(
The olcAccess statements out of the trials were all placed in front of the asterisk * one. So the order should not be the problem =(
Hi Martin, there are several olcAccess clauses (olcAccess attribute values) with several directives each.
With slapacl I don’t really get a clue – I’ll attach one result below, that I would interpret like that my l.dap user is not allowed to change the description of entity e1 … but if I use JXplorer to connect to the directory as l.dap, I can – even submit. Is it wrong how I’m using slapacl? Or isn’t it reliable since I’m using RegEx?
$ slapacl -v -U "uid=l.dap,ou=people,dc=example,dc=com" -b "o=e1,ou=entities,dc=example,dc=com" -d acl "description/write"
This is the relevant snippet from the output:
authcDN: "uid=uid\3Dl.dap\2Cou\3Dpeople\2Cdc\3dexample\2Cdc\3Dcom,cn=auth" 5d5db13a => access_allowed: write access to "o=jpbay,ou=lve,dc=example,dc=com" "description" requested 5d5db13a => acl_get: [2] attr description 5d5db13a => acl_mask: access to entry "o=jpbay,ou=lve,dc=example,dc=com", attr "description" requested 5d5db13a => acl_mask: to all values by "uid=uid\3Dl.dap\2Cou\3Dpeople\2Cdc\3dexample\2Cdc\3Dcom,cn=auth", (=0) 5d5db13a <= check a_dn_pat: self 5d5db13a <= check a_dn_pat: cn=admin,dc=example,dc=com 5d5db13a <= check a_set_pat: [cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user 5d5db13a => mdb_entry_get: found entry: "cn=ldapadmins,ou=groups,dc=example,dc=com" 5d5db13a ACL set[0]=cn=globaladmins,ou=groups,dc=example,dc=com 5d5db13a => mdb_entry_get: found entry: "cn=globaladmins,ou=groups,dc=example,dc=com" 5d5db13a ACL set[0]=cn=globaladmins,ou=groups,dc=example,dc=com 5d5db13a ACL set[1]=cn=admin,dc=example,dc=com 5d5db13a ACL set[2]=uid=l.dap,ou=people,dc=example,dc=com 5d5db13a => mdb_entry_get: found entry: "cn=admin,dc=example,dc=com" 5d5db13a <= mdb_entry_get: failed to find attribute member 5d5db13a => mdb_entry_get: found entry: "uid=l.dap,ou=people,dc=example,dc=com" 5d5db13a <= mdb_entry_get: failed to find attribute member 5d5db13a ACL set: empty 5d5db13a <= check a_dn_pat: users 5d5db13a <= acl_mask: [4] applying read(=rscxd) (stop) 5d5db13a <= acl_mask: [4] mask: read(=rscxd) 5d5db13a => slap_access_allowed: write access denied by read(=rscxd) 5d5db13a => access_allowed: no more rules write access to description: DENIED
Which seems to correspond to your first olcAccess clause only:
olcAccess: to * by self write by dn="cn=admin,dc=example,dc=com" write by set="[cn=ldapadmins,ou=groups,dc=example,dc=com]/member* & user" write by users read by * none
It shows that "by users read" matches and processing stops. If you want processing to continue past this clause, you will either have to reorganise the structure and ordering of your rules or (to get you started for now) use "break" at the end of certain directives (most likely the last two: "by users read" and "by * none").
Hopefully with this and man slapd.access in mind, you should be able to find a way to describe what you need.
With more complex ACLs, it is also useful to maintain a test suite using slapacl or sample DBs so you can refactor them with confidence later.
Regards,
openldap-technical@openldap.org