mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
1137 lines
44 KiB
Plaintext
1137 lines
44 KiB
Plaintext
|
# $OpenLDAP$
|
||
|
# Copyright 1999-2008 The OpenLDAP Foundation, All Rights Reserved.
|
||
|
# COPYING RESTRICTIONS APPLY, see COPYRIGHT.
|
||
|
|
||
|
H1: Access Control
|
||
|
|
||
|
Access to your directory can be configured via two methods, the first using
|
||
|
{{SECT:The slapd Configuration File}} and the second using the {{slapd-config}}(5)
|
||
|
format ({{SECT:Configuring slapd}}).
|
||
|
|
||
|
H2: Static Access Control Configuration
|
||
|
|
||
|
Access to entries and attributes is controlled by the
|
||
|
access configuration file directive. The general form of an
|
||
|
access line is:
|
||
|
|
||
|
> <access directive> ::= access to <what>
|
||
|
> [by <who> [<access>] [<control>] ]+
|
||
|
> <what> ::= * |
|
||
|
> [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
|
||
|
> [filter=<ldapfilter>] [attrs=<attrlist>]
|
||
|
> <basic-style> ::= regex | exact
|
||
|
> <scope-style> ::= base | one | subtree | children
|
||
|
> <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
|
||
|
> <attr> ::= <attrname> | entry | children
|
||
|
> <who> ::= * | [anonymous | users | self
|
||
|
> | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
|
||
|
> [dnattr=<attrname>]
|
||
|
> [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
|
||
|
> [peername[.<basic-style>]=<regex>]
|
||
|
> [sockname[.<basic-style>]=<regex>]
|
||
|
> [domain[.<basic-style>]=<regex>]
|
||
|
> [sockurl[.<basic-style>]=<regex>]
|
||
|
> [set=<setspec>]
|
||
|
> [aci=<attrname>]
|
||
|
> <access> ::= [self]{<level>|<priv>}
|
||
|
> <level> ::= none | disclose | auth | compare | search | read | write | manage
|
||
|
> <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
|
||
|
> <control> ::= [stop | continue | break]
|
||
|
|
||
|
where the <what> part selects the entries and/or attributes to which
|
||
|
the access applies, the {{EX:<who>}} part specifies which entities
|
||
|
are granted access, and the {{EX:<access>}} part specifies the
|
||
|
access granted. Multiple {{EX:<who> <access> <control>}} triplets
|
||
|
are supported, allowing many entities to be granted different access
|
||
|
to the same set of entries and attributes. Not all of these access
|
||
|
control options are described here; for more details see the
|
||
|
{{slapd.access}}(5) man page.
|
||
|
|
||
|
|
||
|
H3: What to control access to
|
||
|
|
||
|
The <what> part of an access specification determines the entries
|
||
|
and attributes to which the access control applies. Entries are
|
||
|
commonly selected in two ways: by DN and by filter. The following
|
||
|
qualifiers select entries by DN:
|
||
|
|
||
|
> to *
|
||
|
> to dn[.<basic-style>]=<regex>
|
||
|
> to dn.<scope-style>=<DN>
|
||
|
|
||
|
The first form is used to select all entries. The second form may
|
||
|
be used to select entries by matching a regular expression against
|
||
|
the target entry's {{normalized DN}}. (The second form is not
|
||
|
discussed further in this document.) The third form is used to
|
||
|
select entries which are within the requested scope of DN. The
|
||
|
<DN> is a string representation of the Distinguished Name, as
|
||
|
described in {{REF:RFC4514}}.
|
||
|
|
||
|
The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
|
||
|
or {{EX:children}}. Where {{EX:base}} matches only the entry with
|
||
|
provided DN, {{EX:one}} matches the entries whose parent is the
|
||
|
provided DN, {{EX:subtree}} matches all entries in the subtree whose
|
||
|
root is the provided DN, and {{EX:children}} matches all entries
|
||
|
under the DN (but not the entry named by the DN).
|
||
|
|
||
|
For example, if the directory contained entries named:
|
||
|
|
||
|
> 0: o=suffix
|
||
|
> 1: cn=Manager,o=suffix
|
||
|
> 2: ou=people,o=suffix
|
||
|
> 3: uid=kdz,ou=people,o=suffix
|
||
|
> 4: cn=addresses,uid=kdz,ou=people,o=suffix
|
||
|
> 5: uid=hyc,ou=people,o=suffix
|
||
|
|
||
|
\Then:
|
||
|
. {{EX:dn.base="ou=people,o=suffix"}} match 2;
|
||
|
. {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
|
||
|
. {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
|
||
|
. {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
|
||
|
|
||
|
|
||
|
Entries may also be selected using a filter:
|
||
|
|
||
|
> to filter=<ldap filter>
|
||
|
|
||
|
where <ldap filter> is a string representation of an LDAP
|
||
|
search filter, as described in {{REF:RFC4515}}. For example:
|
||
|
|
||
|
> to filter=(objectClass=person)
|
||
|
|
||
|
Note that entries may be selected by both DN and filter by
|
||
|
including both qualifiers in the <what> clause.
|
||
|
|
||
|
> to dn.one="ou=people,o=suffix" filter=(objectClass=person)
|
||
|
|
||
|
Attributes within an entry are selected by including a comma-separated
|
||
|
list of attribute names in the <what> selector:
|
||
|
|
||
|
> attrs=<attribute list>
|
||
|
|
||
|
A specific value of an attribute is selected by using a single
|
||
|
attribute name and also using a value selector:
|
||
|
|
||
|
> attrs=<attribute> val[.<style>]=<regex>
|
||
|
|
||
|
There are two special {{pseudo}} attributes {{EX:entry}} and
|
||
|
{{EX:children}}. To read (and hence return) a target entry, the
|
||
|
subject must have {{EX:read}} access to the target's {{entry}}
|
||
|
attribute. To add or delete an entry, the subject must have
|
||
|
{{EX:write}} access to the entry's {{EX:entry}} attribute AND must
|
||
|
have {{EX:write}} access to the entry's parent's {{EX:children}}
|
||
|
attribute. To rename an entry, the subject must have {{EX:write}}
|
||
|
access to entry's {{EX:entry}} attribute AND have {{EX:write}}
|
||
|
access to both the old parent's and new parent's {{EX:children}}
|
||
|
attributes. The complete examples at the end of this section should
|
||
|
help clear things up.
|
||
|
|
||
|
Lastly, there is a special entry selector {{EX:"*"}} that is used to
|
||
|
select any entry. It is used when no other {{EX:<what>}}
|
||
|
selector has been provided. It's equivalent to "{{EX:dn=.*}}"
|
||
|
|
||
|
|
||
|
H3: Who to grant access to
|
||
|
|
||
|
The <who> part identifies the entity or entities being granted
|
||
|
access. Note that access is granted to "entities" not "entries."
|
||
|
The following table summarizes entity specifiers:
|
||
|
|
||
|
!block table; align=Center; coltags="EX,N"; \
|
||
|
title="Table 6.3: Access Entity Specifiers"
|
||
|
Specifier|Entities
|
||
|
*|All, including anonymous and authenticated users
|
||
|
anonymous|Anonymous (non-authenticated) users
|
||
|
users|Authenticated users
|
||
|
self|User associated with target entry
|
||
|
dn[.<basic-style>]=<regex>|Users matching a regular expression
|
||
|
dn.<scope-style>=<DN>|Users within scope of a DN
|
||
|
!endblock
|
||
|
|
||
|
The DN specifier behaves much like <what> clause DN specifiers.
|
||
|
|
||
|
Other control factors are also supported. For example, a {{EX:<who>}}
|
||
|
can be restricted by an entry listed in a DN-valued attribute in
|
||
|
the entry to which the access applies:
|
||
|
|
||
|
> dnattr=<dn-valued attribute name>
|
||
|
|
||
|
The dnattr specification is used to give access to an entry
|
||
|
whose DN is listed in an attribute of the entry (e.g., give
|
||
|
access to a group entry to whoever is listed as the owner of
|
||
|
the group entry).
|
||
|
|
||
|
Some factors may not be appropriate in all environments (or any).
|
||
|
For example, the domain factor relies on IP to domain name lookups.
|
||
|
As these can easily be spoofed, the domain factor should be avoided.
|
||
|
|
||
|
|
||
|
H3: The access to grant
|
||
|
|
||
|
The kind of <access> granted can be one of the following:
|
||
|
|
||
|
!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
|
||
|
title="Table 6.4: Access Levels"
|
||
|
Level Privileges Description
|
||
|
none =0 no access
|
||
|
disclose =d needed for information disclosure on error
|
||
|
auth =dx needed to authenticate (bind)
|
||
|
compare =cdx needed to compare
|
||
|
search =scdx needed to apply search filters
|
||
|
read =rscdx needed to read search results
|
||
|
write =wrscdx needed to modify/rename
|
||
|
manage =mwrscdx needed to manage
|
||
|
!endblock
|
||
|
|
||
|
Each level implies all lower levels of access. So, for example,
|
||
|
granting someone {{EX:write}} access to an entry also grants them
|
||
|
{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
|
||
|
{{EX:disclose}} access. However, one may use the privileges specifier
|
||
|
to grant specific permissions.
|
||
|
|
||
|
|
||
|
H3: Access Control Evaluation
|
||
|
|
||
|
When evaluating whether some requester should be given access to
|
||
|
an entry and/or attribute, slapd compares the entry and/or attribute
|
||
|
to the {{EX:<what>}} selectors given in the configuration file.
|
||
|
For each entry, access controls provided in the database which holds
|
||
|
the entry (or the first database if not held in any database) apply
|
||
|
first, followed by the global access directives. Within this
|
||
|
priority, access directives are examined in the order in which they
|
||
|
appear in the config file. Slapd stops with the first {{EX:<what>}}
|
||
|
selector that matches the entry and/or attribute. The corresponding
|
||
|
access directive is the one slapd will use to evaluate access.
|
||
|
|
||
|
Next, slapd compares the entity requesting access to the {{EX:<who>}}
|
||
|
selectors within the access directive selected above in the order
|
||
|
in which they appear. It stops with the first {{EX:<who>}} selector
|
||
|
that matches the requester. This determines the access the entity
|
||
|
requesting access has to the entry and/or attribute.
|
||
|
|
||
|
Finally, slapd compares the access granted in the selected
|
||
|
{{EX:<access>}} clause to the access requested by the client. If
|
||
|
it allows greater or equal access, access is granted. Otherwise,
|
||
|
access is denied.
|
||
|
|
||
|
The order of evaluation of access directives makes their placement
|
||
|
in the configuration file important. If one access directive is
|
||
|
more specific than another in terms of the entries it selects, it
|
||
|
should appear first in the config file. Similarly, if one {{EX:<who>}}
|
||
|
selector is more specific than another it should come first in the
|
||
|
access directive. The access control examples given below should
|
||
|
help make this clear.
|
||
|
|
||
|
|
||
|
|
||
|
H3: Access Control Examples
|
||
|
|
||
|
The access control facility described above is quite powerful. This
|
||
|
section shows some examples of its use for descriptive purposes.
|
||
|
|
||
|
A simple example:
|
||
|
|
||
|
> access to * by * read
|
||
|
|
||
|
This access directive grants read access to everyone.
|
||
|
|
||
|
> access to *
|
||
|
> by self write
|
||
|
> by anonymous auth
|
||
|
> by * read
|
||
|
|
||
|
This directive allows the user to modify their entry, allows anonymous
|
||
|
to authentication against these entries, and allows all others to
|
||
|
read these entries. Note that only the first {{EX:by <who>}} clause
|
||
|
which matches applies. Hence, the anonymous users are granted
|
||
|
{{EX:auth}}, not {{EX:read}}. The last clause could just as well
|
||
|
have been "{{EX:by users read}}".
|
||
|
|
||
|
It is often desirable to restrict operations based upon the level
|
||
|
of protection in place. The following shows how security strength
|
||
|
factors (SSF) can be used.
|
||
|
|
||
|
> access to *
|
||
|
> by ssf=128 self write
|
||
|
> by ssf=64 anonymous auth
|
||
|
> by ssf=64 users read
|
||
|
|
||
|
This directive allows users to modify their own entries if security
|
||
|
protections have of strength 128 or better have been established,
|
||
|
allows authentication access to anonymous users, and read access
|
||
|
when 64 or better security protections have been established. If
|
||
|
client has not establish sufficient security protections, the
|
||
|
implicit {{EX:by * none}} clause would be applied.
|
||
|
|
||
|
The following example shows the use of a style specifiers to select
|
||
|
the entries by DN in two access directives where ordering is
|
||
|
significant.
|
||
|
|
||
|
> access to dn.children="dc=example,dc=com"
|
||
|
> by * search
|
||
|
> access to dn.children="dc=com"
|
||
|
> by * read
|
||
|
|
||
|
Read access is granted to entries under the {{EX:dc=com}} subtree,
|
||
|
except for those entries under the {{EX:dc=example,dc=com}} subtree,
|
||
|
to which search access is granted. No access is granted to
|
||
|
{{EX:dc=com}} as neither access directive matches this DN. If the
|
||
|
order of these access directives was reversed, the trailing directive
|
||
|
would never be reached, since all entries under {{EX:dc=example,dc=com}}
|
||
|
are also under {{EX:dc=com}} entries.
|
||
|
|
||
|
Also note that if no {{EX:access to}} directive matches or no {{EX:by
|
||
|
<who>}} clause, {{B:access is denied}}. That is, every {{EX:access
|
||
|
to}} directive ends with an implicit {{EX:by * none}} clause and
|
||
|
every access list ends with an implicit {{EX:access to * by * none}}
|
||
|
directive.
|
||
|
|
||
|
The next example again shows the importance of ordering, both of
|
||
|
the access directives and the {{EX:by <who>}} clauses. It also
|
||
|
shows the use of an attribute selector to grant access to a specific
|
||
|
attribute and various {{EX:<who>}} selectors.
|
||
|
|
||
|
> access to dn.subtree="dc=example,dc=com" attrs=homePhone
|
||
|
> by self write
|
||
|
> by dn.children="dc=example,dc=com" search
|
||
|
> by peername.regex=IP:10\..+ read
|
||
|
> access to dn.subtree="dc=example,dc=com"
|
||
|
> by self write
|
||
|
> by dn.children="dc=example,dc=com" search
|
||
|
> by anonymous auth
|
||
|
|
||
|
This example applies to entries in the "{{EX:dc=example,dc=com}}"
|
||
|
subtree. To all attributes except {{EX:homePhone}}, an entry can
|
||
|
write to itself, entries under {{EX:example.com}} entries can search
|
||
|
by them, anybody else has no access (implicit {{EX:by * none}})
|
||
|
excepting for authentication/authorization (which is always done
|
||
|
anonymously). The {{EX:homePhone}} attribute is writable by the
|
||
|
entry, searchable by entries under {{EX:example.com}}, readable by
|
||
|
clients connecting from network 10, and otherwise not readable
|
||
|
(implicit {{EX:by * none}}). All other access is denied by the
|
||
|
implicit {{EX:access to * by * none}}.
|
||
|
|
||
|
Sometimes it is useful to permit a particular DN to add or
|
||
|
remove itself from an attribute. For example, if you would like to
|
||
|
create a group and allow people to add and remove only
|
||
|
their own DN from the member attribute, you could accomplish
|
||
|
it with an access directive like this:
|
||
|
|
||
|
> access to attrs=member,entry
|
||
|
> by dnattr=member selfwrite
|
||
|
|
||
|
The dnattr {{EX:<who>}} selector says that the access applies to
|
||
|
entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
|
||
|
selector says that such members can only add or delete their
|
||
|
own DN from the attribute, not other values. The addition of
|
||
|
the entry attribute is required because access to the entry is
|
||
|
required to access any of the entry's attributes.
|
||
|
|
||
|
!if 0
|
||
|
For more details on how to use the {{EX:access}} directive,
|
||
|
consult the {{Advanced Access Control}} chapter.
|
||
|
!endif
|
||
|
|
||
|
|
||
|
H3: Configuration File Example
|
||
|
|
||
|
The following is an example configuration file, interspersed
|
||
|
with explanatory text. It defines two databases to handle
|
||
|
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
||
|
database instances. The line numbers shown are provided for
|
||
|
reference only and are not included in the actual file. First, the
|
||
|
global configuration section:
|
||
|
|
||
|
E: 1. # example config file - global configuration section
|
||
|
E: 2. include /usr/local/etc/schema/core.schema
|
||
|
E: 3. referral ldap://root.openldap.org
|
||
|
E: 4. access to * by * read
|
||
|
|
||
|
Line 1 is a comment. Line 2 includes another config file
|
||
|
which contains {{core}} schema definitions.
|
||
|
The {{EX:referral}} directive on line 3
|
||
|
means that queries not local to one of the databases defined
|
||
|
below will be referred to the LDAP server running on the
|
||
|
standard port (389) at the host {{EX:root.openldap.org}}.
|
||
|
|
||
|
Line 4 is a global access control. It applies to all
|
||
|
entries (after any applicable database-specific access
|
||
|
controls).
|
||
|
|
||
|
The next section of the configuration file defines a BDB
|
||
|
backend that will handle queries for things in the
|
||
|
"dc=example,dc=com" portion of the tree. The
|
||
|
database is to be replicated to two slave slapds, one on
|
||
|
truelies, the other on judgmentday. Indices are to be
|
||
|
maintained for several attributes, and the {{EX:userPassword}}
|
||
|
attribute is to be protected from unauthorized access.
|
||
|
|
||
|
E: 5. # BDB definition for the example.com
|
||
|
E: 6. database bdb
|
||
|
E: 7. suffix "dc=example,dc=com"
|
||
|
E: 8. directory /usr/local/var/openldap-data
|
||
|
E: 9. rootdn "cn=Manager,dc=example,dc=com"
|
||
|
E: 10. rootpw secret
|
||
|
E: 11. # indexed attribute definitions
|
||
|
E: 12. index uid pres,eq
|
||
|
E: 13. index cn,sn,uid pres,eq,approx,sub
|
||
|
E: 14. index objectClass eq
|
||
|
E: 15. # database access control definitions
|
||
|
E: 16. access to attrs=userPassword
|
||
|
E: 17. by self write
|
||
|
E: 18. by anonymous auth
|
||
|
E: 19. by dn.base="cn=Admin,dc=example,dc=com" write
|
||
|
E: 20. by * none
|
||
|
E: 21. access to *
|
||
|
E: 22. by self write
|
||
|
E: 23. by dn.base="cn=Admin,dc=example,dc=com" write
|
||
|
E: 24. by * read
|
||
|
|
||
|
Line 5 is a comment. The start of the database definition is marked
|
||
|
by the database keyword on line 6. Line 7 specifies the DN suffix
|
||
|
for queries to pass to this database. Line 8 specifies the directory
|
||
|
in which the database files will live.
|
||
|
|
||
|
Lines 9 and 10 identify the database {{super-user}} entry and associated
|
||
|
password. This entry is not subject to access control or size or
|
||
|
time limit restrictions.
|
||
|
|
||
|
Lines 12 through 14 indicate the indices to maintain for various
|
||
|
attributes.
|
||
|
|
||
|
Lines 16 through 24 specify access control for entries in this
|
||
|
database. As this is the first database, the controls also apply
|
||
|
to entries not held in any database (such as the Root DSE). For
|
||
|
all applicable entries, the {{EX:userPassword}} attribute is writable
|
||
|
by the entry itself and by the "admin" entry. It may be used for
|
||
|
authentication/authorization purposes, but is otherwise not readable.
|
||
|
All other attributes are writable by the entry and the "admin"
|
||
|
entry, but may be read by all users (authenticated or not).
|
||
|
|
||
|
The next section of the example configuration file defines another
|
||
|
BDB database. This one handles queries involving the
|
||
|
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
|
||
|
as the first database. Note that without line 39, the read access
|
||
|
would be allowed due to the global access rule at line 4.
|
||
|
|
||
|
E: 33. # BDB definition for example.net
|
||
|
E: 34. database bdb
|
||
|
E: 35. suffix "dc=example,dc=net"
|
||
|
E: 36. directory /usr/local/var/openldap-data-net
|
||
|
E: 37. rootdn "cn=Manager,dc=example,dc=com"
|
||
|
E: 38. index objectClass eq
|
||
|
E: 39. access to * by users read
|
||
|
|
||
|
H2: Dynamic Access Control Configuration
|
||
|
|
||
|
Access to slapd entries and attributes is controlled by the
|
||
|
olcAccess attribute, whose values are a sequence of access directives.
|
||
|
The general form of the olcAccess configuration is:
|
||
|
|
||
|
> olcAccess: <access directive>
|
||
|
> <access directive> ::= to <what>
|
||
|
> [by <who> [<access>] [<control>] ]+
|
||
|
> <what> ::= * |
|
||
|
> [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
|
||
|
> [filter=<ldapfilter>] [attrs=<attrlist>]
|
||
|
> <basic-style> ::= regex | exact
|
||
|
> <scope-style> ::= base | one | subtree | children
|
||
|
> <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
|
||
|
> <attr> ::= <attrname> | entry | children
|
||
|
> <who> ::= * | [anonymous | users | self
|
||
|
> | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
|
||
|
> [dnattr=<attrname>]
|
||
|
> [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
|
||
|
> [peername[.<basic-style>]=<regex>]
|
||
|
> [sockname[.<basic-style>]=<regex>]
|
||
|
> [domain[.<basic-style>]=<regex>]
|
||
|
> [sockurl[.<basic-style>]=<regex>]
|
||
|
> [set=<setspec>]
|
||
|
> [aci=<attrname>]
|
||
|
> <access> ::= [self]{<level>|<priv>}
|
||
|
> <level> ::= none | disclose | auth | compare | search | read | write | manage
|
||
|
> <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
|
||
|
> <control> ::= [stop | continue | break]
|
||
|
|
||
|
where the <what> part selects the entries and/or attributes to which
|
||
|
the access applies, the {{EX:<who>}} part specifies which entities
|
||
|
are granted access, and the {{EX:<access>}} part specifies the
|
||
|
access granted. Multiple {{EX:<who> <access> <control>}} triplets
|
||
|
are supported, allowing many entities to be granted different access
|
||
|
to the same set of entries and attributes. Not all of these access
|
||
|
control options are described here; for more details see the
|
||
|
{{slapd.access}}(5) man page.
|
||
|
|
||
|
|
||
|
H3: What to control access to
|
||
|
|
||
|
The <what> part of an access specification determines the entries
|
||
|
and attributes to which the access control applies. Entries are
|
||
|
commonly selected in two ways: by DN and by filter. The following
|
||
|
qualifiers select entries by DN:
|
||
|
|
||
|
> to *
|
||
|
> to dn[.<basic-style>]=<regex>
|
||
|
> to dn.<scope-style>=<DN>
|
||
|
|
||
|
The first form is used to select all entries. The second form may
|
||
|
be used to select entries by matching a regular expression against
|
||
|
the target entry's {{normalized DN}}. (The second form is not
|
||
|
discussed further in this document.) The third form is used to
|
||
|
select entries which are within the requested scope of DN. The
|
||
|
<DN> is a string representation of the Distinguished Name, as
|
||
|
described in {{REF:RFC4514}}.
|
||
|
|
||
|
The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
|
||
|
or {{EX:children}}. Where {{EX:base}} matches only the entry with
|
||
|
provided DN, {{EX:one}} matches the entries whose parent is the
|
||
|
provided DN, {{EX:subtree}} matches all entries in the subtree whose
|
||
|
root is the provided DN, and {{EX:children}} matches all entries
|
||
|
under the DN (but not the entry named by the DN).
|
||
|
|
||
|
For example, if the directory contained entries named:
|
||
|
|
||
|
> 0: o=suffix
|
||
|
> 1: cn=Manager,o=suffix
|
||
|
> 2: ou=people,o=suffix
|
||
|
> 3: uid=kdz,ou=people,o=suffix
|
||
|
> 4: cn=addresses,uid=kdz,ou=people,o=suffix
|
||
|
> 5: uid=hyc,ou=people,o=suffix
|
||
|
|
||
|
\Then:
|
||
|
. {{EX:dn.base="ou=people,o=suffix"}} match 2;
|
||
|
. {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
|
||
|
. {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
|
||
|
. {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
|
||
|
|
||
|
|
||
|
Entries may also be selected using a filter:
|
||
|
|
||
|
> to filter=<ldap filter>
|
||
|
|
||
|
where <ldap filter> is a string representation of an LDAP
|
||
|
search filter, as described in {{REF:RFC4515}}. For example:
|
||
|
|
||
|
> to filter=(objectClass=person)
|
||
|
|
||
|
Note that entries may be selected by both DN and filter by
|
||
|
including both qualifiers in the <what> clause.
|
||
|
|
||
|
> to dn.one="ou=people,o=suffix" filter=(objectClass=person)
|
||
|
|
||
|
Attributes within an entry are selected by including a comma-separated
|
||
|
list of attribute names in the <what> selector:
|
||
|
|
||
|
> attrs=<attribute list>
|
||
|
|
||
|
A specific value of an attribute is selected by using a single
|
||
|
attribute name and also using a value selector:
|
||
|
|
||
|
> attrs=<attribute> val[.<style>]=<regex>
|
||
|
|
||
|
There are two special {{pseudo}} attributes {{EX:entry}} and
|
||
|
{{EX:children}}. To read (and hence return) a target entry, the
|
||
|
subject must have {{EX:read}} access to the target's {{entry}}
|
||
|
attribute. To add or delete an entry, the subject must have
|
||
|
{{EX:write}} access to the entry's {{EX:entry}} attribute AND must
|
||
|
have {{EX:write}} access to the entry's parent's {{EX:children}}
|
||
|
attribute. To rename an entry, the subject must have {{EX:write}}
|
||
|
access to entry's {{EX:entry}} attribute AND have {{EX:write}}
|
||
|
access to both the old parent's and new parent's {{EX:children}}
|
||
|
attributes. The complete examples at the end of this section should
|
||
|
help clear things up.
|
||
|
|
||
|
Lastly, there is a special entry selector {{EX:"*"}} that is used to
|
||
|
select any entry. It is used when no other {{EX:<what>}}
|
||
|
selector has been provided. It's equivalent to "{{EX:dn=.*}}"
|
||
|
|
||
|
|
||
|
H3: Who to grant access to
|
||
|
|
||
|
The <who> part identifies the entity or entities being granted
|
||
|
access. Note that access is granted to "entities" not "entries."
|
||
|
The following table summarizes entity specifiers:
|
||
|
|
||
|
!block table; align=Center; coltags="EX,N"; \
|
||
|
title="Table 5.3: Access Entity Specifiers"
|
||
|
Specifier|Entities
|
||
|
*|All, including anonymous and authenticated users
|
||
|
anonymous|Anonymous (non-authenticated) users
|
||
|
users|Authenticated users
|
||
|
self|User associated with target entry
|
||
|
dn[.<basic-style>]=<regex>|Users matching a regular expression
|
||
|
dn.<scope-style>=<DN>|Users within scope of a DN
|
||
|
!endblock
|
||
|
|
||
|
The DN specifier behaves much like <what> clause DN specifiers.
|
||
|
|
||
|
Other control factors are also supported. For example, a {{EX:<who>}}
|
||
|
can be restricted by an entry listed in a DN-valued attribute in
|
||
|
the entry to which the access applies:
|
||
|
|
||
|
> dnattr=<dn-valued attribute name>
|
||
|
|
||
|
The dnattr specification is used to give access to an entry
|
||
|
whose DN is listed in an attribute of the entry (e.g., give
|
||
|
access to a group entry to whoever is listed as the owner of
|
||
|
the group entry).
|
||
|
|
||
|
Some factors may not be appropriate in all environments (or any).
|
||
|
For example, the domain factor relies on IP to domain name lookups.
|
||
|
As these can easily be spoofed, the domain factor should be avoided.
|
||
|
|
||
|
|
||
|
H3: The access to grant
|
||
|
|
||
|
The kind of <access> granted can be one of the following:
|
||
|
|
||
|
!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
|
||
|
title="Table 5.4: Access Levels"
|
||
|
Level Privileges Description
|
||
|
none =0 no access
|
||
|
disclose =d needed for information disclosure on error
|
||
|
auth =dx needed to authenticate (bind)
|
||
|
compare =cdx needed to compare
|
||
|
search =scdx needed to apply search filters
|
||
|
read =rscdx needed to read search results
|
||
|
write =wrscdx needed to modify/rename
|
||
|
manage =mwrscdx needed to manage
|
||
|
!endblock
|
||
|
|
||
|
Each level implies all lower levels of access. So, for example,
|
||
|
granting someone {{EX:write}} access to an entry also grants them
|
||
|
{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
|
||
|
{{EX:disclose}} access. However, one may use the privileges specifier
|
||
|
to grant specific permissions.
|
||
|
|
||
|
|
||
|
H3: Access Control Evaluation
|
||
|
|
||
|
When evaluating whether some requester should be given access to
|
||
|
an entry and/or attribute, slapd compares the entry and/or attribute
|
||
|
to the {{EX:<what>}} selectors given in the configuration. For
|
||
|
each entry, access controls provided in the database which holds
|
||
|
the entry (or the first database if not held in any database) apply
|
||
|
first, followed by the global access directives (which are held in
|
||
|
the {{EX:frontend}} database definition). Within this priority,
|
||
|
access directives are examined in the order in which they appear
|
||
|
in the configuration attribute. Slapd stops with the first
|
||
|
{{EX:<what>}} selector that matches the entry and/or attribute. The
|
||
|
corresponding access directive is the one slapd will use to evaluate
|
||
|
access.
|
||
|
|
||
|
Next, slapd compares the entity requesting access to the {{EX:<who>}}
|
||
|
selectors within the access directive selected above in the order
|
||
|
in which they appear. It stops with the first {{EX:<who>}} selector
|
||
|
that matches the requester. This determines the access the entity
|
||
|
requesting access has to the entry and/or attribute.
|
||
|
|
||
|
Finally, slapd compares the access granted in the selected
|
||
|
{{EX:<access>}} clause to the access requested by the client. If
|
||
|
it allows greater or equal access, access is granted. Otherwise,
|
||
|
access is denied.
|
||
|
|
||
|
The order of evaluation of access directives makes their placement
|
||
|
in the configuration file important. If one access directive is
|
||
|
more specific than another in terms of the entries it selects, it
|
||
|
should appear first in the configuration. Similarly, if one {{EX:<who>}}
|
||
|
selector is more specific than another it should come first in the
|
||
|
access directive. The access control examples given below should
|
||
|
help make this clear.
|
||
|
|
||
|
|
||
|
|
||
|
H3: Access Control Examples
|
||
|
|
||
|
The access control facility described above is quite powerful. This
|
||
|
section shows some examples of its use for descriptive purposes.
|
||
|
|
||
|
A simple example:
|
||
|
|
||
|
> olcAccess: to * by * read
|
||
|
|
||
|
This access directive grants read access to everyone.
|
||
|
|
||
|
> olcAccess: to *
|
||
|
> by self write
|
||
|
> by anonymous auth
|
||
|
> by * read
|
||
|
|
||
|
This directive allows the user to modify their entry, allows anonymous
|
||
|
to authenticate against these entries, and allows all others to
|
||
|
read these entries. Note that only the first {{EX:by <who>}} clause
|
||
|
which matches applies. Hence, the anonymous users are granted
|
||
|
{{EX:auth}}, not {{EX:read}}. The last clause could just as well
|
||
|
have been "{{EX:by users read}}".
|
||
|
|
||
|
It is often desirable to restrict operations based upon the level
|
||
|
of protection in place. The following shows how security strength
|
||
|
factors (SSF) can be used.
|
||
|
|
||
|
> olcAccess: to *
|
||
|
> by ssf=128 self write
|
||
|
> by ssf=64 anonymous auth
|
||
|
> by ssf=64 users read
|
||
|
|
||
|
This directive allows users to modify their own entries if security
|
||
|
protections of strength 128 or better have been established,
|
||
|
allows authentication access to anonymous users, and read access
|
||
|
when strength 64 or better security protections have been established. If
|
||
|
the client has not establish sufficient security protections, the
|
||
|
implicit {{EX:by * none}} clause would be applied.
|
||
|
|
||
|
The following example shows the use of style specifiers to select
|
||
|
the entries by DN in two access directives where ordering is
|
||
|
significant.
|
||
|
|
||
|
> olcAccess: to dn.children="dc=example,dc=com"
|
||
|
> by * search
|
||
|
> olcAccess: to dn.children="dc=com"
|
||
|
> by * read
|
||
|
|
||
|
Read access is granted to entries under the {{EX:dc=com}} subtree,
|
||
|
except for those entries under the {{EX:dc=example,dc=com}} subtree,
|
||
|
to which search access is granted. No access is granted to
|
||
|
{{EX:dc=com}} as neither access directive matches this DN. If the
|
||
|
order of these access directives was reversed, the trailing directive
|
||
|
would never be reached, since all entries under {{EX:dc=example,dc=com}}
|
||
|
are also under {{EX:dc=com}} entries.
|
||
|
|
||
|
Also note that if no {{EX:olcAccess: to}} directive matches or no {{EX:by
|
||
|
<who>}} clause, {{B:access is denied}}. That is, every {{EX:olcAccess:
|
||
|
to}} directive ends with an implicit {{EX:by * none}} clause and
|
||
|
every access list ends with an implicit {{EX:olcAccess: to * by * none}}
|
||
|
directive.
|
||
|
|
||
|
The next example again shows the importance of ordering, both of
|
||
|
the access directives and the {{EX:by <who>}} clauses. It also
|
||
|
shows the use of an attribute selector to grant access to a specific
|
||
|
attribute and various {{EX:<who>}} selectors.
|
||
|
|
||
|
> olcAccess: to dn.subtree="dc=example,dc=com" attrs=homePhone
|
||
|
> by self write
|
||
|
> by dn.children=dc=example,dc=com" search
|
||
|
> by peername.regex=IP:10\..+ read
|
||
|
> olcAccess: to dn.subtree="dc=example,dc=com"
|
||
|
> by self write
|
||
|
> by dn.children="dc=example,dc=com" search
|
||
|
> by anonymous auth
|
||
|
|
||
|
This example applies to entries in the "{{EX:dc=example,dc=com}}"
|
||
|
subtree. To all attributes except {{EX:homePhone}}, an entry can
|
||
|
write to itself, entries under {{EX:example.com}} entries can search
|
||
|
by them, anybody else has no access (implicit {{EX:by * none}})
|
||
|
excepting for authentication/authorization (which is always done
|
||
|
anonymously). The {{EX:homePhone}} attribute is writable by the
|
||
|
entry, searchable by entries under {{EX:example.com}}, readable by
|
||
|
clients connecting from network 10, and otherwise not readable
|
||
|
(implicit {{EX:by * none}}). All other access is denied by the
|
||
|
implicit {{EX:access to * by * none}}.
|
||
|
|
||
|
Sometimes it is useful to permit a particular DN to add or
|
||
|
remove itself from an attribute. For example, if you would like to
|
||
|
create a group and allow people to add and remove only
|
||
|
their own DN from the member attribute, you could accomplish
|
||
|
it with an access directive like this:
|
||
|
|
||
|
> olcAccess: to attrs=member,entry
|
||
|
> by dnattr=member selfwrite
|
||
|
|
||
|
The dnattr {{EX:<who>}} selector says that the access applies to
|
||
|
entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
|
||
|
selector says that such members can only add or delete their
|
||
|
own DN from the attribute, not other values. The addition of
|
||
|
the entry attribute is required because access to the entry is
|
||
|
required to access any of the entry's attributes.
|
||
|
|
||
|
|
||
|
|
||
|
H3: Access Control Ordering
|
||
|
|
||
|
Since the ordering of {{EX:olcAccess}} directives is essential to their
|
||
|
proper evaluation, but LDAP attributes normally do not preserve the
|
||
|
ordering of their values, OpenLDAP uses a custom schema extension to
|
||
|
maintain a fixed ordering of these values. This ordering is maintained
|
||
|
by prepending a {{EX:"{X}"}} numeric index to each value, similarly to
|
||
|
the approach used for ordering the configuration entries. These index
|
||
|
tags are maintained automatically by slapd and do not need to be specified
|
||
|
when originally defining the values. For example, when you create the
|
||
|
settings
|
||
|
|
||
|
> olcAccess: to attrs=member,entry
|
||
|
> by dnattr=member selfwrite
|
||
|
> olcAccess: to dn.children="dc=example,dc=com"
|
||
|
> by * search
|
||
|
> olcAccess: to dn.children="dc=com"
|
||
|
> by * read
|
||
|
|
||
|
when you read them back using slapcat or ldapsearch they will contain
|
||
|
|
||
|
> olcAccess: {0}to attrs=member,entry
|
||
|
> by dnattr=member selfwrite
|
||
|
> olcAccess: {1}to dn.children="dc=example,dc=com"
|
||
|
> by * search
|
||
|
> olcAccess: {2}to dn.children="dc=com"
|
||
|
> by * read
|
||
|
|
||
|
The numeric index may be used to specify a particular value to change
|
||
|
when using ldapmodify to edit the access rules. This index can be used
|
||
|
instead of (or in addition to) the actual access value. Using this
|
||
|
numeric index is very helpful when multiple access rules are being managed.
|
||
|
|
||
|
For example, if we needed to change the second rule above to grant
|
||
|
write access instead of search, we could try this LDIF:
|
||
|
|
||
|
> changetype: modify
|
||
|
> delete: olcAccess
|
||
|
> olcAccess: to dn.children="dc=example,dc=com" by * search
|
||
|
> -
|
||
|
> add: olcAccess
|
||
|
> olcAccess: to dn.children="dc=example,dc=com" by * write
|
||
|
> -
|
||
|
|
||
|
But this example {{B:will not}} guarantee that the existing values remain in
|
||
|
their original order, so it will most likely yield a broken security
|
||
|
configuration. Instead, the numeric index should be used:
|
||
|
|
||
|
> changetype: modify
|
||
|
> delete: olcAccess
|
||
|
> olcAccess: {1}
|
||
|
> -
|
||
|
> add: olcAccess
|
||
|
> olcAccess: {1}to dn.children="dc=example,dc=com" by * write
|
||
|
> -
|
||
|
|
||
|
This example deletes whatever rule is in value #1 of the {{EX:olcAccess}}
|
||
|
attribute (regardless of its value) and adds a new value that is
|
||
|
explicitly inserted as value #1. The result will be
|
||
|
|
||
|
> olcAccess: {0}to attrs=member,entry
|
||
|
> by dnattr=member selfwrite
|
||
|
> olcAccess: {1}to dn.children="dc=example,dc=com"
|
||
|
> by * write
|
||
|
> olcAccess: {2}to dn.children="dc=com"
|
||
|
> by * read
|
||
|
|
||
|
which is exactly what was intended.
|
||
|
|
||
|
!if 0
|
||
|
For more details on how to use the {{EX:access}} directive,
|
||
|
consult the {{Advanced Access Control}} chapter.
|
||
|
!endif
|
||
|
|
||
|
|
||
|
H3: Configuration Example
|
||
|
|
||
|
The following is an example configuration, interspersed
|
||
|
with explanatory text. It defines two databases to handle
|
||
|
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
||
|
database instances. The line numbers shown are provided for
|
||
|
reference only and are not included in the actual file. First, the
|
||
|
global configuration section:
|
||
|
|
||
|
E: 1. # example config file - global configuration entry
|
||
|
E: 2. dn: cn=config
|
||
|
E: 3. objectClass: olcGlobal
|
||
|
E: 4. cn: config
|
||
|
E: 5. olcReferral: ldap://root.openldap.org
|
||
|
E: 6.
|
||
|
|
||
|
Line 1 is a comment. Lines 2-4 identify this as the global
|
||
|
configuration entry.
|
||
|
The {{EX:olcReferral:}} directive on line 5
|
||
|
means that queries not local to one of the databases defined
|
||
|
below will be referred to the LDAP server running on the
|
||
|
standard port (389) at the host {{EX:root.openldap.org}}.
|
||
|
Line 6 is a blank line, indicating the end of this entry.
|
||
|
|
||
|
E: 7. # internal schema
|
||
|
E: 8. dn: cn=schema,cn=config
|
||
|
E: 9. objectClass: olcSchemaConfig
|
||
|
E: 10. cn: schema
|
||
|
E: 11.
|
||
|
|
||
|
Line 7 is a comment. Lines 8-10 identify this as the root of
|
||
|
the schema subtree. The actual schema definitions in this entry
|
||
|
are hardcoded into slapd so no additional attributes are specified here.
|
||
|
Line 11 is a blank line, indicating the end of this entry.
|
||
|
|
||
|
E: 12. # include the core schema
|
||
|
E: 13. include: file:///usr/local/etc/openldap/schema/core.ldif
|
||
|
E: 14.
|
||
|
|
||
|
Line 12 is a comment. Line 13 is an LDIF include directive which
|
||
|
accesses the {{core}} schema definitions in LDIF format. Line 14
|
||
|
is a blank line.
|
||
|
|
||
|
Next comes the database definitions. The first database is the
|
||
|
special {{EX:frontend}} database whose settings are applied globally
|
||
|
to all the other databases.
|
||
|
|
||
|
E: 15. # global database parameters
|
||
|
E: 16. dn: olcDatabase=frontend,cn=config
|
||
|
E: 17. objectClass: olcDatabaseConfig
|
||
|
E: 18. olcDatabase: frontend
|
||
|
E: 19. olcAccess: to * by * read
|
||
|
E: 20.
|
||
|
|
||
|
Line 15 is a comment. Lines 16-18 identify this entry as the global
|
||
|
database entry. Line 19 is a global access control. It applies to all
|
||
|
entries (after any applicable database-specific access controls).
|
||
|
|
||
|
The next entry defines a BDB backend that will handle queries for things
|
||
|
in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
|
||
|
for several attributes, and the {{EX:userPassword}} attribute is to be
|
||
|
protected from unauthorized access.
|
||
|
|
||
|
E: 21. # BDB definition for example.com
|
||
|
E: 22. dn: olcDatabase=bdb,cn=config
|
||
|
E: 23. objectClass: olcDatabaseConfig
|
||
|
E: 24. objectClass: olcBdbConfig
|
||
|
E: 25. olcDatabase: bdb
|
||
|
E: 26. olcSuffix: "dc=example,dc=com"
|
||
|
E: 27. olcDbDirectory: /usr/local/var/openldap-data
|
||
|
E: 28. olcRootDN: "cn=Manager,dc=example,dc=com"
|
||
|
E: 29. olcRootPW: secret
|
||
|
E: 30. olcDbIndex: uid pres,eq
|
||
|
E: 31. olcDbIndex: cn,sn,uid pres,eq,approx,sub
|
||
|
E: 32. olcDbIndex: objectClass eq
|
||
|
E: 33. olcAccess: to attrs=userPassword
|
||
|
E: 34. by self write
|
||
|
E: 35. by anonymous auth
|
||
|
E: 36. by dn.base="cn=Admin,dc=example,dc=com" write
|
||
|
E: 37. by * none
|
||
|
E: 38. olcAccess: to *
|
||
|
E: 39. by self write
|
||
|
E: 40. by dn.base="cn=Admin,dc=example,dc=com" write
|
||
|
E: 41. by * read
|
||
|
E: 42.
|
||
|
|
||
|
Line 21 is a comment. Lines 22-25 identify this entry as a BDB database
|
||
|
configuration entry. Line 26 specifies the DN suffix
|
||
|
for queries to pass to this database. Line 27 specifies the directory
|
||
|
in which the database files will live.
|
||
|
|
||
|
Lines 28 and 29 identify the database {{super-user}} entry and associated
|
||
|
password. This entry is not subject to access control or size or
|
||
|
time limit restrictions.
|
||
|
|
||
|
Lines 30 through 32 indicate the indices to maintain for various
|
||
|
attributes.
|
||
|
|
||
|
Lines 33 through 41 specify access control for entries in this
|
||
|
database. As this is the first database, the controls also apply
|
||
|
to entries not held in any database (such as the Root DSE). For
|
||
|
all applicable entries, the {{EX:userPassword}} attribute is writable
|
||
|
by the entry itself and by the "admin" entry. It may be used for
|
||
|
authentication/authorization purposes, but is otherwise not readable.
|
||
|
All other attributes are writable by the entry and the "admin"
|
||
|
entry, but may be read by all users (authenticated or not).
|
||
|
|
||
|
Line 42 is a blank line, indicating the end of this entry.
|
||
|
|
||
|
The next section of the example configuration file defines another
|
||
|
BDB database. This one handles queries involving the
|
||
|
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
|
||
|
as the first database. Note that without line 52, the read access
|
||
|
would be allowed due to the global access rule at line 19.
|
||
|
|
||
|
E: 43. # BDB definition for example.net
|
||
|
E: 44. dn: olcDatabase=bdb,cn=config
|
||
|
E: 45. objectClass: olcDatabaseConfig
|
||
|
E: 46. objectClass: olcBdbConfig
|
||
|
E: 47. olcDatabase: bdb
|
||
|
E: 48. olcSuffix: "dc=example,dc=net"
|
||
|
E: 49. olcDbDirectory: /usr/local/var/openldap-data-net
|
||
|
E: 50. olcRootDN: "cn=Manager,dc=example,dc=com"
|
||
|
E: 51. olcDbIndex: objectClass eq
|
||
|
E: 52. olcAccess: to * by users read
|
||
|
|
||
|
|
||
|
H3: Converting from slapd.conf(8) to a {{B:cn=config}} directory format
|
||
|
|
||
|
Discuss slap* -f slapd.conf -F slapd.d/ (man slapd-config)
|
||
|
|
||
|
|
||
|
H2: Sets - Granting rights based on relationships
|
||
|
|
||
|
Sets are best illustrated via examples. The following sections will present
|
||
|
a few set ACL examples in order to facilitate their understanding.
|
||
|
|
||
|
(Sets in Access Controls FAQ Entry: {{URL:http://www.openldap.org/faq/data/cache/1133.html}})
|
||
|
|
||
|
Note: Sets are considered experimental.
|
||
|
|
||
|
|
||
|
H3: Groups of Groups
|
||
|
|
||
|
The OpenLDAP ACL for groups doesn't expand groups within groups, which are
|
||
|
groups that have another group as a member. For example:
|
||
|
|
||
|
> dn: cn=sudoadm,ou=group,dc=example,dc=com
|
||
|
> cn: sudoadm
|
||
|
> objectClass: groupOfNames
|
||
|
> member: uid=john,ou=people,dc=example,dc=com
|
||
|
> member: cn=accountadm,ou=group,dc=example,dc=com
|
||
|
>
|
||
|
> dn: cn=accountadm,ou=group,dc=example,dc=com
|
||
|
> cn: accountadm
|
||
|
> objectClass: groupOfNames
|
||
|
> member: uid=mary,ou=people,dc=example,dc=com
|
||
|
|
||
|
If we use standard group ACLs with the above entries and allow members of the
|
||
|
{{F:sudoadm}} group to write somewhere, {{F:mary}} won't be included:
|
||
|
|
||
|
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
|
||
|
> by group.exact="cn=sudoadm,ou=group,dc=example,dc=com" write
|
||
|
> by * read
|
||
|
|
||
|
With sets we can make the ACL be recursive and consider group within groups. So
|
||
|
for each member that is a group, it is further expanded:
|
||
|
|
||
|
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
|
||
|
> by set="[cn=sudoadm,ou=group,dc=example,dc=com]/member* & user" write
|
||
|
> by * read
|
||
|
|
||
|
This set ACL means: take the {{F:cn=sudoadm}} DN, check its {{F:member}}
|
||
|
attribute(s) (where the "{{F:*}}" means recursively) and intersect the result
|
||
|
with the authenticated user's DN. If the result is non-empty, the ACL is
|
||
|
considered a match and write access is granted.
|
||
|
|
||
|
The following drawing explains how this set is built:
|
||
|
!import "set-recursivegroup.png"; align="center"; title="Building a recursive group"
|
||
|
FT[align="Center"] Figure X.Y: Populating a recursive group set
|
||
|
|
||
|
First we get the {{F:uid=john}} DN. This entry doesn't have a {{F:member}}
|
||
|
attribute, so the expansion stops here. Now we get to {{F:cn=accountadm}}.
|
||
|
This one does have a {{F:member}} attribute, which is {{F:uid=mary}}. The
|
||
|
{{F:uid=mary}} entry, however, doesn't have member, so we stop here again. The
|
||
|
end comparison is:
|
||
|
|
||
|
> {"uid=john,ou=people,dc=example,dc=com","uid=mary,ou=people,dc=example,dc=com"} & user
|
||
|
|
||
|
If the authenticated user's DN is any one of those two, write access is
|
||
|
granted. So this set will include {{F:mary}} in the {{F:sudoadm}} group and she
|
||
|
will be allowed the write access.
|
||
|
|
||
|
H3: Group ACLs without DN syntax
|
||
|
|
||
|
The traditional group ACLs, and even the previous example about recursive groups, require
|
||
|
that the members are specified as DNs instead of just usernames.
|
||
|
|
||
|
With sets, however, it's also possible to use simple names in group ACLs, as this example will
|
||
|
show.
|
||
|
|
||
|
Let's say we want to allow members of the {{F:sudoadm}} group to write to the
|
||
|
{{F:ou=suders}} branch of our tree. But our group definition now is using {{F:memberUid}} for
|
||
|
the group members:
|
||
|
|
||
|
> dn: cn=sudoadm,ou=group,dc=example,dc=com
|
||
|
> cn: sudoadm
|
||
|
> objectClass: posixGroup
|
||
|
> gidNumber: 1000
|
||
|
> memberUid: john
|
||
|
|
||
|
With this type of group, we can't use group ACLs. But with a set ACL we can
|
||
|
grant the desired access:
|
||
|
|
||
|
> access to dn.subtree="ou=sudoers,dc=example,dc=com"
|
||
|
> by set="[cn=sudoadm,ou=group,dc=example,dc=com]/memberUid & user/uid" write
|
||
|
> by * read
|
||
|
|
||
|
We use a simple intersection where we compare the {{F:uid}} attribute
|
||
|
of the connecting (and authenticated) user with the {{F:memberUid}} attributes
|
||
|
of the group. If they match, the intersection is non-empty and the ACL will
|
||
|
grant write access.
|
||
|
|
||
|
This drawing illustrates this set when the connecting user is authenticated as
|
||
|
{{F:uid=john,ou=people,dc=example,dc=com}}:
|
||
|
!import "set-memberUid.png"; align="center"; title="Sets with memberUid"
|
||
|
FT[align="Center"] Figure X.Y: Sets with {{F:memberUid}}
|
||
|
|
||
|
In this case, it's a match. If it were {{F:mary}} authenticating, however, she
|
||
|
would be denied write access to {{F:ou=sudoers}} because her {{F:uid}}
|
||
|
attribute is not listed in the group's {{F:memberUid}}.
|
||
|
|
||
|
H3: Following references
|
||
|
|
||
|
We will now show a quite powerful example of what can be done with sets. This
|
||
|
example tends to make OpenLDAP administrators smile after they have understood
|
||
|
it and its implications.
|
||
|
|
||
|
Let's start with an user entry:
|
||
|
|
||
|
> dn: uid=john,ou=people,dc=example,dc=com
|
||
|
> uid: john
|
||
|
> objectClass: inetOrgPerson
|
||
|
> givenName: John
|
||
|
> sn: Smith
|
||
|
> cn: john
|
||
|
> manager: uid=mary,ou=people,dc=example,dc=com
|
||
|
|
||
|
Writing an ACL to allow the manager to update some attributes is quite simple
|
||
|
using sets:
|
||
|
|
||
|
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
|
||
|
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
|
||
|
> by self write
|
||
|
> by set="this/manager & user" write
|
||
|
> by * read
|
||
|
|
||
|
In that set, {{F:this}} expands to the entry being accessed, so that
|
||
|
{{F:this/manager}} expands to {{F:uid=mary,ou=people,dc=example,dc=com}} when
|
||
|
john's entry is accessed. If the manager herself is accessing John's entry,
|
||
|
the ACL will match and write access to those attributes will be granted.
|
||
|
|
||
|
So far, this same behavior can be obtained with the {{F:dnattr}} keyword. With
|
||
|
sets, however, we can further enhance this ACL. Let's say we want to allow the
|
||
|
secretary of the manager to also update these attributes. This is how we do it:
|
||
|
|
||
|
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
|
||
|
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
|
||
|
> by self write
|
||
|
> by set="this/manager & user" write
|
||
|
> by set="this/manager/secretary & user" write
|
||
|
> by * read
|
||
|
|
||
|
Now we need a picture to help explain what is happening here (entries shortened
|
||
|
for clarity):
|
||
|
|
||
|
!import "set-following-references.png"; align="center"; title="Sets jumping through entries"
|
||
|
FT[align="Center"] Figure X.Y: Sets jumping through entries
|
||
|
|
||
|
In this example, Jane is the secretary of Mary, which is the manager of John.
|
||
|
This whole relationship is defined with the {{F:manager}} and {{F:secretary}}
|
||
|
attributes, which are both of the distinguishedName syntax (i.e., full DNs).
|
||
|
So, when the {{F:uid=john}} entry is being accessed, the
|
||
|
{{F:this/manager/secretary}} set becomes
|
||
|
{{F:{"uid=jane,ou=people,dc=example,dc=com"}}} (follow the references in the
|
||
|
picture):
|
||
|
|
||
|
> this = [uid=john,ou=people,dc=example,dc=com]
|
||
|
> this/manager = \
|
||
|
> [uid=john,ou=people,dc=example,dc=com]/manager = uid=mary,ou=people,dc=example,dc=com
|
||
|
> this/manager/secretary = \
|
||
|
> [uid=mary,ou=people,dc=example,dc=com]/secretary = uid=jane,ou=people,dc=example,dc=com
|
||
|
|
||
|
The end result is that when Jane accesses John's entry, she will be granted
|
||
|
write access to the specified attributes. Better yet, this will happen to any
|
||
|
entry she accesses which has Mary as the manager.
|
||
|
|
||
|
This is all cool and nice, but perhaps gives to much power to secretaries. Maybe we need to further
|
||
|
restrict it. For example, let's only allow executive secretaries to have this power:
|
||
|
|
||
|
> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
|
||
|
> attrs=carLicense,homePhone,mobile,pager,telephoneNumber
|
||
|
> by self write
|
||
|
> by set="this/manager & user" write
|
||
|
> by set="this/manager/secretary &
|
||
|
> [cn=executive,ou=group,dc=example,dc=com]/member* &
|
||
|
> user" write
|
||
|
> by * read
|
||
|
|
||
|
It's almost the same ACL as before, but we now also require that the connecting user be a member
|
||
|
of the (possibly nested) {{F:cn=executive}} group.
|
||
|
|
||
|
|