Hello,
studying the slapd.access man page left me with an open question regarding the control of object creation:
* How to allow the creation of objects with a specific objectclass only?
For example, I want to prevent that an object with a object class other than 'foobar' is created.
Assumming the following LDIF should be valid for an "add" operation:
dn: uid=anton1,cn=settings,dc=ldap,dc=base objectClass: foobar uid: anton1
And this one to be invalid:
dn: uid=anton1,cn=settings,dc=ldap,dc=base objectClass: CourierMailAccount objectClass: univentionAdminUserSettings uid: anton1 uidNumber: 0 gidNumber: 0
All of the following examples aren't doing their job when *creating* an entry. Most of them (and even more simple ones) work fine when *modifying* an entry:
## 1. a attribute blacklist ## access to dn="cn=settings,dc=ldap,dc=base" attrs="entry,children" by users write by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" filter="objectClass=foobar" attrs=!foobar by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" none by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" filter="objectClass=foobar" attrs=entry,@foobar by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" write by * none ################## → does probably not work because "!foobar" also disallows "objectClass"?
## 2. a negative regex blacklist ## access to dn="cn=settings,dc=ldap,dc=base" attrs="entry,children" by users write by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" attrs=objectClass val.regex="^([^f]|f[^o]|fo[^o]|foo[^b]|foob[^a]|fooba[^r])$" by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" none by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" filter="objectClass=foobar" attrs=entry,@foobar by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" write by * none ##################
## 3. a whitelist ## access to dn="cn=settings,dc=ldap,dc=base" attrs="entry,children" by users write by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" attrs=objectClass value="foobar" by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" write by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" attrs=objectClass by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" none by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=ldap,dc=base$" filter="objectClass=foobar" attrs=entry,@foobar by dn.regex="^uid=$1,.*dc=ldap,dc=base$$" write by * none ##################
* Is the filter="…" in the "to" clause of an ACL evaluated when "adding" an entry?
* Is the filter="…" when modifying an entry also applied against the modified result or only against the current state of the object?
* the manpage says the syntax is "attrs=<attrlist>[ val[/matchingRule][.<attrstyle>]=<attrval>]" → The hardcoded "val" can also be "value"
* no multiple value-lists can be used in a single defintion (e.g. access to attrs="objectClass val=foo" attrs="someAttribute val="bar" or attrs="objectClass val=foo,someAttribute val=bar")
* "matchingRule" is nowhere defined in the manpage
Some further suggestions for the development are:
* It would reduce a lot of redundancy if multiple "to" statements could be used in one ACL definition (so that the different by clauses doesn't always need to be copied).
* If the "by" clause would also have a filter="" one wouldn't need to use "set"s anymore - sets are slower and doesn't even work with all things (e.g. if you have special characters in the DN). There is no way to escape "]" / "[" and urlencode things which are e.g. used in a LDAP URI filter. This can even lead to security issues.
* ACL rules can't be bound to the ldap operation (search, auth, add, modify, delete, ...), you can only remove e.g. some of the permission bits (e.g. access to if-operation="search" ...)
* Using backreferences of the DN in the filter="" or attrs="" would also be very handy (how to restrict e.g. the "uid" value to be only what's in the DN of the target/operating user?)
Best regards Florian
Florian Best wrote:
- How to allow the creation of objects with a specific objectclass only?
http://www.openldap.org/faq/data/cache/1474.html
The FAQ-O-MATIC does not look fancy but contains lots of useful access control examples.
All of the following examples aren't doing their job when *creating* an entry.
You probably need "add_content_acl yes" as mentioned in the FAQ above.
Some further suggestions for the development are:
- It would reduce a lot of redundancy if multiple "to" statements could
be used in one ACL definition (so that the different by clauses doesn't always need to be copied).
Or you could use templating provided with ansible/puppet/saltstack/chef...
- If the "by" clause would also have a filter="" one wouldn't need to
use "set"s anymore - sets are slower and doesn't even work with all things (e.g. if you have special characters in the DN).
Are you aware that you can have hex-escaped bytes in DN string representations?
There is no way to escape "]" / "[" and urlencode things which are e.g. used in a LDAP URI filter. This can even lead to security issues.
Do you have a detailed example?
- ACL rules can't be bound to the ldap operation (search, auth, add,
modify, delete, ...), you can only remove e.g. some of the permission bits (e.g. access to if-operation="search" ...)
Setting the privileges is IMO sufficient.
- Using backreferences of the DN in the filter="" or attrs="" would also
be very handy (how to restrict e.g. the "uid" value to be only what's in the DN of the target/operating user?)
Use set-based constraints. In general slapo-constraint is your fried for constraining attribute values.
Ciao, Michael.
Am Wed, 29 Jun 2016 14:49:12 +0200 schrieb Florian Best best@univention.de:
Hello,
studying the slapd.access man page left me with an open question regarding the control of object creation:
- How to allow the creation of objects with a specific objectclass
only?
For example, I want to prevent that an object with a object class other than 'foobar' is created.
Assumming the following LDIF should be valid for an "add" operation:
dn: uid=anton1,cn=settings,dc=ldap,dc=base objectClass: foobar uid: anton1
man slapd.conf(5) search for - ditcontentrule - add_content_acl
and following access rules:
access to dn.sub=cn=foo,o=bar attrs=entry,@foobar by *
-Dieter
Thank you for this information, Dieter and Michael!
With "add_content_acl on" this works. I now use the following rule:
access to dn.regex="^uid=([^,]+),cn=settings,dc=base$" filter="objectClass=foobar" attrs=objectClass value=foobar by dn.regex="^uid=$1,.*dc=base$$" write by * none access to dn.regex="^uid=([^,]+),cn=settings,dc=base$" filter="objectClass=foobar" attrs=objectClass by dn.regex="^uid=$1,.*dc=base$$" none by * +0 break access to dn.regex="^uid=([^,]+),cn=settings,dc=base$" filter="objectClass=foobar" attrs=entry,@foobar by dn.regex="^uid=$1,.*dc=base$$" write by * none
Using the example below from Dieter would allow to also add other object classes which doesn't conflict with the MUST attributes of 'foobar'.
Best regards Florian
Am 30.06.2016 um 22:14 schrieb Dieter Klünter:
Am Wed, 29 Jun 2016 14:49:12 +0200 schrieb Florian Best best@univention.de:
Hello,
studying the slapd.access man page left me with an open question regarding the control of object creation:
- How to allow the creation of objects with a specific objectclass
only?
For example, I want to prevent that an object with a object class other than 'foobar' is created.
Assumming the following LDIF should be valid for an "add" operation:
dn: uid=anton1,cn=settings,dc=ldap,dc=base objectClass: foobar uid: anton1
man slapd.conf(5) search for
- ditcontentrule
- add_content_acl
and following access rules:
access to dn.sub=cn=foo,o=bar attrs=entry,@foobar by *
-Dieter
Hello Michael,
Am 30.06.2016 um 11:29 schrieb Michael Ströder:
- ACL rules can't be bound to the ldap operation (search, auth, add,
modify, delete, ...), you can only remove e.g. some of the permission bits (e.g. access to if-operation="search" ...)
Setting the privileges is IMO sufficient.
I see this differently. One example where this is useful would be the following: I would like to e.g. add a rule at the very top of all ACL definitions:
"access to attrs=uidNumber value=0 by * none stop"
But this prevents that any other rule afterwards can make it *readable*.
Having something like:
"access to attrs=uidNumber value=0 if-operation="write,manage" by * none stop"
would solve this problem.
Best regards Florian
Florian Best wrote:
Am 30.06.2016 um 11:29 schrieb Michael Ströder:
Setting the privileges is IMO sufficient.
I see this differently. One example where this is useful would be the following:
Maybe I do not fully understand your aim but...
I would like to e.g. add a rule at the very top of all ACL definitions:
"access to attrs=uidNumber value=0 by * none stop"
But this prevents that any other rule afterwards can make it *readable*.
...then don't do this. ;-)
Seriously: <who> clauses are also ordered. Simply use several of them in access directive(s) with one passing control flow with "break".
Ciao, Michael.
openldap-technical@openldap.org