At slapd.access we read (about the control keywords):
One useful application is to easily grant write privileges to an updatedn that is different from the rootdn. In this case, since the updatedn needs write access to (almost) all data, one can use access to * by dn.exact="cn=The Update DN,dc=example,dc=com" write by * break as the first access rule. As a consequence, unless the operation is performed with the updatedn identity, control is passed straight to the subsequent rules.
I have the following question. If below the above ACL we add another ACL like:
access to dn.subtree="ou=people,dc=example,dc=com" by dn.exact="cn=Some Other DN,dc=example,dc=com" by * none
...doesn't this mean that the second ACL will override the first, so that "The Update DN" will no longer have access to the whole DIT (as was intended), since, based on the second ACL, "The Update DN"does not have access to "ou=people" branch? If this is the case, then the first ACL is not enough, but care must be taken to avoid any privilege revocation(s) from "The Update DN", by following ACLs.
Or the existence of the former rule means that access has been *definitively decided* for "The Update DN" (i.e. "by" clause match(es) in the first ACL) and any subsequent access statements (later ACLs) can affect *ONLY* other users (i.e. whatever "by" clause matches, *except* "The Update DN")?? This is what I understand from the statement "As a consequence, unless the operation is performed with the updatedn identity, control is passed straight to the subsequent rules."
Can you please clarify which is the case?
Thanks, Nick
On Fri, May 25, 2012 at 12:38:09PM +0300, Nick Milas wrote:
One useful application is to easily grant write privileges to an updatedn that is different from the rootdn. In this case, since the updatedn needs write access to (almost) all data, one can use access to * by dn.exact="cn=The Update DN,dc=example,dc=com" write by * break as the first access rule. As a consequence, unless the operation is performed with the updatedn identity, control is passed straight to the subsequent rules.
I have the following question. If below the above ACL we add another ACL like:
access to dn.subtree="ou=people,dc=example,dc=com" by dn.exact="cn=Some Other DN,dc=example,dc=com" by * none
...doesn't this mean that the second ACL will override the first, so that "The Update DN" will no longer have access to the whole DIT (as
No. From slapd.access(5): Access control checking stops at the first match of the <what> and <who> clause, unless otherwise dictated by the <control> clause.
In the example above, the first access statement does not have a <control> clause for dn.exact="cn=The Update DN,dc=example,dc=com" so it uses the default, which is 'stop'.
Note that your second access statement does not specify any particular access for dn.exact="cn=Some Other DN,dc=example,dc=com" so it won't be much use.
Andrew
On 25/5/2012 2:37 μμ, Andrew Findlay wrote:
In the example above, the first access statement does not have a <control> clause for dn.exact="cn=The Update DN,dc=example,dc=com" so it uses the default, which is 'stop'.
Fine. Thank you Andrew, I see. Control clauses are on a per-<who>-clause basis.
Note that your second access statement does not specify any particular access for dn.exact="cn=Some Other DN,dc=example,dc=com" so it won't be much use.
OK, it was just an example. I now see it was incomplete; sorry for the confusion. At least I made my thinking clear enough.
It should have been:
access to dn.subtree="ou=people,dc=example,dc=com" by dn.exact="cn=Some Other DN,dc=example,dc=com" write by * none
Thanks, Nick
On 25/5/2012 2:37 μμ, Andrew Findlay wrote:
No. From slapd.access(5): Access control checking stops at the first match of the <what> and<who> clause, unless otherwise dictated by the <control> clause.
In the example above, the first access statement does not have a <control> clause for dn.exact="cn=The Update DN,dc=example,dc=com" so it uses the default, which is 'stop'.
By the way, let me also ask:
Why when assigning access rights to "entry" and/or "children" attributes, in most cases - as I have seen from experience - we have to end with a "by * break" clause?
access to dn.subtree="ou=people,dc=example,dc=com" attrs=children,entry by dn.exact="uid=admin,ou=people,dc=example,dc=com" write by * break
The assignment of privileges to children and/or entry attributes on some branch, could cause problems if we terminate (and implicitly don't allow the evaluation of other access statements on this what/attrs combination)?
I tend to think that this is needed in case(s) where we want to be able to assign different privileges (for children/entry attributes) in subordinate branches, using ACLs following later. But if we follow the rule: "special access rules first, generic access rules last", i.e. if we place our ACLs for entry/children of the bottom branches first in the ACL sequence, then a "by * break" clause would not be required. Is my thinking right?
And a second question:
Are there any cases where access to "children" and "entry" attributes is determined implicitly, or in all cases (except, I guess, when we specify "access to *") we should declare access rights to these attributes explicitly?
Thanks, Nick
On Fri, 25 May 2012, Nick Milas wrote:
Why when assigning access rights to "entry" and/or "children" attributes, in most cases - as I have seen from experience - we have to end with a "by * break" clause?
Because that's a popular style of ACL processing logic to use for those attributes. As you note, this is done in "most cases", i.e., not all, so obviously there nothing in the software that requires it.
I'm not sure why the ACLs for entry and children that you tend to see use that style, but if I recall correctly, they weren't part of the original ACL design but rather were added in OpenLDAP 2.2 (or maybe 2.3?), so this may be the result of ACL sets being retrofitted during upgrades.
...
I tend to think that this is needed in case(s) where we want to be able to assign different privileges (for children/entry attributes) in subordinate branches, using ACLs following later. But if we follow the rule: "special access rules first, generic access rules last", i.e. if we place our ACLs for entry/children of the bottom branches first in the ACL sequence, then a "by * break" clause would not be required. Is my thinking right?
Yes, though you should review any rules without an attrs= clause carefully to check whether they're setting the rights for the children/entry pseudo-attributes unexpectedly.
And a second question:
Are there any cases where access to "children" and "entry" attributes is determined implicitly, or in all cases (except, I guess, when we specify "access to *") we should declare access rights to these attributes explicitly?
I'm not sure what you mean by "determined implicitly" here, so I can't answer that.
Philip
On 25/5/2012 6:44 μμ, Philip Guenther wrote:
Because that's a popular style of ACL processing logic to use for those attributes. As you note, this is done in "most cases", i.e., not all, so obviously there nothing in the software that requires it.
I'm not sure why the ACLs for entry and children that you tend to see use that style, but if I recall correctly, they weren't part of the original ACL design but rather were added in OpenLDAP 2.2 (or maybe 2.3?), so this may be the result of ACL sets being retrofitted during upgrades.
Thank you Philip, I hope someone can provide some more information on why "that's a popular style of ACL processing logic to use for those attributes." (i.e. entry and children pseudo-attrs).
I am wondering: if there is (or there was) nothing in the software that requires (required) it, why such a style has developed?
Yes, though you should review any rules without an attrs= clause carefully to check whether they're setting the rights for the children/entry pseudo-attributes unexpectedly.
You mean that if we use a <what> statement without an "attrs=" clause, then it affects children and entry pseudo-attributes as well? And what if there is a filter specified too (still without an "attrs=" clause)?
I'm not sure what you mean by "determined implicitly" here, so I can't answer that.
What I meant was exactly that (see above): if e.g. we use a <what> statement without an "attrs=" clause, then it affects children and entry pseudo-attributes as well?
Thanks, Nick
On 25/5/2012 6:59 μμ, Nick Milas wrote:
You mean that if we use a <what> statement without an "attrs=" clause, then it affects children and entry pseudo-attributes as well? And what if there is a filter specified too (still without an "attrs=" clause)?
From some research I did (e.g.: http://www.openldap.org/faq/data/cache/1140.html), I don't see cases of implicit change (meant as described above) of entry and children pseudo-attributes.
In case we would like an ACL statement to include all attributes *plus* the pseudo-attributes, then we should explicitly specify, for example:
access to dn.subtree="ou=people,dc=example,dc=com" attrs="@extensibleObject,children,entry" by dn.exact="uid=admin,ou=people,dc=example,dc=com" write ...
If anyone has more details on this, I would appreciate your feecback.
Regards, Nick
On Sat, 26 May 2012, Nick Milas wrote:
On 25/5/2012 6:59 ??, Nick Milas wrote:
You mean that if we use a <what> statement without an "attrs=" clause, then it affects children and entry pseudo-attributes as well? And what if there is a filter specified too (still without an "attrs=" clause)?
From some research I did (e.g.: http://www.openldap.org/faq/data/cache/1140.html), I don't see cases of implicit change (meant as described above) of entry and children pseudo-attributes.
You didn't see the last example on that page? ---- access to dn.onelevel="dc=example,dc=com" by dnattr=creatorsName write by * read ----
No attrs clause, and yet for the behavior described there to work it must be giving access to the 'entry' pseudo-attr.
In case we would like an ACL statement to include all attributes *plus* the pseudo-attributes, then we should explicitly specify, for example:
access to dn.subtree="ou=people,dc=example,dc=com" attrs="@extensibleObject,children,entry" by dn.exact="uid=admin,ou=people,dc=example,dc=com" write ...
@extensibleObject covers *EVERYTHING*, including the pseudo-attrs entry and children.
If anyone has more details on this, I would appreciate your feecback.
Let's do something *crazy*: let's *actually try it*!
I added the following two acls to an existing server ----- # Just needed so I can add dc=testing... access to dn.exact="" attrs=children by dn.exact="mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com" write
access to dn.sub="dc=testing" by dn.exact="mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com" write -----
This server had no dc=testing tree at this point. With those ACLs present, I was then able to bind as the indicated user and create a dc=testing entry and an entry below it:
$ ldapadd -D mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com -w foobar dn: dc=testing changetype: add objectclass: domain dc: testing
adding new entry "dc=testing"
dn: ou=foo,dc=testing objectClass: organizationalUnit ou: foo
adding new entry "ou=foo,dc=testing"
$
So, no attrs clause on the second ACL but I was able to create entries covered by it.
I then replaced those two ACLs with this single one: ----- access to dn.sub="dc=testing" attrs="objectclass,ou,entry" by dn.exact="mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com" write -----
I.e., the ACL no longer gives write access to the 'children' pseudo-attribute.
Adding an entry then fails:
$ ldapadd -D mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com -w foobar dn: ou=baz,dc=testing objectClass: organizationalUnit ou: baz
adding new entry "ou=baz,dc=testing" ldap_add: Insufficient access (50) additional info: no write access to parent
$
I then updated that ACL to include children: ----- access to dn.sub="dc=testing" attrs="objectclass,ou,entry,children" by dn.exact="mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com" write -----
...and now the same add succeeds:
$ ldapadd -D mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com -w foobar dn: ou=baz,dc=testing objectClass: organizationalUnit ou: baz
adding new entry "ou=baz,dc=testing"
$
Those two tests together show that the server is indeed checking for the 'children' attr, so it's not that it just wasn't looking.
Finally, let's try using attrs="@extensibleObject" (I only mention it because that's what the *documention* says is the default.) ----- access to dn.sub="dc=testing" attrs="@extensibleObject" by dn.exact="mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com" write -----
$ ldapadd -D mailRoutingAddress=foo@foo.com,ou=People,dc=foo,dc=com -w foobar dn: ou=quux,dc=testing objectClass: organizationalUnit ou: quux
adding new entry "ou=quux,dc=testing"
$
So @extensibleObject clearly must cover 'children'.
I suggest you set up a similar test environment and play around with some ACLs on a real system. Less theory and more practice will lead to faster results. For example, you could set up an ACL with a filter clause and answer your own question about whether that affects the attrs matched.
Philip
On 27/5/2012 6:33 πμ, Philip Guenther wrote:
@extensibleObject covers*EVERYTHING*, including the pseudo-attrs entry and children.
Then, the first example at: http://www.openldap.org/faq/data/cache/1140.html is a bit deceptive, or it just aims in emphasizing the entry pseudo-attr, by specifying it explicitly (along with @extensibleObject), when there was no need to.
You didn't see the last example on that page? ... No attrs clause, and yet for the behavior described there to work it must be giving access to the 'entry' pseudo-attr.
True, but one could think that the example here empasizes (because this is what it discusses) the assignment of write privileges and is incomplete with regard to the assignment of read privileges.
Let's do something*crazy*: let's*actually try it*!
Ha, ha! Thanks Philip. You were great! I was just too lazy! (Too busy as well, or hoping someone would know and clarify things so we would avoid testing thoroughly.)
So there is a risk of "implicit" inadvertent changes!
To summarize your findings:
attrs="@extensibleObject" EQ attrs="@extensibleObject,entry,children" EQ NO attrs= clause
I suggest you set up a similar test environment and play around with some ACLs on a real system. Less theory and more practice will lead to faster results. For example, you could set up an ACL with a filter clause and answer your own question about whether that affects the attrs matched.
OK, I'll do it.
Nick
On 27/5/2012 10:25 μμ, Nick Milas wrote:
For example, you could set up an ACL with a filter clause and answer your own question about whether that affects the attrs matched.
OK, I'll do it.
I owe an answer on this; I have done the required research and found that if we use an ACL of the form:
access to <dn>.<scope> filter=<some filter>
(i.e. without "attrs=" clause), then it DOES include entry, children pseudo-attributes, for all matching entries (according to filter).
For example, we could use a statement like (devised to illustrate the case):
acces to dn.subtree="ou=TestBranch,dc=example,dc=com" filter="(|(objectClass=organizationalUnit)(someattr=*))" by dn.exact="uid=usr,ou=people,dc=example,dc=com" read by group.exact="cn=Admins,ou=Groups,dc=example,dc=com" write by * none
to assign privileges to all attrs (including entry, children) of the parent entry (which has objectClass=organizationalUnit) and of all entries having a "someattr" attribute.
A useful tool to display access rights is slapacl. For example, we could use:
slapacl -b "ou=TestBranch,dc=example,dc=com" -D "uid=usr,ou=people,dc=example,dc=com"
to view in detail the access rights to each and every attribute of that particular entry by that particular user DN.
Nick
openldap-technical@openldap.org