1
# $OpenLDAP: pkg/openldap-guide/admin/access-control.sdf,v 1.3.2.5 2009/02/02 22:45:18 quanah Exp $
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. However, when dealing with
223
an access list, because the global access list is effectively appended
224
to each per-database list, if the resulting list is non-empty then the
225
access list will end with an implicit {{EX:access to * by * none}} directive.
226
If there are no access directives applicable to a backend, then a default
230
priority, access directives are examined in the order in which they
231
appear in the config file. Slapd stops with the first {{EX:<what>}}
232
selector that matches the entry and/or attribute. The corresponding
233
access directive is the one slapd will use to evaluate access.
235
Next, slapd compares the entity requesting access to the {{EX:<who>}}
236
selectors within the access directive selected above in the order
237
in which they appear. It stops with the first {{EX:<who>}} selector
238
that matches the requester. This determines the access the entity
239
requesting access has to the entry and/or attribute.
241
Finally, slapd compares the access granted in the selected
242
{{EX:<access>}} clause to the access requested by the client. If
243
it allows greater or equal access, access is granted. Otherwise,
246
The order of evaluation of access directives makes their placement
247
in the configuration file important. If one access directive is
248
more specific than another in terms of the entries it selects, it
249
should appear first in the config file. Similarly, if one {{EX:<who>}}
250
selector is more specific than another it should come first in the
251
access directive. The access control examples given below should
252
help make this clear.
256
H3: Access Control Examples
258
The access control facility described above is quite powerful. This
259
section shows some examples of its use for descriptive purposes.
263
> access to * by * read
265
This access directive grants read access to everyone.
272
This directive allows the user to modify their entry, allows anonymous
273
to authentication against these entries, and allows all others to
274
read these entries. Note that only the first {{EX:by <who>}} clause
275
which matches applies. Hence, the anonymous users are granted
276
{{EX:auth}}, not {{EX:read}}. The last clause could just as well
277
have been "{{EX:by users read}}".
279
It is often desirable to restrict operations based upon the level
280
of protection in place. The following shows how security strength
281
factors (SSF) can be used.
284
> by ssf=128 self write
285
> by ssf=64 anonymous auth
286
> by ssf=64 users read
288
This directive allows users to modify their own entries if security
289
protections have of strength 128 or better have been established,
290
allows authentication access to anonymous users, and read access
291
when 64 or better security protections have been established. If
292
client has not establish sufficient security protections, the
293
implicit {{EX:by * none}} clause would be applied.
295
The following example shows the use of a style specifiers to select
296
the entries by DN in two access directives where ordering is
299
> access to dn.children="dc=example,dc=com"
301
> access to dn.children="dc=com"
304
Read access is granted to entries under the {{EX:dc=com}} subtree,
305
except for those entries under the {{EX:dc=example,dc=com}} subtree,
306
to which search access is granted. No access is granted to
307
{{EX:dc=com}} as neither access directive matches this DN. If the
308
order of these access directives was reversed, the trailing directive
309
would never be reached, since all entries under {{EX:dc=example,dc=com}}
310
are also under {{EX:dc=com}} entries.
312
Also note that if no {{EX:access to}} directive matches or no {{EX:by
313
<who>}} clause, {{B:access is denied}}. That is, every {{EX:access
314
to}} directive ends with an implicit {{EX:by * none}} clause. When dealing
315
with an access list, because the global access list is effectively appended
316
to each per-database list, if the resulting list is non-empty then the access
317
list will end with an implicit {{EX:access to * by * none}} directive. If
318
there are no access directives applicable to a backend, then a default read is
321
The next example again shows the importance of ordering, both of
322
the access directives and the {{EX:by <who>}} clauses. It also
323
shows the use of an attribute selector to grant access to a specific
324
attribute and various {{EX:<who>}} selectors.
326
> access to dn.subtree="dc=example,dc=com" attrs=homePhone
328
> by dn.children="dc=example,dc=com" search
329
> by peername.regex=IP:10\..+ read
330
> access to dn.subtree="dc=example,dc=com"
332
> by dn.children="dc=example,dc=com" search
335
This example applies to entries in the "{{EX:dc=example,dc=com}}"
336
subtree. To all attributes except {{EX:homePhone}}, an entry can
337
write to itself, entries under {{EX:example.com}} entries can search
338
by them, anybody else has no access (implicit {{EX:by * none}})
339
excepting for authentication/authorization (which is always done
340
anonymously). The {{EX:homePhone}} attribute is writable by the
341
entry, searchable by entries under {{EX:example.com}}, readable by
342
clients connecting from network 10, and otherwise not readable
343
(implicit {{EX:by * none}}). All other access is denied by the
344
implicit {{EX:access to * by * none}}.
346
Sometimes it is useful to permit a particular DN to add or
347
remove itself from an attribute. For example, if you would like to
348
create a group and allow people to add and remove only
349
their own DN from the member attribute, you could accomplish
350
it with an access directive like this:
352
> access to attrs=member,entry
353
> by dnattr=member selfwrite
355
The dnattr {{EX:<who>}} selector says that the access applies to
356
entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
357
selector says that such members can only add or delete their
358
own DN from the attribute, not other values. The addition of
359
the entry attribute is required because access to the entry is
360
required to access any of the entry's attributes.
363
For more details on how to use the {{EX:access}} directive,
364
consult the {{Advanced Access Control}} chapter.
368
H3: Configuration File Example
370
The following is an example configuration file, interspersed
371
with explanatory text. It defines two databases to handle
372
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
373
database instances. The line numbers shown are provided for
374
reference only and are not included in the actual file. First, the
375
global configuration section:
377
E: 1. # example config file - global configuration section
378
E: 2. include /usr/local/etc/schema/core.schema
379
E: 3. referral ldap://root.openldap.org
380
E: 4. access to * by * read
382
Line 1 is a comment. Line 2 includes another config file
383
which contains {{core}} schema definitions.
384
The {{EX:referral}} directive on line 3
385
means that queries not local to one of the databases defined
386
below will be referred to the LDAP server running on the
387
standard port (389) at the host {{EX:root.openldap.org}}.
389
Line 4 is a global access control. It applies to all
390
entries (after any applicable database-specific access
393
The next section of the configuration file defines a BDB
394
backend that will handle queries for things in the
395
"dc=example,dc=com" portion of the tree. The
396
database is to be replicated to two slave slapds, one on
397
truelies, the other on judgmentday. Indices are to be
398
maintained for several attributes, and the {{EX:userPassword}}
399
attribute is to be protected from unauthorized access.
401
E: 5. # BDB definition for the example.com
403
E: 7. suffix "dc=example,dc=com"
404
E: 8. directory /usr/local/var/openldap-data
405
E: 9. rootdn "cn=Manager,dc=example,dc=com"
407
E: 11. # indexed attribute definitions
408
E: 12. index uid pres,eq
409
E: 13. index cn,sn,uid pres,eq,approx,sub
410
E: 14. index objectClass eq
411
E: 15. # database access control definitions
412
E: 16. access to attrs=userPassword
414
E: 18. by anonymous auth
415
E: 19. by dn.base="cn=Admin,dc=example,dc=com" write
419
E: 23. by dn.base="cn=Admin,dc=example,dc=com" write
422
Line 5 is a comment. The start of the database definition is marked
423
by the database keyword on line 6. Line 7 specifies the DN suffix
424
for queries to pass to this database. Line 8 specifies the directory
425
in which the database files will live.
427
Lines 9 and 10 identify the database {{super-user}} entry and associated
428
password. This entry is not subject to access control or size or
429
time limit restrictions.
431
Lines 12 through 14 indicate the indices to maintain for various
434
Lines 16 through 24 specify access control for entries in this
435
database. For all applicable entries, the {{EX:userPassword}} attribute is writable
436
by the entry itself and by the "admin" entry. It may be used for
437
authentication/authorization purposes, but is otherwise not readable.
438
All other attributes are writable by the entry and the "admin"
439
entry, but may be read by all users (authenticated or not).
441
The next section of the example configuration file defines another
442
BDB database. This one handles queries involving the
443
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
444
as the first database. Note that without line 39, the read access
445
would be allowed due to the global access rule at line 4.
447
E: 33. # BDB definition for example.net
449
E: 35. suffix "dc=example,dc=net"
450
E: 36. directory /usr/local/var/openldap-data-net
451
E: 37. rootdn "cn=Manager,dc=example,dc=com"
452
E: 38. index objectClass eq
453
E: 39. access to * by users read
455
H2: Access Control via Dynamic Configuration
457
Access to slapd entries and attributes is controlled by the
458
olcAccess attribute, whose values are a sequence of access directives.
459
The general form of the olcAccess configuration is:
461
> olcAccess: <access directive>
462
> <access directive> ::= to <what>
463
> [by <who> [<access>] [<control>] ]+
465
> [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
466
> [filter=<ldapfilter>] [attrs=<attrlist>]
467
> <basic-style> ::= regex | exact
468
> <scope-style> ::= base | one | subtree | children
469
> <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
470
> <attr> ::= <attrname> | entry | children
471
> <who> ::= * | [anonymous | users | self
472
> | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
473
> [dnattr=<attrname>]
474
> [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
475
> [peername[.<basic-style>]=<regex>]
476
> [sockname[.<basic-style>]=<regex>]
477
> [domain[.<basic-style>]=<regex>]
478
> [sockurl[.<basic-style>]=<regex>]
481
> <access> ::= [self]{<level>|<priv>}
482
> <level> ::= none | disclose | auth | compare | search | read | write | manage
483
> <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
484
> <control> ::= [stop | continue | break]
486
where the <what> part selects the entries and/or attributes to which
487
the access applies, the {{EX:<who>}} part specifies which entities
488
are granted access, and the {{EX:<access>}} part specifies the
489
access granted. Multiple {{EX:<who> <access> <control>}} triplets
490
are supported, allowing many entities to be granted different access
491
to the same set of entries and attributes. Not all of these access
492
control options are described here; for more details see the
493
{{slapd.access}}(5) man page.
496
H3: What to control access to
498
The <what> part of an access specification determines the entries
499
and attributes to which the access control applies. Entries are
500
commonly selected in two ways: by DN and by filter. The following
501
qualifiers select entries by DN:
504
> to dn[.<basic-style>]=<regex>
505
> to dn.<scope-style>=<DN>
507
The first form is used to select all entries. The second form may
508
be used to select entries by matching a regular expression against
509
the target entry's {{normalized DN}}. (The second form is not
510
discussed further in this document.) The third form is used to
511
select entries which are within the requested scope of DN. The
512
<DN> is a string representation of the Distinguished Name, as
513
described in {{REF:RFC4514}}.
515
The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
516
or {{EX:children}}. Where {{EX:base}} matches only the entry with
517
provided DN, {{EX:one}} matches the entries whose parent is the
518
provided DN, {{EX:subtree}} matches all entries in the subtree whose
519
root is the provided DN, and {{EX:children}} matches all entries
520
under the DN (but not the entry named by the DN).
522
For example, if the directory contained entries named:
525
> 1: cn=Manager,o=suffix
526
> 2: ou=people,o=suffix
527
> 3: uid=kdz,ou=people,o=suffix
528
> 4: cn=addresses,uid=kdz,ou=people,o=suffix
529
> 5: uid=hyc,ou=people,o=suffix
532
. {{EX:dn.base="ou=people,o=suffix"}} match 2;
533
. {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
534
. {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
535
. {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
538
Entries may also be selected using a filter:
540
> to filter=<ldap filter>
542
where <ldap filter> is a string representation of an LDAP
543
search filter, as described in {{REF:RFC4515}}. For example:
545
> to filter=(objectClass=person)
547
Note that entries may be selected by both DN and filter by
548
including both qualifiers in the <what> clause.
550
> to dn.one="ou=people,o=suffix" filter=(objectClass=person)
552
Attributes within an entry are selected by including a comma-separated
553
list of attribute names in the <what> selector:
555
> attrs=<attribute list>
557
A specific value of an attribute is selected by using a single
558
attribute name and also using a value selector:
560
> attrs=<attribute> val[.<style>]=<regex>
562
There are two special {{pseudo}} attributes {{EX:entry}} and
563
{{EX:children}}. To read (and hence return) a target entry, the
564
subject must have {{EX:read}} access to the target's {{entry}}
565
attribute. To perform a search, the subject must have
566
{{EX:search}} access to the search base's {{entry}} attribute.
567
To add or delete an entry, the subject must have
568
{{EX:write}} access to the entry's {{EX:entry}} attribute AND must
569
have {{EX:write}} access to the entry's parent's {{EX:children}}
570
attribute. To rename an entry, the subject must have {{EX:write}}
571
access to entry's {{EX:entry}} attribute AND have {{EX:write}}
572
access to both the old parent's and new parent's {{EX:children}}
573
attributes. The complete examples at the end of this section should
574
help clear things up.
576
Lastly, there is a special entry selector {{EX:"*"}} that is used to
577
select any entry. It is used when no other {{EX:<what>}}
578
selector has been provided. It's equivalent to "{{EX:dn=.*}}"
581
H3: Who to grant access to
583
The <who> part identifies the entity or entities being granted
584
access. Note that access is granted to "entities" not "entries."
585
The following table summarizes entity specifiers:
587
!block table; align=Center; coltags="EX,N"; \
588
title="Table 5.3: Access Entity Specifiers"
590
*|All, including anonymous and authenticated users
591
anonymous|Anonymous (non-authenticated) users
592
users|Authenticated users
593
self|User associated with target entry
594
dn[.<basic-style>]=<regex>|Users matching a regular expression
595
dn.<scope-style>=<DN>|Users within scope of a DN
598
The DN specifier behaves much like <what> clause DN specifiers.
600
Other control factors are also supported. For example, a {{EX:<who>}}
601
can be restricted by an entry listed in a DN-valued attribute in
602
the entry to which the access applies:
604
> dnattr=<dn-valued attribute name>
606
The dnattr specification is used to give access to an entry
607
whose DN is listed in an attribute of the entry (e.g., give
608
access to a group entry to whoever is listed as the owner of
611
Some factors may not be appropriate in all environments (or any).
612
For example, the domain factor relies on IP to domain name lookups.
613
As these can easily be spoofed, the domain factor should be avoided.
616
H3: The access to grant
618
The kind of <access> granted can be one of the following:
620
!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
621
title="Table 5.4: Access Levels"
622
Level Privileges Description
624
disclose =d needed for information disclosure on error
625
auth =dx needed to authenticate (bind)
626
compare =cdx needed to compare
627
search =scdx needed to apply search filters
628
read =rscdx needed to read search results
629
write =wrscdx needed to modify/rename
630
manage =mwrscdx needed to manage
633
Each level implies all lower levels of access. So, for example,
634
granting someone {{EX:write}} access to an entry also grants them
635
{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
636
{{EX:disclose}} access. However, one may use the privileges specifier
637
to grant specific permissions.
640
H3: Access Control Evaluation
642
When evaluating whether some requester should be given access to
643
an entry and/or attribute, slapd compares the entry and/or attribute
644
to the {{EX:<what>}} selectors given in the configuration. For
645
each entry, access controls provided in the database which holds
646
the entry (or the global access directives if not held in any database) apply
647
first, followed by the global access directives (which are held in
648
the {{EX:frontend}} database definition). However, when dealing with
649
an access list, because the global access list is effectively appended
650
to each per-database list, if the resulting list is non-empty then the
651
access list will end with an implicit {{EX:access to * by * none}} directive.
652
If there are no access directives applicable to a backend, then a default
655
Within this priority,
656
access directives are examined in the order in which they appear
657
in the configuration attribute. Slapd stops with the first
658
{{EX:<what>}} selector that matches the entry and/or attribute. The
659
corresponding access directive is the one slapd will use to evaluate
662
Next, slapd compares the entity requesting access to the {{EX:<who>}}
663
selectors within the access directive selected above in the order
664
in which they appear. It stops with the first {{EX:<who>}} selector
665
that matches the requester. This determines the access the entity
666
requesting access has to the entry and/or attribute.
668
Finally, slapd compares the access granted in the selected
669
{{EX:<access>}} clause to the access requested by the client. If
670
it allows greater or equal access, access is granted. Otherwise,
673
The order of evaluation of access directives makes their placement
674
in the configuration file important. If one access directive is
675
more specific than another in terms of the entries it selects, it
676
should appear first in the configuration. Similarly, if one {{EX:<who>}}
677
selector is more specific than another it should come first in the
678
access directive. The access control examples given below should
679
help make this clear.
683
H3: Access Control Examples
685
The access control facility described above is quite powerful. This
686
section shows some examples of its use for descriptive purposes.
690
> olcAccess: to * by * read
692
This access directive grants read access to everyone.
699
This directive allows the user to modify their entry, allows anonymous
700
to authenticate against these entries, and allows all others to
701
read these entries. Note that only the first {{EX:by <who>}} clause
702
which matches applies. Hence, the anonymous users are granted
703
{{EX:auth}}, not {{EX:read}}. The last clause could just as well
704
have been "{{EX:by users read}}".
706
It is often desirable to restrict operations based upon the level
707
of protection in place. The following shows how security strength
708
factors (SSF) can be used.
711
> by ssf=128 self write
712
> by ssf=64 anonymous auth
713
> by ssf=64 users read
715
This directive allows users to modify their own entries if security
716
protections of strength 128 or better have been established,
717
allows authentication access to anonymous users, and read access
718
when strength 64 or better security protections have been established. If
719
the client has not establish sufficient security protections, the
720
implicit {{EX:by * none}} clause would be applied.
722
The following example shows the use of style specifiers to select
723
the entries by DN in two access directives where ordering is
726
> olcAccess: to dn.children="dc=example,dc=com"
728
> olcAccess: to dn.children="dc=com"
731
Read access is granted to entries under the {{EX:dc=com}} subtree,
732
except for those entries under the {{EX:dc=example,dc=com}} subtree,
733
to which search access is granted. No access is granted to
734
{{EX:dc=com}} as neither access directive matches this DN. If the
735
order of these access directives was reversed, the trailing directive
736
would never be reached, since all entries under {{EX:dc=example,dc=com}}
737
are also under {{EX:dc=com}} entries.
739
Also note that if no {{EX:olcAccess: to}} directive matches or no {{EX:by
740
<who>}} clause, {{B:access is denied}}. When dealing with an access list,
741
because the global access list is effectively appended to each per-database
742
list, if the resulting list is non-empty then the access list will end with
743
an implicit {{EX:access to * by * none}} directive. If there are no access
744
directives applicable to a backend, then a default read is used.
746
The next example again shows the importance of ordering, both of
747
the access directives and the {{EX:by <who>}} clauses. It also
748
shows the use of an attribute selector to grant access to a specific
749
attribute and various {{EX:<who>}} selectors.
751
> olcAccess: to dn.subtree="dc=example,dc=com" attrs=homePhone
753
> by dn.children=dc=example,dc=com" search
754
> by peername.regex=IP:10\..+ read
755
> olcAccess: to dn.subtree="dc=example,dc=com"
757
> by dn.children="dc=example,dc=com" search
760
This example applies to entries in the "{{EX:dc=example,dc=com}}"
761
subtree. To all attributes except {{EX:homePhone}}, an entry can
762
write to itself, entries under {{EX:example.com}} entries can search
763
by them, anybody else has no access (implicit {{EX:by * none}})
764
excepting for authentication/authorization (which is always done
765
anonymously). The {{EX:homePhone}} attribute is writable by the
766
entry, searchable by entries under {{EX:example.com}}, readable by
767
clients connecting from network 10, and otherwise not readable
768
(implicit {{EX:by * none}}). All other access is denied by the
769
implicit {{EX:access to * by * none}}.
771
Sometimes it is useful to permit a particular DN to add or
772
remove itself from an attribute. For example, if you would like to
773
create a group and allow people to add and remove only
774
their own DN from the member attribute, you could accomplish
775
it with an access directive like this:
777
> olcAccess: to attrs=member,entry
778
> by dnattr=member selfwrite
780
The dnattr {{EX:<who>}} selector says that the access applies to
781
entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
782
selector says that such members can only add or delete their
783
own DN from the attribute, not other values. The addition of
784
the entry attribute is required because access to the entry is
785
required to access any of the entry's attributes.
789
H3: Access Control Ordering
791
Since the ordering of {{EX:olcAccess}} directives is essential to their
792
proper evaluation, but LDAP attributes normally do not preserve the
793
ordering of their values, OpenLDAP uses a custom schema extension to
794
maintain a fixed ordering of these values. This ordering is maintained
795
by prepending a {{EX:"{X}"}} numeric index to each value, similarly to
796
the approach used for ordering the configuration entries. These index
797
tags are maintained automatically by slapd and do not need to be specified
798
when originally defining the values. For example, when you create the
801
> olcAccess: to attrs=member,entry
802
> by dnattr=member selfwrite
803
> olcAccess: to dn.children="dc=example,dc=com"
805
> olcAccess: to dn.children="dc=com"
808
when you read them back using slapcat or ldapsearch they will contain
810
> olcAccess: {0}to attrs=member,entry
811
> by dnattr=member selfwrite
812
> olcAccess: {1}to dn.children="dc=example,dc=com"
814
> olcAccess: {2}to dn.children="dc=com"
817
The numeric index may be used to specify a particular value to change
818
when using ldapmodify to edit the access rules. This index can be used
819
instead of (or in addition to) the actual access value. Using this
820
numeric index is very helpful when multiple access rules are being managed.
822
For example, if we needed to change the second rule above to grant
823
write access instead of search, we could try this LDIF:
827
> olcAccess: to dn.children="dc=example,dc=com" by * search
830
> olcAccess: to dn.children="dc=example,dc=com" by * write
833
But this example {{B:will not}} guarantee that the existing values remain in
834
their original order, so it will most likely yield a broken security
835
configuration. Instead, the numeric index should be used:
842
> olcAccess: {1}to dn.children="dc=example,dc=com" by * write
845
This example deletes whatever rule is in value #1 of the {{EX:olcAccess}}
846
attribute (regardless of its value) and adds a new value that is
847
explicitly inserted as value #1. The result will be
849
> olcAccess: {0}to attrs=member,entry
850
> by dnattr=member selfwrite
851
> olcAccess: {1}to dn.children="dc=example,dc=com"
853
> olcAccess: {2}to dn.children="dc=com"
856
which is exactly what was intended.
859
For more details on how to use the {{EX:access}} directive,
860
consult the {{Advanced Access Control}} chapter.
864
H3: Configuration Example
866
The following is an example configuration, interspersed
867
with explanatory text. It defines two databases to handle
868
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
869
database instances. The line numbers shown are provided for
870
reference only and are not included in the actual file. First, the
871
global configuration section:
873
E: 1. # example config file - global configuration entry
875
E: 3. objectClass: olcGlobal
877
E: 5. olcReferral: ldap://root.openldap.org
880
Line 1 is a comment. Lines 2-4 identify this as the global
882
The {{EX:olcReferral:}} directive on line 5
883
means that queries not local to one of the databases defined
884
below will be referred to the LDAP server running on the
885
standard port (389) at the host {{EX:root.openldap.org}}.
886
Line 6 is a blank line, indicating the end of this entry.
888
E: 7. # internal schema
889
E: 8. dn: cn=schema,cn=config
890
E: 9. objectClass: olcSchemaConfig
894
Line 7 is a comment. Lines 8-10 identify this as the root of
895
the schema subtree. The actual schema definitions in this entry
896
are hardcoded into slapd so no additional attributes are specified here.
897
Line 11 is a blank line, indicating the end of this entry.
899
E: 12. # include the core schema
900
E: 13. include: file:///usr/local/etc/openldap/schema/core.ldif
903
Line 12 is a comment. Line 13 is an LDIF include directive which
904
accesses the {{core}} schema definitions in LDIF format. Line 14
907
Next comes the database definitions. The first database is the
908
special {{EX:frontend}} database whose settings are applied globally
909
to all the other databases.
911
E: 15. # global database parameters
912
E: 16. dn: olcDatabase=frontend,cn=config
913
E: 17. objectClass: olcDatabaseConfig
914
E: 18. olcDatabase: frontend
915
E: 19. olcAccess: to * by * read
918
Line 15 is a comment. Lines 16-18 identify this entry as the global
919
database entry. Line 19 is a global access control. It applies to all
920
entries (after any applicable database-specific access controls).
922
The next entry defines a BDB backend that will handle queries for things
923
in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
924
for several attributes, and the {{EX:userPassword}} attribute is to be
925
protected from unauthorized access.
927
E: 21. # BDB definition for example.com
928
E: 22. dn: olcDatabase=bdb,cn=config
929
E: 23. objectClass: olcDatabaseConfig
930
E: 24. objectClass: olcBdbConfig
931
E: 25. olcDatabase: bdb
932
E: 26. olcSuffix: "dc=example,dc=com"
933
E: 27. olcDbDirectory: /usr/local/var/openldap-data
934
E: 28. olcRootDN: "cn=Manager,dc=example,dc=com"
935
E: 29. olcRootPW: secret
936
E: 30. olcDbIndex: uid pres,eq
937
E: 31. olcDbIndex: cn,sn,uid pres,eq,approx,sub
938
E: 32. olcDbIndex: objectClass eq
939
E: 33. olcAccess: to attrs=userPassword
941
E: 35. by anonymous auth
942
E: 36. by dn.base="cn=Admin,dc=example,dc=com" write
944
E: 38. olcAccess: to *
946
E: 40. by dn.base="cn=Admin,dc=example,dc=com" write
950
Line 21 is a comment. Lines 22-25 identify this entry as a BDB database
951
configuration entry. Line 26 specifies the DN suffix
952
for queries to pass to this database. Line 27 specifies the directory
953
in which the database files will live.
955
Lines 28 and 29 identify the database {{super-user}} entry and associated
956
password. This entry is not subject to access control or size or
957
time limit restrictions.
959
Lines 30 through 32 indicate the indices to maintain for various
962
Lines 33 through 41 specify access control for entries in this
963
database. For all applicable entries, the {{EX:userPassword}} attribute is writable
964
by the entry itself and by the "admin" entry. It may be used for
965
authentication/authorization purposes, but is otherwise not readable.
966
All other attributes are writable by the entry and the "admin"
967
entry, but may be read by all users (authenticated or not).
969
Line 42 is a blank line, indicating the end of this entry.
971
The next section of the example configuration file defines another
972
BDB database. This one handles queries involving the
973
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
974
as the first database. Note that without line 52, the read access
975
would be allowed due to the global access rule at line 19.
977
E: 43. # BDB definition for example.net
978
E: 44. dn: olcDatabase=bdb,cn=config
979
E: 45. objectClass: olcDatabaseConfig
980
E: 46. objectClass: olcBdbConfig
981
E: 47. olcDatabase: bdb
982
E: 48. olcSuffix: "dc=example,dc=net"
983
E: 49. olcDbDirectory: /usr/local/var/openldap-data-net
984
E: 50. olcRootDN: "cn=Manager,dc=example,dc=com"
985
E: 51. olcDbIndex: objectClass eq
986
E: 52. olcAccess: to * by users read
989
H3: Converting from {{slapd.conf}}(5) to a {{B:cn=config}} directory format
991
Discuss slap* -f slapd.conf -F slapd.d/ (man slapd-config)
994
H2: Access Control Common Examples
998
Generally one should start with some basic ACLs such as:
1000
> access to attr=userPassword
1011
The first ACL allows users to update (but not read) their passwords, anonymous
1012
users to authenticate against this attribute, and (implicitly) denying all
1015
The second ACL allows users full access to their entry, authenticated users read
1016
access to anything, and (implicitly) denying all access to others (in this case,
1020
H3: Matching Anonymous and Authenticated users
1022
An anonymous user has a empty DN. While the {{dn.exact=""}} or {{dn.regex="^$"}}
1023
could be used, {{slapd}}(8)) offers an anonymous shorthand which should be
1030
denies all access to anonymous users while granting others read.
1032
Authenticated users have a subject DN. While {{dn.regex=".+"}} will match any
1033
authenticated user, OpenLDAP provides the users short hand which should be used
1040
This ACL grants read permissions to authenticated users while denying others
1041
(i.e.: anonymous users).
1044
H3: Controlling rootdn access
1046
You could specify the {{rootdn}} in {{slapd.conf}}(5) or {[slapd.d}} without
1047
specifying a {{rootpw}}. Then you have to add an actual directory entry with
1050
> dn: cn=Manager,o=MyOrganization
1053
> objectClass: person
1055
> userPassword: {SSHA}someSSHAdata
1057
Then binding as the {{rootdn}} will require a regular bind to that DN, which
1058
in turn requires auth access to that entry's DN and {{userPassword}}, and this
1059
can be restricted via ACLs. E.g.:
1061
> access to dn.base="cn=Manager,o=MyOrganization"
1062
> by peername.regex=127\.0\.0\.1 auth
1063
> by peername.regex=192\.168\.0\..* auth
1067
The ACLs above will only allow binding using rootdn from localhost and
1071
H3: Managing access with Groups
1073
There are a few ways to do this. One approach is illustrated here. Consider the
1074
following DIT layout:
1076
> +-dc=example,dc=com
1077
> +---cn=administrators,dc=example,dc=com
1078
> +---cn=fred blogs,dc=example,dc=com
1080
and the following group object (in LDIF format):
1082
> dn: cn=administrators,dc=example,dc=com
1083
> cn: administrators of this region
1084
> objectclass: groupOfNames (important for the group acl feature)
1085
> member: cn=fred blogs,dc=example,dc=com
1086
> member: cn=somebody else,dc=example,dc=com
1088
One can then grant access to the members of this this group by adding appropriate
1089
{{by group}} clause to an access directive in {{slapd.conf}}(5). For instance,
1091
> access to dn.children="dc=example,dc=com"
1093
> by group.exact="cn=Administrators,dc=example,dc=com" write
1096
Like by {[dn}} clauses, one can also use {{expand}} to expand the group name
1097
based upon the regular expression matching of the target, that is, the to {{dn.regex}}).
1100
> access to dn.regex="(.+,)?ou=People,(dc=[^,]+,dc=[^,]+)$"
1101
> attrs=children,entry,uid
1102
> by group.expand="cn=Managers,$2" write
1107
The above illustration assumed that the group members are to be found in the
1108
{{member}} attribute type of the {{groupOfNames}} object class. If you need to
1109
use a different group object and/or a different attribute type then use the
1110
following {{slapd.conf}}(5) (abbreviated) syntax:
1113
> by group/<objectclass>/<attributename>=<DN> <access>
1118
> by group/organizationalRole/roleOccupant="cn=Administrator,dc=example,dc=com" write
1120
In this case, we have an ObjectClass {{organizationalRole}} which contains the
1121
administrator DN's in the {{roleOccupant}} attribute. For instance:
1123
> dn: cn=Administrator,dc=example,dc=com
1125
> objectclass: organizationalRole
1126
> roleOccupant: cn=Jane Doe,dc=example,dc=com
1128
Note: the specified member attribute type MUST be of DN or {{NameAndOptionalUID}} syntax,
1129
and the specified object class SHOULD allow the attribute type.
1131
Dynamic Groups are also supported in Access Control. Please see {{slapo-dynlist}}(5)
1132
and the {{SECT:Dynamic Lists}} overlay section.
1135
H3: Granting access to a subset of attributes
1137
You can grant access to a set of attributes by specifying a list of attribute names
1138
in the ACL {{to}} clause. To be useful, you also need to grant access to the
1139
{{entry}} itself. Also note how {{children}} controls the ability to add, delete,
1142
> # mail: self may write, authenticated users may read
1143
> access to attrs=mail
1148
> # cn, sn: self my write, all may read
1149
> access to attrs=cn,sn
1153
> # immediate children: only self can add/delete entries under this entry
1154
> access to attrs=children
1157
> # entry itself: self may write, all may read
1158
> access to attrs=entry
1162
> # other attributes: self may write, others have no access
1167
ObjectClass names may also be specified in this list, which will affect
1168
all the attributes that are required and/or allowed by that {{objectClass}}.
1169
Actually, names in {{attrlist}} that are prefixed by {{@}} are directly treated
1170
as objectClass names. A name prefixed by {{!}} is also treated as an objectClass,
1171
but in this case the access rule affects the attributes that are not required
1172
nor allowed by that {{objectClass}}.
1175
H3: Allowing a user write to all entries below theirs
1177
For a setup where a user can write to its own record and to all of its children:
1179
> access to dn.regex="(.+,)?(uid=[^,]+,o=Company)$"
1180
> by dn.exact,expand="$2" write
1183
(Add more examples for above)
1186
H3: Allowing entry creation
1188
Let's say, you have it like this:
1192
> associatedDomain=<somedomain>
1195
> uid=<someotheruserid>
1201
and, for another domain <someotherdomain>:
1205
> associatedDomain=<someotherdomain>
1208
> uid=<someotheruserid>
1210
> uid=<someotheruserid>
1214
then, if you wanted user {{uid=<someuserid>}} to {{B:ONLY}} create an entry
1215
for its own thing, you could write an ACL like this:
1217
> # this rule lets users of "associatedDomain=<matcheddomain>"
1218
> # write under "ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>",
1219
> # i.e. a user can write ANY entry below its domain's address book;
1220
> # this permission is necessary, but not sufficient, the next
1221
> # will restrict this permission further
1224
> access to dn.regex="^ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$" attrs=children
1225
> by dn.regex="^uid=([^,]+),ou=users,associatedDomain=$1,ou=domains,o=<basedn>$$" write
1229
> # Note that above the "by" clause needs a "regex" style to make sure
1230
> # it expands to a DN that starts with a "uid=<someuserid>" pattern
1231
> # while substituting the associatedDomain submatch from the "what" clause.
1234
> # This rule lets a user with "uid=<matcheduid>" of "<associatedDomain=matcheddomain>"
1235
> # write (i.e. add, modify, delete) the entry whose DN is exactly
1236
> # "uid=<matcheduid>,ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>"
1237
> # and ANY entry as subtree of it
1240
> access to dn.regex="^(.+,)?uid=([^,]+),ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$"
1241
> by dn.exact,expand="uid=$2,ou=users,associatedDomain=$3,ou=domains,o=<basedn>" write
1245
> # Note that above the "by" clause uses the "exact" style with the "expand"
1246
> # modifier because now the whole pattern can be rebuilt by means of the
1247
> # submatches from the "what" clause, so a "regex" compilation and evaluation
1248
> # is no longer required.
1251
H3: Tips for using regular expressions in Access Control
1253
Always use {{dn.regex=<pattern>}} when you intend to use regular expression
1254
matching. {{dn=<pattern>}} alone defaults to {{dn.exact<pattern>}}.
1256
Use {{(.+)}} instead of {{(.*)}} when you want at least one char to be matched.
1257
{{(.*)}} matches the empty string as well.
1259
Don't use regular expressions for matches that can be done otherwise in a safer
1260
and cheaper manner. Examples:
1262
> dn.regex=".*dc=example,dc=com"
1264
is unsafe and expensive:
1266
* unsafe because any string containing {{dc=example,dc=com }}will match,
1267
not only those that end with the desired pattern; use {{.*dc=example,dc=com$}} instead.
1268
* unsafe also because it would allow any {{attributeType}} ending with {{dc}}
1269
as naming attribute for the first RDN in the string, e.g. a custom attributeType
1270
{{mydc}} would match as well. If you really need a regular expression that allows
1271
just {{dc=example,dc=com}} or any of its subtrees, use {{^(.+,)?dc=example,dc=com$}},
1272
which means: anything to the left of dc=..., if any (the question mark after the
1273
pattern within brackets), must end with a comma;
1274
* expensive because if you don't need submatches, you could use scoping styles, e.g.
1276
> dn.subtree="dc=example,dc=com"
1278
to include {{dc=example,dc=com}} in the matching patterns,
1280
> dn.children="dc=example,dc=com"
1282
to exclude {{dc=example,dc=com}} from the matching patterns, or
1284
> dn.onelevel="dc=example,dc=com"
1286
to allow exactly one sublevel matches only.
1288
Always use {{^}} and {{$}} in regexes, whenever appropriate, because
1289
{{ou=(.+),ou=(.+),ou=addressbooks,o=basedn}} will match
1290
{{something=bla,ou=xxx,ou=yyy,ou=addressbooks,o=basedn,ou=addressbooks,o=basedn,dc=some,dc=org}}
1292
Always use {{([^,]+)}} to indicate exactly one RDN, because {{(.+)}} can
1293
include any number of RDNs; e.g. {{ou=(.+),dc=example,dc=com}} will match
1294
{{ou=My,o=Org,dc=example,dc=com}}, which might not be what you want.
1296
Never add the rootdn to the by clauses. ACLs are not even processed for operations
1297
performed with rootdn identity (otherwise there would be no reason to define a
1300
Use shorthands. The user directive matches authenticated users and the anonymous
1301
directive matches anonymous users.
1303
Don't use the {{dn.regex}} form for <by> clauses if all you need is scoping
1304
and/or substring replacement; use scoping styles (e.g. {{exact}}, {{onelevel}},
1305
{{children}} or {{subtree}}) and the style modifier expand to cause substring expansion.
1309
> access to dn.regex=".+,dc=([^,]+),dc=([^,]+)$"
1310
> by dn.regex="^[^,],ou=Admin,dc=$1,dc=$2$$" write
1312
although correct, can be safely and efficiently replaced by
1314
> access to dn.regex=".+,(dc=[^,]+,dc=[^,]+)$"
1315
> by dn.onelevel,expand="ou=Admin,$1" write
1317
where the regex in the {{<what>}} clause is more compact, and the one in the {{<by>}}
1318
clause is replaced by a much more efficient scoping style of onelevel with substring expansion.
1321
H3: Granting and Denying access based on security strength factors (ssf)
1323
You can restrict access based on the security strength factor (SSF)
1325
> access to dn="cn=example,cn=edu"
1328
0 (zero) implies no protection,
1329
1 implies integrity protection only,
1330
56 DES or other weak ciphers,
1331
112 triple DES and other strong ciphers,
1332
128 RC4, Blowfish and other modern strong ciphers.
1334
Other possibilities:
1342
See {{slapd.conf}}(5) for information on {{ssf}}.
1345
H3: When things aren't working as expected
1347
Consider this example:
1358
You may think this will allow any user to login, to read everything and change
1359
his own data if he is logged in. But in this example only the login works and
1360
an ldapsearch returns no data. The Problem is that SLAPD goes through its access
1361
config line by line and stops as soon as it finds a match in the part of the
1362
access rule.(here: {{to *}})
1364
To get what we wanted the file has to read:
1371
The general rule is: "special access rules first, generic access rules last"
1373
See also {{slapd.access}}(8), loglevel 128 and {{slapacl}}(8) for debugging
1377
H2: Sets - Granting rights based on relationships
1379
Sets are best illustrated via examples. The following sections will present
1380
a few set ACL examples in order to facilitate their understanding.
1382
(Sets in Access Controls FAQ Entry: {{URL:http://www.openldap.org/faq/data/cache/1133.html}})
1384
Note: Sets are considered experimental.
1387
H3: Groups of Groups
1389
The OpenLDAP ACL for groups doesn't expand groups within groups, which are
1390
groups that have another group as a member. For example:
1392
> dn: cn=sudoadm,ou=group,dc=example,dc=com
1394
> objectClass: groupOfNames
1395
> member: uid=john,ou=people,dc=example,dc=com
1396
> member: cn=accountadm,ou=group,dc=example,dc=com
1398
> dn: cn=accountadm,ou=group,dc=example,dc=com
1400
> objectClass: groupOfNames
1401
> member: uid=mary,ou=people,dc=example,dc=com
1403
If we use standard group ACLs with the above entries and allow members of the
1404
{{F:sudoadm}} group to write somewhere, {{F:mary}} won't be included:
1406
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1407
> by group.exact="cn=sudoadm,ou=group,dc=example,dc=com" write
1410
With sets we can make the ACL be recursive and consider group within groups. So
1411
for each member that is a group, it is further expanded:
1413
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1414
> by set="[cn=sudoadm,ou=group,dc=example,dc=com]/member* & user" write
1417
This set ACL means: take the {{F:cn=sudoadm}} DN, check its {{F:member}}
1418
attribute(s) (where the "{{F:*}}" means recursively) and intersect the result
1419
with the authenticated user's DN. If the result is non-empty, the ACL is
1420
considered a match and write access is granted.
1422
The following drawing explains how this set is built:
1423
!import "set-recursivegroup.png"; align="center"; title="Building a recursive group"
1424
FT[align="Center"] Figure X.Y: Populating a recursive group set
1426
First we get the {{F:uid=john}} DN. This entry doesn't have a {{F:member}}
1427
attribute, so the expansion stops here. Now we get to {{F:cn=accountadm}}.
1428
This one does have a {{F:member}} attribute, which is {{F:uid=mary}}. The
1429
{{F:uid=mary}} entry, however, doesn't have member, so we stop here again. The
1432
> {"uid=john,ou=people,dc=example,dc=com","uid=mary,ou=people,dc=example,dc=com"} & user
1434
If the authenticated user's DN is any one of those two, write access is
1435
granted. So this set will include {{F:mary}} in the {{F:sudoadm}} group and she
1436
will be allowed the write access.
1438
H3: Group ACLs without DN syntax
1440
The traditional group ACLs, and even the previous example about recursive groups, require
1441
that the members are specified as DNs instead of just usernames.
1443
With sets, however, it's also possible to use simple names in group ACLs, as this example will
1446
Let's say we want to allow members of the {{F:sudoadm}} group to write to the
1447
{{F:ou=suders}} branch of our tree. But our group definition now is using {{F:memberUid}} for
1450
> dn: cn=sudoadm,ou=group,dc=example,dc=com
1452
> objectClass: posixGroup
1456
With this type of group, we can't use group ACLs. But with a set ACL we can
1457
grant the desired access:
1459
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1460
> by set="[cn=sudoadm,ou=group,dc=example,dc=com]/memberUid & user/uid" write
1463
We use a simple intersection where we compare the {{F:uid}} attribute
1464
of the connecting (and authenticated) user with the {{F:memberUid}} attributes
1465
of the group. If they match, the intersection is non-empty and the ACL will
1468
This drawing illustrates this set when the connecting user is authenticated as
1469
{{F:uid=john,ou=people,dc=example,dc=com}}:
1470
!import "set-memberUid.png"; align="center"; title="Sets with memberUid"
1471
FT[align="Center"] Figure X.Y: Sets with {{F:memberUid}}
1473
In this case, it's a match. If it were {{F:mary}} authenticating, however, she
1474
would be denied write access to {{F:ou=sudoers}} because her {{F:uid}}
1475
attribute is not listed in the group's {{F:memberUid}}.
1477
H3: Following references
1479
We will now show a quite powerful example of what can be done with sets. This
1480
example tends to make OpenLDAP administrators smile after they have understood
1481
it and its implications.
1483
Let's start with an user entry:
1485
> dn: uid=john,ou=people,dc=example,dc=com
1487
> objectClass: inetOrgPerson
1491
> manager: uid=mary,ou=people,dc=example,dc=com
1493
Writing an ACL to allow the manager to update some attributes is quite simple
1496
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1497
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1499
> by set="this/manager & user" write
1502
In that set, {{F:this}} expands to the entry being accessed, so that
1503
{{F:this/manager}} expands to {{F:uid=mary,ou=people,dc=example,dc=com}} when
1504
john's entry is accessed. If the manager herself is accessing John's entry,
1505
the ACL will match and write access to those attributes will be granted.
1507
So far, this same behavior can be obtained with the {{F:dnattr}} keyword. With
1508
sets, however, we can further enhance this ACL. Let's say we want to allow the
1509
secretary of the manager to also update these attributes. This is how we do it:
1511
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1512
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1514
> by set="this/manager & user" write
1515
> by set="this/manager/secretary & user" write
1518
Now we need a picture to help explain what is happening here (entries shortened
1521
!import "set-following-references.png"; align="center"; title="Sets jumping through entries"
1522
FT[align="Center"] Figure X.Y: Sets jumping through entries
1524
In this example, Jane is the secretary of Mary, which is the manager of John.
1525
This whole relationship is defined with the {{F:manager}} and {{F:secretary}}
1526
attributes, which are both of the distinguishedName syntax (i.e., full DNs).
1527
So, when the {{F:uid=john}} entry is being accessed, the
1528
{{F:this/manager/secretary}} set becomes
1529
{{F:{"uid=jane,ou=people,dc=example,dc=com"}}} (follow the references in the
1532
> this = [uid=john,ou=people,dc=example,dc=com]
1534
> [uid=john,ou=people,dc=example,dc=com]/manager = uid=mary,ou=people,dc=example,dc=com
1535
> this/manager/secretary = \
1536
> [uid=mary,ou=people,dc=example,dc=com]/secretary = uid=jane,ou=people,dc=example,dc=com
1538
The end result is that when Jane accesses John's entry, she will be granted
1539
write access to the specified attributes. Better yet, this will happen to any
1540
entry she accesses which has Mary as the manager.
1542
This is all cool and nice, but perhaps gives to much power to secretaries. Maybe we need to further
1543
restrict it. For example, let's only allow executive secretaries to have this power:
1545
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1546
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1548
> by set="this/manager & user" write
1549
> by set="this/manager/secretary &
1550
> [cn=executive,ou=group,dc=example,dc=com]/member* &
1554
It's almost the same ACL as before, but we now also require that the connecting user be a member
1555
of the (possibly nested) {{F:cn=executive}} group.