2 # Copyright 1999-2009 The OpenLDAP Foundation, All Rights Reserved.
3 # COPYING RESTRICTIONS APPLY, see COPYRIGHT.
9 As the directory gets populated with more and more data of varying sensitivity,
10 controlling the kinds of access granted to the directory becomes more and more
11 critical. For instance, the directory may contain data of a confidential nature
12 that you may need to protect by contract or by law. Or, if using the directory
13 to control access to other services, inappropriate access to the directory may
14 create avenues of attack to your sites security that result in devastating
15 damage to your assets.
17 Access to your directory can be configured via two methods, the first using
18 {{SECT:The slapd Configuration File}} and the second using the {{slapd-config}}(5)
19 format ({{SECT:Configuring slapd}}).
21 The default access control policy is allow read by all clients. Regardless of
22 what access control policy is defined, the {{rootdn}} is always allowed full
23 rights (i.e. auth, search, compare, read and write) on everything and anything.
25 As a consequence, it's useless (and results in a performance penalty) to explicitly
26 list the {{rootdn}} among the {{<by>}} clauses.
28 The following sections will describe Access Control Lists in more details and
29 follow with some examples and recommendations.
31 H2: Access Control via Static Configuration
33 Access to entries and attributes is controlled by the
34 access configuration file directive. The general form of an
37 > <access directive> ::= access to <what>
38 > [by <who> [<access>] [<control>] ]+
40 > [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
41 > [filter=<ldapfilter>] [attrs=<attrlist>]
42 > <basic-style> ::= regex | exact
43 > <scope-style> ::= base | one | subtree | children
44 > <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
45 > <attr> ::= <attrname> | entry | children
46 > <who> ::= * | [anonymous | users | self
47 > | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
49 > [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
50 > [peername[.<basic-style>]=<regex>]
51 > [sockname[.<basic-style>]=<regex>]
52 > [domain[.<basic-style>]=<regex>]
53 > [sockurl[.<basic-style>]=<regex>]
56 > <access> ::= [self]{<level>|<priv>}
57 > <level> ::= none | disclose | auth | compare | search | read | write | manage
58 > <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
59 > <control> ::= [stop | continue | break]
61 where the <what> part selects the entries and/or attributes to which
62 the access applies, the {{EX:<who>}} part specifies which entities
63 are granted access, and the {{EX:<access>}} part specifies the
64 access granted. Multiple {{EX:<who> <access> <control>}} triplets
65 are supported, allowing many entities to be granted different access
66 to the same set of entries and attributes. Not all of these access
67 control options are described here; for more details see the
68 {{slapd.access}}(5) man page.
71 H3: What to control access to
73 The <what> part of an access specification determines the entries
74 and attributes to which the access control applies. Entries are
75 commonly selected in two ways: by DN and by filter. The following
76 qualifiers select entries by DN:
79 > to dn[.<basic-style>]=<regex>
80 > to dn.<scope-style>=<DN>
82 The first form is used to select all entries. The second form may
83 be used to select entries by matching a regular expression against
84 the target entry's {{normalized DN}}. (The second form is not
85 discussed further in this document.) The third form is used to
86 select entries which are within the requested scope of DN. The
87 <DN> is a string representation of the Distinguished Name, as
88 described in {{REF:RFC4514}}.
90 The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
91 or {{EX:children}}. Where {{EX:base}} matches only the entry with
92 provided DN, {{EX:one}} matches the entries whose parent is the
93 provided DN, {{EX:subtree}} matches all entries in the subtree whose
94 root is the provided DN, and {{EX:children}} matches all entries
95 under the DN (but not the entry named by the DN).
97 For example, if the directory contained entries named:
100 > 1: cn=Manager,o=suffix
101 > 2: ou=people,o=suffix
102 > 3: uid=kdz,ou=people,o=suffix
103 > 4: cn=addresses,uid=kdz,ou=people,o=suffix
104 > 5: uid=hyc,ou=people,o=suffix
107 . {{EX:dn.base="ou=people,o=suffix"}} match 2;
108 . {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
109 . {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
110 . {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
113 Entries may also be selected using a filter:
115 > to filter=<ldap filter>
117 where <ldap filter> is a string representation of an LDAP
118 search filter, as described in {{REF:RFC4515}}. For example:
120 > to filter=(objectClass=person)
122 Note that entries may be selected by both DN and filter by
123 including both qualifiers in the <what> clause.
125 > to dn.one="ou=people,o=suffix" filter=(objectClass=person)
127 Attributes within an entry are selected by including a comma-separated
128 list of attribute names in the <what> selector:
130 > attrs=<attribute list>
132 A specific value of an attribute is selected by using a single
133 attribute name and also using a value selector:
135 > attrs=<attribute> val[.<style>]=<regex>
137 There are two special {{pseudo}} attributes {{EX:entry}} and
138 {{EX:children}}. To read (and hence return) a target entry, the
139 subject must have {{EX:read}} access to the target's {{entry}}
140 attribute. To perform a search, the subject must have
141 {{EX:search}} access to the search base's {{entry}} attribute.
142 To add or delete an entry, the subject must have
143 {{EX:write}} access to the entry's {{EX:entry}} attribute AND must
144 have {{EX:write}} access to the entry's parent's {{EX:children}}
145 attribute. To rename an entry, the subject must have {{EX:write}}
146 access to entry's {{EX:entry}} attribute AND have {{EX:write}}
147 access to both the old parent's and new parent's {{EX:children}}
148 attributes. The complete examples at the end of this section should
149 help clear things up.
151 Lastly, there is a special entry selector {{EX:"*"}} that is used to
152 select any entry. It is used when no other {{EX:<what>}}
153 selector has been provided. It's equivalent to "{{EX:dn=.*}}"
156 H3: Who to grant access to
158 The <who> part identifies the entity or entities being granted
159 access. Note that access is granted to "entities" not "entries."
160 The following table summarizes entity specifiers:
162 !block table; align=Center; coltags="EX,N"; \
163 title="Table 6.3: Access Entity Specifiers"
165 *|All, including anonymous and authenticated users
166 anonymous|Anonymous (non-authenticated) users
167 users|Authenticated users
168 self|User associated with target entry
169 dn[.<basic-style>]=<regex>|Users matching a regular expression
170 dn.<scope-style>=<DN>|Users within scope of a DN
173 The DN specifier behaves much like <what> clause DN specifiers.
175 Other control factors are also supported. For example, a {{EX:<who>}}
176 can be restricted by an entry listed in a DN-valued attribute in
177 the entry to which the access applies:
179 > dnattr=<dn-valued attribute name>
181 The dnattr specification is used to give access to an entry
182 whose DN is listed in an attribute of the entry (e.g., give
183 access to a group entry to whoever is listed as the owner of
186 Some factors may not be appropriate in all environments (or any).
187 For example, the domain factor relies on IP to domain name lookups.
188 As these can easily be spoofed, the domain factor should be avoided.
191 H3: The access to grant
193 The kind of <access> granted can be one of the following:
195 !block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
196 title="Table 6.4: Access Levels"
197 Level Privileges Description
199 disclose =d needed for information disclosure on error
200 auth =dx needed to authenticate (bind)
201 compare =cdx needed to compare
202 search =scdx needed to apply search filters
203 read =rscdx needed to read search results
204 write =wrscdx needed to modify/rename
205 manage =mwrscdx needed to manage
208 Each level implies all lower levels of access. So, for example,
209 granting someone {{EX:write}} access to an entry also grants them
210 {{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
211 {{EX:disclose}} access. However, one may use the privileges specifier
212 to grant specific permissions.
215 H3: Access Control Evaluation
217 When evaluating whether some requester should be given access to
218 an entry and/or attribute, slapd compares the entry and/or attribute
219 to the {{EX:<what>}} selectors given in the configuration file.
220 For each entry, access controls provided in the database which holds
221 the entry (or the global access directives if not held in any database) apply
222 first, followed by the global access directives. Within this
223 priority, access directives are examined in the order in which they
224 appear in the config file. Slapd stops with the first {{EX:<what>}}
225 selector that matches the entry and/or attribute. The corresponding
226 access directive is the one slapd will use to evaluate access.
228 Next, slapd compares the entity requesting access to the {{EX:<who>}}
229 selectors within the access directive selected above in the order
230 in which they appear. It stops with the first {{EX:<who>}} selector
231 that matches the requester. This determines the access the entity
232 requesting access has to the entry and/or attribute.
234 Finally, slapd compares the access granted in the selected
235 {{EX:<access>}} clause to the access requested by the client. If
236 it allows greater or equal access, access is granted. Otherwise,
239 The order of evaluation of access directives makes their placement
240 in the configuration file important. If one access directive is
241 more specific than another in terms of the entries it selects, it
242 should appear first in the config file. Similarly, if one {{EX:<who>}}
243 selector is more specific than another it should come first in the
244 access directive. The access control examples given below should
245 help make this clear.
249 H3: Access Control Examples
251 The access control facility described above is quite powerful. This
252 section shows some examples of its use for descriptive purposes.
256 > access to * by * read
258 This access directive grants read access to everyone.
265 This directive allows the user to modify their entry, allows anonymous
266 to authentication against these entries, and allows all others to
267 read these entries. Note that only the first {{EX:by <who>}} clause
268 which matches applies. Hence, the anonymous users are granted
269 {{EX:auth}}, not {{EX:read}}. The last clause could just as well
270 have been "{{EX:by users read}}".
272 It is often desirable to restrict operations based upon the level
273 of protection in place. The following shows how security strength
274 factors (SSF) can be used.
277 > by ssf=128 self write
278 > by ssf=64 anonymous auth
279 > by ssf=64 users read
281 This directive allows users to modify their own entries if security
282 protections have of strength 128 or better have been established,
283 allows authentication access to anonymous users, and read access
284 when 64 or better security protections have been established. If
285 client has not establish sufficient security protections, the
286 implicit {{EX:by * none}} clause would be applied.
288 The following example shows the use of a style specifiers to select
289 the entries by DN in two access directives where ordering is
292 > access to dn.children="dc=example,dc=com"
294 > access to dn.children="dc=com"
297 Read access is granted to entries under the {{EX:dc=com}} subtree,
298 except for those entries under the {{EX:dc=example,dc=com}} subtree,
299 to which search access is granted. No access is granted to
300 {{EX:dc=com}} as neither access directive matches this DN. If the
301 order of these access directives was reversed, the trailing directive
302 would never be reached, since all entries under {{EX:dc=example,dc=com}}
303 are also under {{EX:dc=com}} entries.
305 Also note that if no {{EX:access to}} directive matches or no {{EX:by
306 <who>}} clause, {{B:access is denied}}. That is, every {{EX:access
307 to}} directive ends with an implicit {{EX:by * none}} clause and
308 every access list ends with an implicit {{EX:access to * by * none}}
311 The next example again shows the importance of ordering, both of
312 the access directives and the {{EX:by <who>}} clauses. It also
313 shows the use of an attribute selector to grant access to a specific
314 attribute and various {{EX:<who>}} selectors.
316 > access to dn.subtree="dc=example,dc=com" attrs=homePhone
318 > by dn.children="dc=example,dc=com" search
319 > by peername.regex=IP:10\..+ read
320 > access to dn.subtree="dc=example,dc=com"
322 > by dn.children="dc=example,dc=com" search
325 This example applies to entries in the "{{EX:dc=example,dc=com}}"
326 subtree. To all attributes except {{EX:homePhone}}, an entry can
327 write to itself, entries under {{EX:example.com}} entries can search
328 by them, anybody else has no access (implicit {{EX:by * none}})
329 excepting for authentication/authorization (which is always done
330 anonymously). The {{EX:homePhone}} attribute is writable by the
331 entry, searchable by entries under {{EX:example.com}}, readable by
332 clients connecting from network 10, and otherwise not readable
333 (implicit {{EX:by * none}}). All other access is denied by the
334 implicit {{EX:access to * by * none}}.
336 Sometimes it is useful to permit a particular DN to add or
337 remove itself from an attribute. For example, if you would like to
338 create a group and allow people to add and remove only
339 their own DN from the member attribute, you could accomplish
340 it with an access directive like this:
342 > access to attrs=member,entry
343 > by dnattr=member selfwrite
345 The dnattr {{EX:<who>}} selector says that the access applies to
346 entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
347 selector says that such members can only add or delete their
348 own DN from the attribute, not other values. The addition of
349 the entry attribute is required because access to the entry is
350 required to access any of the entry's attributes.
353 For more details on how to use the {{EX:access}} directive,
354 consult the {{Advanced Access Control}} chapter.
358 H3: Configuration File Example
360 The following is an example configuration file, interspersed
361 with explanatory text. It defines two databases to handle
362 different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
363 database instances. The line numbers shown are provided for
364 reference only and are not included in the actual file. First, the
365 global configuration section:
367 E: 1. # example config file - global configuration section
368 E: 2. include /usr/local/etc/schema/core.schema
369 E: 3. referral ldap://root.openldap.org
370 E: 4. access to * by * read
372 Line 1 is a comment. Line 2 includes another config file
373 which contains {{core}} schema definitions.
374 The {{EX:referral}} directive on line 3
375 means that queries not local to one of the databases defined
376 below will be referred to the LDAP server running on the
377 standard port (389) at the host {{EX:root.openldap.org}}.
379 Line 4 is a global access control. It applies to all
380 entries (after any applicable database-specific access
383 The next section of the configuration file defines a BDB
384 backend that will handle queries for things in the
385 "dc=example,dc=com" portion of the tree. The
386 database is to be replicated to two slave slapds, one on
387 truelies, the other on judgmentday. Indices are to be
388 maintained for several attributes, and the {{EX:userPassword}}
389 attribute is to be protected from unauthorized access.
391 E: 5. # BDB definition for the example.com
393 E: 7. suffix "dc=example,dc=com"
394 E: 8. directory /usr/local/var/openldap-data
395 E: 9. rootdn "cn=Manager,dc=example,dc=com"
397 E: 11. # indexed attribute definitions
398 E: 12. index uid pres,eq
399 E: 13. index cn,sn,uid pres,eq,approx,sub
400 E: 14. index objectClass eq
401 E: 15. # database access control definitions
402 E: 16. access to attrs=userPassword
404 E: 18. by anonymous auth
405 E: 19. by dn.base="cn=Admin,dc=example,dc=com" write
409 E: 23. by dn.base="cn=Admin,dc=example,dc=com" write
412 Line 5 is a comment. The start of the database definition is marked
413 by the database keyword on line 6. Line 7 specifies the DN suffix
414 for queries to pass to this database. Line 8 specifies the directory
415 in which the database files will live.
417 Lines 9 and 10 identify the database {{super-user}} entry and associated
418 password. This entry is not subject to access control or size or
419 time limit restrictions.
421 Lines 12 through 14 indicate the indices to maintain for various
424 Lines 16 through 24 specify access control for entries in this
425 database. For all applicable entries, the {{EX:userPassword}} attribute is writable
426 by the entry itself and by the "admin" entry. It may be used for
427 authentication/authorization purposes, but is otherwise not readable.
428 All other attributes are writable by the entry and the "admin"
429 entry, but may be read by all users (authenticated or not).
431 The next section of the example configuration file defines another
432 BDB database. This one handles queries involving the
433 {{EX:dc=example,dc=net}} subtree but is managed by the same entity
434 as the first database. Note that without line 39, the read access
435 would be allowed due to the global access rule at line 4.
437 E: 33. # BDB definition for example.net
439 E: 35. suffix "dc=example,dc=net"
440 E: 36. directory /usr/local/var/openldap-data-net
441 E: 37. rootdn "cn=Manager,dc=example,dc=com"
442 E: 38. index objectClass eq
443 E: 39. access to * by users read
445 H2: Access Control via Dynamic Configuration
447 Access to slapd entries and attributes is controlled by the
448 olcAccess attribute, whose values are a sequence of access directives.
449 The general form of the olcAccess configuration is:
451 > olcAccess: <access directive>
452 > <access directive> ::= to <what>
453 > [by <who> [<access>] [<control>] ]+
455 > [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
456 > [filter=<ldapfilter>] [attrs=<attrlist>]
457 > <basic-style> ::= regex | exact
458 > <scope-style> ::= base | one | subtree | children
459 > <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
460 > <attr> ::= <attrname> | entry | children
461 > <who> ::= * | [anonymous | users | self
462 > | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
463 > [dnattr=<attrname>]
464 > [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
465 > [peername[.<basic-style>]=<regex>]
466 > [sockname[.<basic-style>]=<regex>]
467 > [domain[.<basic-style>]=<regex>]
468 > [sockurl[.<basic-style>]=<regex>]
471 > <access> ::= [self]{<level>|<priv>}
472 > <level> ::= none | disclose | auth | compare | search | read | write | manage
473 > <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
474 > <control> ::= [stop | continue | break]
476 where the <what> part selects the entries and/or attributes to which
477 the access applies, the {{EX:<who>}} part specifies which entities
478 are granted access, and the {{EX:<access>}} part specifies the
479 access granted. Multiple {{EX:<who> <access> <control>}} triplets
480 are supported, allowing many entities to be granted different access
481 to the same set of entries and attributes. Not all of these access
482 control options are described here; for more details see the
483 {{slapd.access}}(5) man page.
486 H3: What to control access to
488 The <what> part of an access specification determines the entries
489 and attributes to which the access control applies. Entries are
490 commonly selected in two ways: by DN and by filter. The following
491 qualifiers select entries by DN:
494 > to dn[.<basic-style>]=<regex>
495 > to dn.<scope-style>=<DN>
497 The first form is used to select all entries. The second form may
498 be used to select entries by matching a regular expression against
499 the target entry's {{normalized DN}}. (The second form is not
500 discussed further in this document.) The third form is used to
501 select entries which are within the requested scope of DN. The
502 <DN> is a string representation of the Distinguished Name, as
503 described in {{REF:RFC4514}}.
505 The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
506 or {{EX:children}}. Where {{EX:base}} matches only the entry with
507 provided DN, {{EX:one}} matches the entries whose parent is the
508 provided DN, {{EX:subtree}} matches all entries in the subtree whose
509 root is the provided DN, and {{EX:children}} matches all entries
510 under the DN (but not the entry named by the DN).
512 For example, if the directory contained entries named:
515 > 1: cn=Manager,o=suffix
516 > 2: ou=people,o=suffix
517 > 3: uid=kdz,ou=people,o=suffix
518 > 4: cn=addresses,uid=kdz,ou=people,o=suffix
519 > 5: uid=hyc,ou=people,o=suffix
522 . {{EX:dn.base="ou=people,o=suffix"}} match 2;
523 . {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
524 . {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
525 . {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
528 Entries may also be selected using a filter:
530 > to filter=<ldap filter>
532 where <ldap filter> is a string representation of an LDAP
533 search filter, as described in {{REF:RFC4515}}. For example:
535 > to filter=(objectClass=person)
537 Note that entries may be selected by both DN and filter by
538 including both qualifiers in the <what> clause.
540 > to dn.one="ou=people,o=suffix" filter=(objectClass=person)
542 Attributes within an entry are selected by including a comma-separated
543 list of attribute names in the <what> selector:
545 > attrs=<attribute list>
547 A specific value of an attribute is selected by using a single
548 attribute name and also using a value selector:
550 > attrs=<attribute> val[.<style>]=<regex>
552 There are two special {{pseudo}} attributes {{EX:entry}} and
553 {{EX:children}}. To read (and hence return) a target entry, the
554 subject must have {{EX:read}} access to the target's {{entry}}
555 attribute. To perform a search, the subject must have
556 {{EX:search}} access to the search base's {{entry}} attribute.
557 To add or delete an entry, the subject must have
558 {{EX:write}} access to the entry's {{EX:entry}} attribute AND must
559 have {{EX:write}} access to the entry's parent's {{EX:children}}
560 attribute. To rename an entry, the subject must have {{EX:write}}
561 access to entry's {{EX:entry}} attribute AND have {{EX:write}}
562 access to both the old parent's and new parent's {{EX:children}}
563 attributes. The complete examples at the end of this section should
564 help clear things up.
566 Lastly, there is a special entry selector {{EX:"*"}} that is used to
567 select any entry. It is used when no other {{EX:<what>}}
568 selector has been provided. It's equivalent to "{{EX:dn=.*}}"
571 H3: Who to grant access to
573 The <who> part identifies the entity or entities being granted
574 access. Note that access is granted to "entities" not "entries."
575 The following table summarizes entity specifiers:
577 !block table; align=Center; coltags="EX,N"; \
578 title="Table 5.3: Access Entity Specifiers"
580 *|All, including anonymous and authenticated users
581 anonymous|Anonymous (non-authenticated) users
582 users|Authenticated users
583 self|User associated with target entry
584 dn[.<basic-style>]=<regex>|Users matching a regular expression
585 dn.<scope-style>=<DN>|Users within scope of a DN
588 The DN specifier behaves much like <what> clause DN specifiers.
590 Other control factors are also supported. For example, a {{EX:<who>}}
591 can be restricted by an entry listed in a DN-valued attribute in
592 the entry to which the access applies:
594 > dnattr=<dn-valued attribute name>
596 The dnattr specification is used to give access to an entry
597 whose DN is listed in an attribute of the entry (e.g., give
598 access to a group entry to whoever is listed as the owner of
601 Some factors may not be appropriate in all environments (or any).
602 For example, the domain factor relies on IP to domain name lookups.
603 As these can easily be spoofed, the domain factor should be avoided.
606 H3: The access to grant
608 The kind of <access> granted can be one of the following:
610 !block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
611 title="Table 5.4: Access Levels"
612 Level Privileges Description
614 disclose =d needed for information disclosure on error
615 auth =dx needed to authenticate (bind)
616 compare =cdx needed to compare
617 search =scdx needed to apply search filters
618 read =rscdx needed to read search results
619 write =wrscdx needed to modify/rename
620 manage =mwrscdx needed to manage
623 Each level implies all lower levels of access. So, for example,
624 granting someone {{EX:write}} access to an entry also grants them
625 {{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
626 {{EX:disclose}} access. However, one may use the privileges specifier
627 to grant specific permissions.
630 H3: Access Control Evaluation
632 When evaluating whether some requester should be given access to
633 an entry and/or attribute, slapd compares the entry and/or attribute
634 to the {{EX:<what>}} selectors given in the configuration. For
635 each entry, access controls provided in the database which holds
636 the entry (or the global access directives if not held in any database) apply
637 first, followed by the global access directives (which are held in
638 the {{EX:frontend}} database definition). Within this priority,
639 access directives are examined in the order in which they appear
640 in the configuration attribute. Slapd stops with the first
641 {{EX:<what>}} selector that matches the entry and/or attribute. The
642 corresponding access directive is the one slapd will use to evaluate
645 Next, slapd compares the entity requesting access to the {{EX:<who>}}
646 selectors within the access directive selected above in the order
647 in which they appear. It stops with the first {{EX:<who>}} selector
648 that matches the requester. This determines the access the entity
649 requesting access has to the entry and/or attribute.
651 Finally, slapd compares the access granted in the selected
652 {{EX:<access>}} clause to the access requested by the client. If
653 it allows greater or equal access, access is granted. Otherwise,
656 The order of evaluation of access directives makes their placement
657 in the configuration file important. If one access directive is
658 more specific than another in terms of the entries it selects, it
659 should appear first in the configuration. Similarly, if one {{EX:<who>}}
660 selector is more specific than another it should come first in the
661 access directive. The access control examples given below should
662 help make this clear.
666 H3: Access Control Examples
668 The access control facility described above is quite powerful. This
669 section shows some examples of its use for descriptive purposes.
673 > olcAccess: to * by * read
675 This access directive grants read access to everyone.
682 This directive allows the user to modify their entry, allows anonymous
683 to authenticate against these entries, and allows all others to
684 read these entries. Note that only the first {{EX:by <who>}} clause
685 which matches applies. Hence, the anonymous users are granted
686 {{EX:auth}}, not {{EX:read}}. The last clause could just as well
687 have been "{{EX:by users read}}".
689 It is often desirable to restrict operations based upon the level
690 of protection in place. The following shows how security strength
691 factors (SSF) can be used.
694 > by ssf=128 self write
695 > by ssf=64 anonymous auth
696 > by ssf=64 users read
698 This directive allows users to modify their own entries if security
699 protections of strength 128 or better have been established,
700 allows authentication access to anonymous users, and read access
701 when strength 64 or better security protections have been established. If
702 the client has not establish sufficient security protections, the
703 implicit {{EX:by * none}} clause would be applied.
705 The following example shows the use of style specifiers to select
706 the entries by DN in two access directives where ordering is
709 > olcAccess: to dn.children="dc=example,dc=com"
711 > olcAccess: to dn.children="dc=com"
714 Read access is granted to entries under the {{EX:dc=com}} subtree,
715 except for those entries under the {{EX:dc=example,dc=com}} subtree,
716 to which search access is granted. No access is granted to
717 {{EX:dc=com}} as neither access directive matches this DN. If the
718 order of these access directives was reversed, the trailing directive
719 would never be reached, since all entries under {{EX:dc=example,dc=com}}
720 are also under {{EX:dc=com}} entries.
722 Also note that if no {{EX:olcAccess: to}} directive matches or no {{EX:by
723 <who>}} clause, {{B:access is denied}}. That is, every {{EX:olcAccess:
724 to}} directive ends with an implicit {{EX:by * none}} clause and
725 every access list ends with an implicit {{EX:olcAccess: to * by * none}}
728 The next example again shows the importance of ordering, both of
729 the access directives and the {{EX:by <who>}} clauses. It also
730 shows the use of an attribute selector to grant access to a specific
731 attribute and various {{EX:<who>}} selectors.
733 > olcAccess: to dn.subtree="dc=example,dc=com" attrs=homePhone
735 > by dn.children=dc=example,dc=com" search
736 > by peername.regex=IP:10\..+ read
737 > olcAccess: to dn.subtree="dc=example,dc=com"
739 > by dn.children="dc=example,dc=com" search
742 This example applies to entries in the "{{EX:dc=example,dc=com}}"
743 subtree. To all attributes except {{EX:homePhone}}, an entry can
744 write to itself, entries under {{EX:example.com}} entries can search
745 by them, anybody else has no access (implicit {{EX:by * none}})
746 excepting for authentication/authorization (which is always done
747 anonymously). The {{EX:homePhone}} attribute is writable by the
748 entry, searchable by entries under {{EX:example.com}}, readable by
749 clients connecting from network 10, and otherwise not readable
750 (implicit {{EX:by * none}}). All other access is denied by the
751 implicit {{EX:access to * by * none}}.
753 Sometimes it is useful to permit a particular DN to add or
754 remove itself from an attribute. For example, if you would like to
755 create a group and allow people to add and remove only
756 their own DN from the member attribute, you could accomplish
757 it with an access directive like this:
759 > olcAccess: to attrs=member,entry
760 > by dnattr=member selfwrite
762 The dnattr {{EX:<who>}} selector says that the access applies to
763 entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
764 selector says that such members can only add or delete their
765 own DN from the attribute, not other values. The addition of
766 the entry attribute is required because access to the entry is
767 required to access any of the entry's attributes.
771 H3: Access Control Ordering
773 Since the ordering of {{EX:olcAccess}} directives is essential to their
774 proper evaluation, but LDAP attributes normally do not preserve the
775 ordering of their values, OpenLDAP uses a custom schema extension to
776 maintain a fixed ordering of these values. This ordering is maintained
777 by prepending a {{EX:"{X}"}} numeric index to each value, similarly to
778 the approach used for ordering the configuration entries. These index
779 tags are maintained automatically by slapd and do not need to be specified
780 when originally defining the values. For example, when you create the
783 > olcAccess: to attrs=member,entry
784 > by dnattr=member selfwrite
785 > olcAccess: to dn.children="dc=example,dc=com"
787 > olcAccess: to dn.children="dc=com"
790 when you read them back using slapcat or ldapsearch they will contain
792 > olcAccess: {0}to attrs=member,entry
793 > by dnattr=member selfwrite
794 > olcAccess: {1}to dn.children="dc=example,dc=com"
796 > olcAccess: {2}to dn.children="dc=com"
799 The numeric index may be used to specify a particular value to change
800 when using ldapmodify to edit the access rules. This index can be used
801 instead of (or in addition to) the actual access value. Using this
802 numeric index is very helpful when multiple access rules are being managed.
804 For example, if we needed to change the second rule above to grant
805 write access instead of search, we could try this LDIF:
809 > olcAccess: to dn.children="dc=example,dc=com" by * search
812 > olcAccess: to dn.children="dc=example,dc=com" by * write
815 But this example {{B:will not}} guarantee that the existing values remain in
816 their original order, so it will most likely yield a broken security
817 configuration. Instead, the numeric index should be used:
824 > olcAccess: {1}to dn.children="dc=example,dc=com" by * write
827 This example deletes whatever rule is in value #1 of the {{EX:olcAccess}}
828 attribute (regardless of its value) and adds a new value that is
829 explicitly inserted as value #1. The result will be
831 > olcAccess: {0}to attrs=member,entry
832 > by dnattr=member selfwrite
833 > olcAccess: {1}to dn.children="dc=example,dc=com"
835 > olcAccess: {2}to dn.children="dc=com"
838 which is exactly what was intended.
841 For more details on how to use the {{EX:access}} directive,
842 consult the {{Advanced Access Control}} chapter.
846 H3: Configuration Example
848 The following is an example configuration, interspersed
849 with explanatory text. It defines two databases to handle
850 different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
851 database instances. The line numbers shown are provided for
852 reference only and are not included in the actual file. First, the
853 global configuration section:
855 E: 1. # example config file - global configuration entry
857 E: 3. objectClass: olcGlobal
859 E: 5. olcReferral: ldap://root.openldap.org
862 Line 1 is a comment. Lines 2-4 identify this as the global
864 The {{EX:olcReferral:}} directive on line 5
865 means that queries not local to one of the databases defined
866 below will be referred to the LDAP server running on the
867 standard port (389) at the host {{EX:root.openldap.org}}.
868 Line 6 is a blank line, indicating the end of this entry.
870 E: 7. # internal schema
871 E: 8. dn: cn=schema,cn=config
872 E: 9. objectClass: olcSchemaConfig
876 Line 7 is a comment. Lines 8-10 identify this as the root of
877 the schema subtree. The actual schema definitions in this entry
878 are hardcoded into slapd so no additional attributes are specified here.
879 Line 11 is a blank line, indicating the end of this entry.
881 E: 12. # include the core schema
882 E: 13. include: file:///usr/local/etc/openldap/schema/core.ldif
885 Line 12 is a comment. Line 13 is an LDIF include directive which
886 accesses the {{core}} schema definitions in LDIF format. Line 14
889 Next comes the database definitions. The first database is the
890 special {{EX:frontend}} database whose settings are applied globally
891 to all the other databases.
893 E: 15. # global database parameters
894 E: 16. dn: olcDatabase=frontend,cn=config
895 E: 17. objectClass: olcDatabaseConfig
896 E: 18. olcDatabase: frontend
897 E: 19. olcAccess: to * by * read
900 Line 15 is a comment. Lines 16-18 identify this entry as the global
901 database entry. Line 19 is a global access control. It applies to all
902 entries (after any applicable database-specific access controls).
904 The next entry defines a BDB backend that will handle queries for things
905 in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
906 for several attributes, and the {{EX:userPassword}} attribute is to be
907 protected from unauthorized access.
909 E: 21. # BDB definition for example.com
910 E: 22. dn: olcDatabase=bdb,cn=config
911 E: 23. objectClass: olcDatabaseConfig
912 E: 24. objectClass: olcBdbConfig
913 E: 25. olcDatabase: bdb
914 E: 26. olcSuffix: "dc=example,dc=com"
915 E: 27. olcDbDirectory: /usr/local/var/openldap-data
916 E: 28. olcRootDN: "cn=Manager,dc=example,dc=com"
917 E: 29. olcRootPW: secret
918 E: 30. olcDbIndex: uid pres,eq
919 E: 31. olcDbIndex: cn,sn,uid pres,eq,approx,sub
920 E: 32. olcDbIndex: objectClass eq
921 E: 33. olcAccess: to attrs=userPassword
923 E: 35. by anonymous auth
924 E: 36. by dn.base="cn=Admin,dc=example,dc=com" write
926 E: 38. olcAccess: to *
928 E: 40. by dn.base="cn=Admin,dc=example,dc=com" write
932 Line 21 is a comment. Lines 22-25 identify this entry as a BDB database
933 configuration entry. Line 26 specifies the DN suffix
934 for queries to pass to this database. Line 27 specifies the directory
935 in which the database files will live.
937 Lines 28 and 29 identify the database {{super-user}} entry and associated
938 password. This entry is not subject to access control or size or
939 time limit restrictions.
941 Lines 30 through 32 indicate the indices to maintain for various
944 Lines 33 through 41 specify access control for entries in this
945 database. For all applicable entries, the {{EX:userPassword}} attribute is writable
946 by the entry itself and by the "admin" entry. It may be used for
947 authentication/authorization purposes, but is otherwise not readable.
948 All other attributes are writable by the entry and the "admin"
949 entry, but may be read by all users (authenticated or not).
951 Line 42 is a blank line, indicating the end of this entry.
953 The next section of the example configuration file defines another
954 BDB database. This one handles queries involving the
955 {{EX:dc=example,dc=net}} subtree but is managed by the same entity
956 as the first database. Note that without line 52, the read access
957 would be allowed due to the global access rule at line 19.
959 E: 43. # BDB definition for example.net
960 E: 44. dn: olcDatabase=bdb,cn=config
961 E: 45. objectClass: olcDatabaseConfig
962 E: 46. objectClass: olcBdbConfig
963 E: 47. olcDatabase: bdb
964 E: 48. olcSuffix: "dc=example,dc=net"
965 E: 49. olcDbDirectory: /usr/local/var/openldap-data-net
966 E: 50. olcRootDN: "cn=Manager,dc=example,dc=com"
967 E: 51. olcDbIndex: objectClass eq
968 E: 52. olcAccess: to * by users read
971 H3: Converting from {{slapd.conf}}(5) to a {{B:cn=config}} directory format
973 Discuss slap* -f slapd.conf -F slapd.d/ (man slapd-config)
976 H2: Access Control Common Examples
980 Generally one should start with some basic ACLs such as:
982 > access to attr=userPassword
993 The first ACL allows users to update (but not read) their passwords, anonymous
994 users to authenticate against this attribute, and (implicitly) denying all
997 The second ACL allows users full access to their entry, authenticated users read
998 access to anything, and (implicitly) denying all access to others (in this case,
1002 H3: Matching Anonymous and Authenticated users
1004 An anonymous user has a empty DN. While the {{dn.exact=""}} or {{dn.regex="^$"}}
1005 could be used, {{slapd}}(8)) offers an anonymous shorthand which should be
1012 denies all access to anonymous users while granting others read.
1014 Authenticated users have a subject DN. While {{dn.regex=".+"}} will match any
1015 authenticated user, OpenLDAP provides the users short hand which should be used
1022 This ACL grants read permissions to authenticated users while denying others
1023 (i.e.: anonymous users).
1026 H3: Controlling rootdn access
1028 You could specify the {{rootdn}} in {{slapd.conf}}(5) or {[slapd.d}} without
1029 specifying a {{rootpw}}. Then you have to add an actual directory entry with
1032 > dn: cn=Manager,o=MyOrganization
1035 > objectClass: person
1037 > userPassword: {SSHA}someSSHAdata
1039 Then binding as the {{rootdn}} will require a regular bind to that DN, which
1040 in turn requires auth access to that entry's DN and {{userPassword}}, and this
1041 can be restricted via ACLs. E.g.:
1043 > access to dn.base="cn=Manager,o=MyOrganization"
1044 > by peername.regex=127\.0\.0\.1 auth
1045 > by peername.regex=192\.168\.0\..* auth
1049 The ACLs above will only allow binding using rootdn from localhost and
1053 H3: Managing access with Groups
1055 There are a few ways to do this. One approach is illustrated here. Consider the
1056 following DIT layout:
1058 > +-dc=example,dc=com
1059 > +---cn=administrators,dc=example,dc=com
1060 > +---cn=fred blogs,dc=example,dc=com
1062 and the following group object (in LDIF format):
1064 > dn: cn=administrators,dc=example,dc=com
1065 > cn: administrators of this region
1066 > objectclass: groupOfNames (important for the group acl feature)
1067 > member: cn=fred blogs,dc=example,dc=com
1068 > member: cn=somebody else,dc=example,dc=com
1070 One can then grant access to the members of this this group by adding appropriate
1071 {{by group}} clause to an access directive in {{slapd.conf}}(5). For instance,
1073 > access to dn.children="dc=example,dc=com"
1075 > by group.exact="cn=Administrators,dc=example,dc=com" write
1078 Like by {[dn}} clauses, one can also use {{expand}} to expand the group name
1079 based upon the regular expression matching of the target, that is, the to {{dn.regex}}).
1082 > access to dn.regex="(.+,)?ou=People,(dc=[^,]+,dc=[^,]+)$"
1083 > attrs=children,entry,uid
1084 > by group.expand="cn=Managers,$2" write
1089 The above illustration assumed that the group members are to be found in the
1090 {{member}} attribute type of the {{groupOfNames}} object class. If you need to
1091 use a different group object and/or a different attribute type then use the
1092 following {{slapd.conf}}(5) (abbreviated) syntax:
1095 > by group/<objectclass>/<attributename>=<DN> <access>
1100 > by group/organizationalRole/roleOccupant="cn=Administrator,dc=example,dc=com" write
1102 In this case, we have an ObjectClass {{organizationalRole}} which contains the
1103 administrator DN's in the {{roleOccupant}} attribute. For instance:
1105 > dn: cn=Administrator,dc=example,dc=com
1107 > objectclass: organizationalRole
1108 > roleOccupant: cn=Jane Doe,dc=example,dc=com
1110 Note: the specified member attribute type MUST be of DN or {{NameAndOptionalUID}} syntax,
1111 and the specified object class SHOULD allow the attribute type.
1113 Dynamic Groups are also supported in Access Control. Please see {{slapo-dynlist}}(5)
1114 and the {{SECT:Dynamic Lists}} overlay section.
1117 H3: Granting access to a subset of attributes
1119 You can grant access to a set of attributes by specifying a list of attribute names
1120 in the ACL {{to}} clause. To be useful, you also need to grant access to the
1121 {{entry}} itself. Also note how {{children}} controls the ability to add, delete,
1124 > # mail: self may write, authenticated users may read
1125 > access to attrs=mail
1130 > # cn, sn: self my write, all may read
1131 > access to attrs=cn,sn
1135 > # immediate children: only self can add/delete entries under this entry
1136 > access to attrs=children
1139 > # entry itself: self may write, all may read
1140 > access to attrs=entry
1144 > # other attributes: self may write, others have no access
1149 ObjectClass names may also be specified in this list, which will affect
1150 all the attributes that are required and/or allowed by that {{objectClass}}.
1151 Actually, names in {{attrlist}} that are prefixed by {{@}} are directly treated
1152 as objectClass names. A name prefixed by {{!}} is also treated as an objectClass,
1153 but in this case the access rule affects the attributes that are not required
1154 nor allowed by that {{objectClass}}.
1157 H3: Allowing a user write to all entries below theirs
1159 For a setup where a user can write to its own record and to all of its children:
1161 > access to dn.regex="(.+,)?(uid=[^,]+,o=Company)$"
1162 > by dn.exact,expand="$2" write
1165 (Add more examples for above)
1168 H3: Allowing entry creation
1170 Let's say, you have it like this:
1174 > associatedDomain=<somedomain>
1177 > uid=<someotheruserid>
1183 and, for another domain <someotherdomain>:
1187 > associatedDomain=<someotherdomain>
1190 > uid=<someotheruserid>
1192 > uid=<someotheruserid>
1196 then, if you wanted user {{uid=<someuserid>}} to {{B:ONLY}} create an entry
1197 for its own thing, you could write an ACL like this:
1199 > # this rule lets users of "associatedDomain=<matcheddomain>"
1200 > # write under "ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>",
1201 > # i.e. a user can write ANY entry below its domain's address book;
1202 > # this permission is necessary, but not sufficient, the next
1203 > # will restrict this permission further
1206 > access to dn.regex="^ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$" attrs=children
1207 > by dn.regex="^uid=([^,]+),ou=users,associatedDomain=$1,ou=domains,o=<basedn>$$" write
1211 > # Note that above the "by" clause needs a "regex" style to make sure
1212 > # it expands to a DN that starts with a "uid=<someuserid>" pattern
1213 > # while substituting the associatedDomain submatch from the "what" clause.
1216 > # This rule lets a user with "uid=<matcheduid>" of "<associatedDomain=matcheddomain>"
1217 > # write (i.e. add, modify, delete) the entry whose DN is exactly
1218 > # "uid=<matcheduid>,ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>"
1219 > # and ANY entry as subtree of it
1222 > access to dn.regex="^(.+,)?uid=([^,]+),ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$"
1223 > by dn.exact,expand="uid=$2,ou=users,associatedDomain=$3,ou=domains,o=<basedn>" write
1227 > # Note that above the "by" clause uses the "exact" style with the "expand"
1228 > # modifier because now the whole pattern can be rebuilt by means of the
1229 > # submatches from the "what" clause, so a "regex" compilation and evaluation
1230 > # is no longer required.
1233 H3: Tips for using regular expressions in Access Control
1235 Always use {{dn.regex=<pattern>}} when you intend to use regular expression
1236 matching. {{dn=<pattern>}} alone defaults to {{dn.exact<pattern>}}.
1238 Use {{(.+)}} instead of {{(.*)}} when you want at least one char to be matched.
1239 {{(.*)}} matches the empty string as well.
1241 Don't use regular expressions for matches that can be done otherwise in a safer
1242 and cheaper manner. Examples:
1244 > dn.regex=".*dc=example,dc=com"
1246 is unsafe and expensive:
1248 * unsafe because any string containing {{dc=example,dc=com }}will match,
1249 not only those that end with the desired pattern; use {{.*dc=example,dc=com$}} instead.
1250 * unsafe also because it would allow any {{attributeType}} ending with {{dc}}
1251 as naming attribute for the first RDN in the string, e.g. a custom attributeType
1252 {{mydc}} would match as well. If you really need a regular expression that allows
1253 just {{dc=example,dc=com}} or any of its subtrees, use {{^(.+,)?dc=example,dc=com$}},
1254 which means: anything to the left of dc=..., if any (the question mark after the
1255 pattern within brackets), must end with a comma;
1256 * expensive because if you don't need submatches, you could use scoping styles, e.g.
1258 > dn.subtree="dc=example,dc=com"
1260 to include {{dc=example,dc=com}} in the matching patterns,
1262 > dn.children="dc=example,dc=com"
1264 to exclude {{dc=example,dc=com}} from the matching patterns, or
1266 > dn.onelevel="dc=example,dc=com"
1268 to allow exactly one sublevel matches only.
1270 Always use {{^}} and {{$}} in regexes, whenever appropriate, because
1271 {{ou=(.+),ou=(.+),ou=addressbooks,o=basedn}} will match
1272 {{something=bla,ou=xxx,ou=yyy,ou=addressbooks,o=basedn,ou=addressbooks,o=basedn,dc=some,dc=org}}
1274 Always use {{([^,]+)}} to indicate exactly one RDN, because {{(.+)}} can
1275 include any number of RDNs; e.g. {{ou=(.+),dc=example,dc=com}} will match
1276 {{ou=My,o=Org,dc=example,dc=com}}, which might not be what you want.
1278 Never add the rootdn to the by clauses. ACLs are not even processed for operations
1279 performed with rootdn identity (otherwise there would be no reason to define a
1282 Use shorthands. The user directive matches authenticated users and the anonymous
1283 directive matches anonymous users.
1285 Don't use the {{dn.regex}} form for <by> clauses if all you need is scoping
1286 and/or substring replacement; use scoping styles (e.g. {{exact}}, {{onelevel}},
1287 {{children}} or {{subtree}}) and the style modifier expand to cause substring expansion.
1291 > access to dn.regex=".+,dc=([^,]+),dc=([^,]+)$"
1292 > by dn.regex="^[^,],ou=Admin,dc=$1,dc=$2$$" write
1294 although correct, can be safely and efficiently replaced by
1296 > access to dn.regex=".+,(dc=[^,]+,dc=[^,]+)$"
1297 > by dn.onelevel,expand="ou=Admin,$1" write
1299 where the regex in the {{<what>}} clause is more compact, and the one in the {{<by>}}
1300 clause is replaced by a much more efficient scoping style of onelevel with substring expansion.
1303 H3: Granting and Denying access based on security strength factors (ssf)
1305 You can restrict access based on the security strength factor (SSF)
1307 > access to dn="cn=example,cn=edu"
1310 0 (zero) implies no protection,
1311 1 implies integrity protection only,
1312 56 DES or other weak ciphers,
1313 112 triple DES and other strong ciphers,
1314 128 RC4, Blowfish and other modern strong ciphers.
1316 Other possibilities:
1324 See {{slapd.conf}}(5) for information on {{ssf}}.
1327 H3: When things aren't working as expected
1329 Consider this example:
1340 You may think this will allow any user to login, to read everything and change
1341 his own data if he is logged in. But in this example only the login works and
1342 an ldapsearch returns no data. The Problem is that SLAPD goes through its access
1343 config line by line and stops as soon as it finds a match in the part of the
1344 access rule.(here: {{to *}})
1346 To get what we wanted the file has to read:
1353 The general rule is: "special access rules first, generic access rules last"
1355 See also {{slapd.access}}(8), loglevel 128 and {{slapacl}}(8) for debugging
1359 H2: Sets - Granting rights based on relationships
1361 Sets are best illustrated via examples. The following sections will present
1362 a few set ACL examples in order to facilitate their understanding.
1364 (Sets in Access Controls FAQ Entry: {{URL:http://www.openldap.org/faq/data/cache/1133.html}})
1366 Note: Sets are considered experimental.
1369 H3: Groups of Groups
1371 The OpenLDAP ACL for groups doesn't expand groups within groups, which are
1372 groups that have another group as a member. For example:
1374 > dn: cn=sudoadm,ou=group,dc=example,dc=com
1376 > objectClass: groupOfNames
1377 > member: uid=john,ou=people,dc=example,dc=com
1378 > member: cn=accountadm,ou=group,dc=example,dc=com
1380 > dn: cn=accountadm,ou=group,dc=example,dc=com
1382 > objectClass: groupOfNames
1383 > member: uid=mary,ou=people,dc=example,dc=com
1385 If we use standard group ACLs with the above entries and allow members of the
1386 {{F:sudoadm}} group to write somewhere, {{F:mary}} won't be included:
1388 > access to dn.subtree="ou=sudoers,dc=example,dc=com"
1389 > by group.exact="cn=sudoadm,ou=group,dc=example,dc=com" write
1392 With sets we can make the ACL be recursive and consider group within groups. So
1393 for each member that is a group, it is further expanded:
1395 > access to dn.subtree="ou=sudoers,dc=example,dc=com"
1396 > by set="[cn=sudoadm,ou=group,dc=example,dc=com]/member* & user" write
1399 This set ACL means: take the {{F:cn=sudoadm}} DN, check its {{F:member}}
1400 attribute(s) (where the "{{F:*}}" means recursively) and intersect the result
1401 with the authenticated user's DN. If the result is non-empty, the ACL is
1402 considered a match and write access is granted.
1404 The following drawing explains how this set is built:
1405 !import "set-recursivegroup.png"; align="center"; title="Building a recursive group"
1406 FT[align="Center"] Figure X.Y: Populating a recursive group set
1408 First we get the {{F:uid=john}} DN. This entry doesn't have a {{F:member}}
1409 attribute, so the expansion stops here. Now we get to {{F:cn=accountadm}}.
1410 This one does have a {{F:member}} attribute, which is {{F:uid=mary}}. The
1411 {{F:uid=mary}} entry, however, doesn't have member, so we stop here again. The
1414 > {"uid=john,ou=people,dc=example,dc=com","uid=mary,ou=people,dc=example,dc=com"} & user
1416 If the authenticated user's DN is any one of those two, write access is
1417 granted. So this set will include {{F:mary}} in the {{F:sudoadm}} group and she
1418 will be allowed the write access.
1420 H3: Group ACLs without DN syntax
1422 The traditional group ACLs, and even the previous example about recursive groups, require
1423 that the members are specified as DNs instead of just usernames.
1425 With sets, however, it's also possible to use simple names in group ACLs, as this example will
1428 Let's say we want to allow members of the {{F:sudoadm}} group to write to the
1429 {{F:ou=suders}} branch of our tree. But our group definition now is using {{F:memberUid}} for
1432 > dn: cn=sudoadm,ou=group,dc=example,dc=com
1434 > objectClass: posixGroup
1438 With this type of group, we can't use group ACLs. But with a set ACL we can
1439 grant the desired access:
1441 > access to dn.subtree="ou=sudoers,dc=example,dc=com"
1442 > by set="[cn=sudoadm,ou=group,dc=example,dc=com]/memberUid & user/uid" write
1445 We use a simple intersection where we compare the {{F:uid}} attribute
1446 of the connecting (and authenticated) user with the {{F:memberUid}} attributes
1447 of the group. If they match, the intersection is non-empty and the ACL will
1450 This drawing illustrates this set when the connecting user is authenticated as
1451 {{F:uid=john,ou=people,dc=example,dc=com}}:
1452 !import "set-memberUid.png"; align="center"; title="Sets with memberUid"
1453 FT[align="Center"] Figure X.Y: Sets with {{F:memberUid}}
1455 In this case, it's a match. If it were {{F:mary}} authenticating, however, she
1456 would be denied write access to {{F:ou=sudoers}} because her {{F:uid}}
1457 attribute is not listed in the group's {{F:memberUid}}.
1459 H3: Following references
1461 We will now show a quite powerful example of what can be done with sets. This
1462 example tends to make OpenLDAP administrators smile after they have understood
1463 it and its implications.
1465 Let's start with an user entry:
1467 > dn: uid=john,ou=people,dc=example,dc=com
1469 > objectClass: inetOrgPerson
1473 > manager: uid=mary,ou=people,dc=example,dc=com
1475 Writing an ACL to allow the manager to update some attributes is quite simple
1478 > access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1479 > attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1481 > by set="this/manager & user" write
1484 In that set, {{F:this}} expands to the entry being accessed, so that
1485 {{F:this/manager}} expands to {{F:uid=mary,ou=people,dc=example,dc=com}} when
1486 john's entry is accessed. If the manager herself is accessing John's entry,
1487 the ACL will match and write access to those attributes will be granted.
1489 So far, this same behavior can be obtained with the {{F:dnattr}} keyword. With
1490 sets, however, we can further enhance this ACL. Let's say we want to allow the
1491 secretary of the manager to also update these attributes. This is how we do it:
1493 > access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1494 > attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1496 > by set="this/manager & user" write
1497 > by set="this/manager/secretary & user" write
1500 Now we need a picture to help explain what is happening here (entries shortened
1503 !import "set-following-references.png"; align="center"; title="Sets jumping through entries"
1504 FT[align="Center"] Figure X.Y: Sets jumping through entries
1506 In this example, Jane is the secretary of Mary, which is the manager of John.
1507 This whole relationship is defined with the {{F:manager}} and {{F:secretary}}
1508 attributes, which are both of the distinguishedName syntax (i.e., full DNs).
1509 So, when the {{F:uid=john}} entry is being accessed, the
1510 {{F:this/manager/secretary}} set becomes
1511 {{F:{"uid=jane,ou=people,dc=example,dc=com"}}} (follow the references in the
1514 > this = [uid=john,ou=people,dc=example,dc=com]
1516 > [uid=john,ou=people,dc=example,dc=com]/manager = uid=mary,ou=people,dc=example,dc=com
1517 > this/manager/secretary = \
1518 > [uid=mary,ou=people,dc=example,dc=com]/secretary = uid=jane,ou=people,dc=example,dc=com
1520 The end result is that when Jane accesses John's entry, she will be granted
1521 write access to the specified attributes. Better yet, this will happen to any
1522 entry she accesses which has Mary as the manager.
1524 This is all cool and nice, but perhaps gives to much power to secretaries. Maybe we need to further
1525 restrict it. For example, let's only allow executive secretaries to have this power:
1527 > access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1528 > attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1530 > by set="this/manager & user" write
1531 > by set="this/manager/secretary &
1532 > [cn=executive,ou=group,dc=example,dc=com]/member* &
1536 It's almost the same ACL as before, but we now also require that the connecting user be a member
1537 of the (possibly nested) {{F:cn=executive}} group.