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

Implementing object-based access control

I've finished the first cut at adding support for "access control info" (aci)
attributes to any object. ACI attributes are used to control access (duh) to an
individual object and its attributes. These attributes are multi-valued, which
allows an unlimited number of different levels of access on an object-by-object

Configuration happens in three places:

1) your schema needs to be changed to ALLOW attributes of type "aci". I did this
in my setup via the slapd.oc.conf file, and just added the aci attribute to a few
object classes (person, groupOfNames, etc.) Eventually this attribute type will
need to be made user-mod operational, but I have not done that part yet.

2) you need to "turn on" acis for attributes via the ACL mechanism.  I did this
in my slapd.conf file, like this:

    access to * by aci write

The basic format is: access to <what> by aci <right>. The <what> part is the
usual stuff, just like any access clause. The <right> part specifies the highest
right that an aci can grant. What this clause says is that when someone accesses
the specified <what>, slapd should check the object's aci attribute to see if
access is granted. In any case, the aci cannot grant rights greater than the
specified <right>.

So effectively, the setting I used above will turn on aci's for everything, and
allow aci's to completely describe access to a given object without limitation.
You can use the ACL stuff to restrict where and how aci's are used.  And of
course if there are no "by aci" clauses, the aci mechanism never comes into
effect (this is nice default behavior for existing servers, I think).

3) the most important thing, of course, is to add aci attributes to any objects
that you want to control access to via this mechanism. The format of an aci
attribute is taken from "draft-ietf-ldapext-acl-model-03.txt". As that document
states, "It is inappropriate to use Internet-Drafts as reference material."
Yah, whatever.

          < aci > ::= < acl syntax >
          < acl syntax > ::= <familyOID> + '#' + <scope > + '#'
                             + < rights >  + '#' + < dnType >
                             + '#' + < subjectDn >
          < subjectDn > ::= < printable string >
          < familyOid > ::= < oid >
          < scope > ::= "entry" | "subtree" | <level>
          < level > ::= numericstring
          < dnType > ::= "access-id" | "role" | "group" | "self"
          < rights > ::= [  ]   |   [ < right > + [ '$'
                         + <right> ] * ]
          < right > ::= <action > + ';' + <permissions>
                        + ';' +  <attrs>
          < action > ::= "grant" | "deny"
          < permissions > ::= [  ]  |   [ < permission >
                              + [ ',' + <permission> ] *  ]
          < attrs > ::= [ < attributeString>
                         + [ ',' + < attributeString > ] * ]
          < attributeString > ::= "[all]" | "[entry]"
                                  | <printableString >
          < permission > ::= "r" | "s" | "w" | "c"

Note that in the draft document, the "s" permission is defined as "set", but then
all the examples define "s" to mean "search". I chose to go with the latter
definition, for better or worse, since slapd does not know "set" rights.

For the most part, aci's work as described in draft-ietf-ldapext-acl-model-03.txt.
There are a few exceptions, described below, that I'd like some comments on.

I'm ignoring the familyOID, since none have been defined yet.

I've modified the syntax in a compatible manner by allowing the <subjectDN> of a
group or role to specify the objectClass and attribute name of the target object.
This is similar to the "group" <who> in a traditional ACL. The defaults for a
group dnType are "groupOfNames" and "member". The defaults for a role dnType are
"organizationalRole" and "roleOccupant". The group and role dnTypes support
wildcarding in <subjectDN>, same as the group <who> in an ACL.

I've added a dnType of "self", which gives a shorthand way of saying "access-id
equals object's DN." In this case, the <subjectDN> field is ignored. This kind
of shorthand is good for usability reasons, other than that it does not add any

The "subtree" and <level> scopes are not currently supported, although I think
aci inheritance is a very important feature to include. The reason I did not
implement this in my first go-around is that getting a "raw" entry from a backend
is not exactly straight-forward. I'd need to do this in order to walk up (or
down) the tree. If anyone has recommendations on how to do this, let me know.
It would certainly be possible to do this by adding another backend callback,
which would be useful for other things, but that's beyond the scope of what I'm
doing here.

The semantics of the "deny" action are ambiguous (the draft document states that
the server decides how to handle deny actions). There are two basic ways to
handle a deny action: (1) a right not denied is implicitly granted, and (2) a
denied right overrides a granted right. I currently use the former semantics,
which basically means that a deny action is the complement of a grant action, and
as such is a usability feature (gives no additional functionality). The second
semantic definition of deny would require that some ordering be placed on the
rights within an aci, and perhaps on the separate values of the aci attribute.
Apache uses this other semantic definition, and supplies a way to specify how
deny/allow rights should be ordered.

I am planning on switching to the second definition, since it is more powerful.
There is already some of this access-overriding going on for aci's like:


Which according to the draft should be interpreted to mean that the subject has
read access to attr1, no access to attr2, and read/write access to all other

Well, thanks if you've made it this far.  I will be setting up an example
directory so anyone who wants can have a look at how this all works.  I'll
send e-mail to the list when that's ready.