[Date Prev][Date Next] [Chronological] [Thread] [Top]

Dynamic ACL in OpenLDAP with set:expand not working



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:/// -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) – 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