diff --git a/doc/guide/admin/Makefile b/doc/guide/admin/Makefile index f71513c919be008b0b0085f4d2466ebfcfe99aca..dfd373d0a97ec8be9f785060de50c8012b92eaf8 100644 --- a/doc/guide/admin/Makefile +++ b/doc/guide/admin/Makefile @@ -21,6 +21,7 @@ sdf-src: \ ../plain.sdf \ ../preamble.sdf \ abstract.sdf \ + access-control.sdf \ appendix-changes.sdf \ appendix-common-errors.sdf \ appendix-configs.sdf \ @@ -65,7 +66,10 @@ sdf-img: \ dual_dc.png \ intro_dctree.png \ intro_tree.png \ - refint.png + refint.png \ + set-following-references.png \ + set-memberUid.png \ + set-recursivegroup.png guide.html: guide.sdf sdf-src sdf-img sdf -2html guide.sdf diff --git a/doc/guide/admin/access-control.sdf b/doc/guide/admin/access-control.sdf new file mode 100644 index 0000000000000000000000000000000000000000..a60a341052f09dd837c49142ea02fe992cda5ddd --- /dev/null +++ b/doc/guide/admin/access-control.sdf @@ -0,0 +1,1539 @@ +# $OpenLDAP$ +# Copyright 1999-2008 The OpenLDAP Foundation, All Rights Reserved. +# COPYING RESTRICTIONS APPLY, see COPYRIGHT. + +H1: Access Control + +H2: Introduction + +As the directory gets populated with more and more data of varying sensitivity, +controlling the kinds of access granted to the directory becomes more and more +critical. For instance, the directory may contain data of a confidential nature +that you may need to protect by contract or by law. Or, if using the directory +to control access to other services, inappropriate access to the directory may +create avenues of attack to your sites security that result in devastating +damage to your assets. + +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}}). + +The default access control policy is allow read by all clients. Regardless of +what access control policy is defined, the {{rootdn}} is always allowed full +rights (i.e. auth, search, compare, read and write) on everything and anything. + +As a consequence, it's useless (and results in a performance penalty) to explicitly +list the {{rootdn}} among the {{<by>}} clauses. + +The following sections will describe Access Control Lists in more details and +follow with some examples and recommendations. + +H2: Access Control via Static 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: Access Control via Dynamic 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}}(5) to a {{B:cn=config}} directory format + +Discuss slap* -f slapd.conf -F slapd.d/ (man slapd-config) + + +H2: Access Control Common Examples + +H3: Basic ACLs + +Generally one should start with some basic ACLs such as: + +> access to attr=userPassword +> by self =xw +> by anonymous auth +> by * none +> +> +> access to * +> by self write +> by users read +> by * none + +The first ACL allows users to update (but not read) their passwords, anonymous +users to authenticate against this attribute, and (implicitly) denying all +access to others. + +The second ACL allows users full access to their entry, authenticated users read +access to anything, and (implicitly) denying all access to others (in this case, +anonymous users). + + +H3: Matching Anonymous and Authenticated users + +An anonymous user has a empty DN. While the {{dn.exact=""}} or {{dn.regex="^$"}} + could be used, {{slapd}}(8)) offers an anonymous shorthand which should be +used instead. + +> access to * +> by anonymous none +> by * read + +denies all access to anonymous users while granting others read. + +Authenticated users have a subject DN. While {{dn.regex=".+"}} will match any +authenticated user, OpenLDAP provides the users short hand which should be used +instead. + +> access to * +> by users read +> by * none + +This ACL grants read permissions to authenticated users while denying others +(i.e.: anonymous users). + + +H3: Controlling rootdn access + +You could specify the {{rootdn}} in {{slapd.conf}}(5) or {[slapd.d}} without +specifying a {{rootpw}}. Then you have to add an actual directory entry with +the same dn, e.g.: + +> dn: cn=Manager,o=MyOrganization +> cn: Manager +> sn: Manager +> objectClass: person +> objectClass: top +> userPassword: {SSHA}someSSHAdata + +Then binding as the {{rootdn}} will require a regular bind to that DN, which +in turn requires auth access to that entry's DN and {{userPassword}}, and this +can be restricted via ACLs. E.g.: + +> access to dn.base="cn=Manager,o=MyOrganization" +> by peername.regex=127\.0\.0\.1 auth +> by peername.regex=192\.168\.0\..* auth +> by users none +> by * none + +The ACLs above will only allow binding using rootdn from localhost and +192.168.0.0/24. + + +H3: Managing access with Groups + +There are a few ways to do this. One approach is illustrated here. Consider the +following DIT layout: + +> +-dc=example,dc=com +> +---cn=administrators,dc=example,dc=com +> +---cn=fred blogs,dc=example,dc=com + +and the following group object (in LDIF format): + +> dn: cn=administrators,dc=example,dc=com +> cn: administrators of this region +> objectclass: groupOfNames (important for the group acl feature) +> member: cn=fred blogs,dc=example,dc=com +> member: cn=somebody else,dc=example,dc=com + +One can then grant access to the members of this this group by adding appropriate +{{by group}} clause to an access directive in {{slapd.conf}}(5). For instance, + +> access to dn.children="dc=example,dc=com" +> by self write +> by group.exact="cn=Administrators,dc=example,dc=com" write +> by * auth + +Like by {[dn}} clauses, one can also use {{expand}} to expand the group name +based upon the regular expression matching of the target, that is, the to {{dn.regex}}). +For instance, + +> access to dn.regex="(.+,)?ou=People,(dc=[^,]+,dc=[^,]+)$" +> attrs=children,entry,uid +> by group.expand="cn=Managers,$2" write +> by users read +> by * auth + + +The above illustration assumed that the group members are to be found in the +{{member}} attribute type of the {{groupOfNames}} object class. If you need to +use a different group object and/or a different attribute type then use the +following {{slapd.conf}}(5) (abbreviated) syntax: + +> access to <what> +> by group/<objectclass>/<attributename>=<DN> <access> + +For example: + +> access to * +> by group/organizationalRole/roleOccupant="cn=Administrator,dc=example,dc=com" write + +In this case, we have an ObjectClass {{organizationalRole}} which contains the +administrator DN's in the {{roleOccupant}} attribute. For instance: + +> dn: cn=Administrator,dc=example,dc=com +> cn: Administrator +> objectclass: organizationalRole +> roleOccupant: cn=Jane Doe,dc=example,dc=com + +Note: the specified member attribute type MUST be of DN or {{NameAndOptionalUID}} syntax, +and the specified object class SHOULD allow the attribute type. + +Dynamic Groups are also supported in Access Control. Please see {{slapo-dynlist}}(5) +and the {{SECT:Dynamic Lists}} overlay section. + + +H3: Granting access to a subset of attributes + +You can grant access to a set of attributes by specifying a list of attribute names +in the ACL {{to}} clause. To be useful, you also need to grant access to the +{{entry}} itself. Also note how {{children}} controls the ability to add, delete, +and rename entries. + +> # mail: self may write, authenticated users may read +> access to attrs=mail +> by self write +> by users read +> by * none +> +> # cn, sn: self my write, all may read +> access to attrs=cn,sn +> by self write +> by * read +> +> # immediate children: only self can add/delete entries under this entry +> access to attrs=children +> by self write +> +> # entry itself: self may write, all may read +> access to attrs=entry +> by self write +> by * read +> +> # other attributes: self may write, others have no access +> access to * +> by self write +> by * none + +ObjectClass names may also be specified in this list, which will affect +all the attributes that are required and/or allowed by that {{objectClass}}. +Actually, names in {{attrlist}} that are prefixed by {{@}} are directly treated +as objectClass names. A name prefixed by {{!}} is also treated as an objectClass, +but in this case the access rule affects the attributes that are not required +nor allowed by that {{objectClass}}. + + +H3: Allowing a user write to all entries below theirs + +For a setup where a user can write to its own record and to all of its children: + +> access to dn.regex="(.+,)?(uid=[^,]+,o=Company)$" +> by dn.exact,expand="$2" write +> by anonymous auth + +(Add more examples for above) + + +H3: Allowing entry creation + +Let's say, you have it like this: + +> o=<basedn> +> ou=domains +> associatedDomain=<somedomain> +> ou=users +> uid=<someuserid> +> uid=<someotheruserid> +> ou=addressbooks +> uid=<someuserid> +> cn=<someone> +> cn=<someoneelse> + +and, for another domain <someotherdomain>: + +> o=<basedn> +> ou=domains +> associatedDomain=<someotherdomain> +> ou=users +> uid=<someuserid> +> uid=<someotheruserid> +> ou=addressbooks +> uid=<someotheruserid> +> cn=<someone> +> cn=<someoneelse> + +then, if you wanted user {{uid=<someuserid>}} to {{B:ONLY}} create an entry +for its own thing, you could write an ACL like this: + +> # this rule lets users of "associatedDomain=<matcheddomain>" +> # write under "ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>", +> # i.e. a user can write ANY entry below its domain's address book; +> # this permission is necessary, but not sufficient, the next +> # will restrict this permission further +> +> +> access to dn.regex="^ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$" attrs=children +> by dn.regex="^uid=([^,]+),ou=users,associatedDomain=$1,ou=domains,o=<basedn>$$" write +> by * none +> +> +> # Note that above the "by" clause needs a "regex" style to make sure +> # it expands to a DN that starts with a "uid=<someuserid>" pattern +> # while substituting the associatedDomain submatch from the "what" clause. +> +> +> # This rule lets a user with "uid=<matcheduid>" of "<associatedDomain=matcheddomain>" +> # write (i.e. add, modify, delete) the entry whose DN is exactly +> # "uid=<matcheduid>,ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>" +> # and ANY entry as subtree of it +> +> +> access to dn.regex="^(.+,)?uid=([^,]+),ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$" +> by dn.exact,expand="uid=$2,ou=users,associatedDomain=$3,ou=domains,o=<basedn>" write +> by * none +> +> +> # Note that above the "by" clause uses the "exact" style with the "expand" +> # modifier because now the whole pattern can be rebuilt by means of the +> # submatches from the "what" clause, so a "regex" compilation and evaluation +> # is no longer required. + + +H3: Tips for using regular expressions in Access Control + +Always use {{dn.regex=<pattern>}} when you intend to use regular expression +matching. {{dn=<pattern>}} alone defaults to {{dn.exact<pattern>}}. + +Use {{(.+)}} instead of {{(.*)}} when you want at least one char to be matched. +{{(.*)}} matches the empty string as well. + +Don't use regular expressions for matches that can be done otherwise in a safer +and cheaper manner. Examples: + +> dn.regex=".*dc=example,dc=com" + +is unsafe and expensive: + + * unsafe because any string containing {{dc=example,dc=com }}will match, +not only those that end with the desired pattern; use {{.*dc=example,dc=com$}} instead. + * unsafe also because it would allow any {{attributeType}} ending with {{dc}} + as naming attribute for the first RDN in the string, e.g. a custom attributeType +{{mydc}} would match as well. If you really need a regular expression that allows +just {{dc=example,dc=com}} or any of its subtrees, use {{^(.+,)?dc=example,dc=com$}}, +which means: anything to the left of dc=..., if any (the question mark after the +pattern within brackets), must end with a comma; + * expensive because if you don't need submatches, you could use scoping styles, e.g. + +> dn.subtree="dc=example,dc=com" + +to include {{dc=example,dc=com}} in the matching patterns, + +> dn.children="dc=example,dc=com" + +to exclude {{dc=example,dc=com}} from the matching patterns, or + +> dn.onelevel="dc=example,dc=com" + +to allow exactly one sublevel matches only. + +Always use {{^}} and {{$}} in regexes, whenever appropriate, because +{{ou=(.+),ou=(.+),ou=addressbooks,o=basedn}} will match +{{something=bla,ou=xxx,ou=yyy,ou=addressbooks,o=basedn,ou=addressbooks,o=basedn,dc=some,dc=org}} + +Always use {{([^,]+)}} to indicate exactly one RDN, because {{(.+)}} can +include any number of RDNs; e.g. {{ou=(.+),dc=example,dc=com}} will match +{{ou=My,o=Org,dc=example,dc=com}}, which might not be what you want. + +Never add the rootdn to the by clauses. ACLs are not even processed for operations +performed with rootdn identity (otherwise there would be no reason to define a +rootdn at all). + +Use shorthands. The user directive matches authenticated users and the anonymous +directive matches anonymous users. + +Don't use the {{dn.regex}} form for <by> clauses if all you need is scoping +and/or substring replacement; use scoping styles (e.g. {{exact}}, {{onelevel}}, +{{children}} or {{subtree}}) and the style modifier expand to cause substring expansion. + +For instance, + +> access to dn.regex=".+,dc=([^,]+),dc=([^,]+)$" +> by dn.regex="^[^,],ou=Admin,dc=$1,dc=$2$$" write + +although correct, can be safely and efficiently replaced by + +> access to dn.regex=".+,(dc=[^,]+,dc=[^,]+)$" +> by dn.onelevel,expand="ou=Admin,$1" write + +where the regex in the {{<what>}} clause is more compact, and the one in the {{<by>}} +clause is replaced by a much more efficient scoping style of onelevel with substring expansion. + + +H3: Granting and Denying access based on security strength factors (ssf) + +You can restrict access based on the security strength factor (SSF) + +> access to dn="cn=example,cn=edu" +> by * ssf=256 read + +0 (zero) implies no protection, +1 implies integrity protection only, +56 DES or other weak ciphers, +112 triple DES and other strong ciphers, +128 RC4, Blowfish and other modern strong ciphers. + +Other possibilities: + +> transport_ssf=<n> +> tls_ssf=<n> +> sasl_ssf=<n> + +256 is recommended. + +See {{slapd.conf}}(5) for information on {{ssf}}. + + +H3: When things aren't working as expected + +Consider this example: + +> access to * +> by anonymous auth +> +> access to * +> by self write +> +> access to * +> by users read + +You may think this will allow any user to login, to read everything and change +his own data if he is logged in. But in this example only the login works and +an ldapsearch returns no data. The Problem is that SLAPD goes through its access +config line by line and stops as soon as it finds a match in the part of the +access rule.(here: {{to *}}) + +To get what we wanted the file has to read: + +> access to * +> by anonymous auth +> by self write +> by users read + +The general rule is: "special access rules first, generic access rules last" + +See also {{slapd.access}}(8), loglevel 128 and {{slapacl}}(8) for debugging +information. + + +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. + + diff --git a/doc/guide/admin/aspell.en.pws b/doc/guide/admin/aspell.en.pws index 086f7d98ea60516a8433b648ea289fc0b1d64bbe..fe6a20d2f624b7980d4d4a842fd319fe83e38238 100644 --- a/doc/guide/admin/aspell.en.pws +++ b/doc/guide/admin/aspell.en.pws @@ -1,4 +1,4 @@ -personal_ws-1.1 en 1559 +personal_ws-1.1 en 1567 commonName Masarati subjectAltName @@ -36,8 +36,8 @@ DIB dev reqNewSuperior librewrite -memberof memberOf +memberof BSI updateref buf @@ -85,8 +85,8 @@ dlopen eng AttributeValue attributevalue -DUA EOF +DUA inputfile DSP refreshDone @@ -112,6 +112,7 @@ GHz Bint memalloc FSF +usernames strtol idl IDN @@ -120,10 +121,10 @@ iff contextCSN auditModify auditSearch -OpenLDAP openldap -resultcode +OpenLDAP resultCode +resultcode sysconfig indices blen @@ -156,13 +157,13 @@ argv kdz notAllowedOnRDN hostport -StartTLS starttls +StartTLS ldb servercredp ldd -IPv ipv +IPv hyc joe bindmethods @@ -170,6 +171,7 @@ armijo ldp ISP len +carLicense Choi Clatworthy scherr @@ -185,16 +187,16 @@ attrstyle directoryOperation creatorsName mem -oldPasswdFile oldpasswdfile +oldPasswdFile uniqueMember krb libpath acknowledgements jts createTimestamp -MIB LLL +MIB OpenSSL openssl LOF @@ -231,10 +233,10 @@ Subbarao aeeiib oidlen submatches -PEM olc -OLF +PEM PDU +OLF LDAPSchemaExtensionItem auth Pierangelo @@ -271,12 +273,13 @@ rdn wZFQrDD OTP olcSizeLimit -PRD -sbi pos +sbi +PRD pre stringal retoidp +sudoadm sdf efgh accesslog @@ -290,8 +293,8 @@ sel bvec TBC stringbv -SHA Sep +SHA ptr conn pwd @@ -308,8 +311,8 @@ myOID supportedSASLMechanism supportedSASLmechanism realnamingcontext -UCD SMD +UCD keytab portnumber uncached @@ -322,8 +325,8 @@ sasldb UCS searchDN keytbl -UDP tgz +UDP freemods prepend errText @@ -340,22 +343,22 @@ crit objectClassViolation ssf ldapfilter -vec -TOC rwm +TOC +vec pwdChangedTime tls peernamestyle xpasswd -SRP tmp +SRP SSL dupbv CPUs SRV entrymods -sss rwx +sss reqNewRDN rebindproc olcOverlayConfig @@ -380,8 +383,8 @@ wildcards uri tty url -sortKey XED +sortKey UTF vlv TXN @@ -406,12 +409,13 @@ MANCOMPRESSSUFFIX memberAttr multiclassing memberURL +sudoers pwdMaxFailure pseudorootdn GDBM LIBRELEASE -DSA's DSAs +DSA's realloc booleanMatch compareTrue @@ -467,8 +471,8 @@ pwdMinLength iZ ldapdelete xyz -rdbms RDBMs +rdbms extparam mk ng @@ -527,8 +531,8 @@ ZZ LDVERSION testAttr backend -backends backend's +backends BerValues Solaris structs @@ -540,9 +544,9 @@ ostring policyDN testObject pwdMaxAge -binddn -bindDN bindDn +bindDN +binddn distributedOperation schemachecking strvals @@ -570,6 +574,7 @@ protocolError errno errOp serverctrls +recursivegroup integerMatch moduledir dynstyle @@ -582,14 +587,14 @@ IEEE regex SIGINT slappasswd -errABsObject errAbsObject +errABsObject ldapexop -objectIdentifier objectidentifier +objectIdentifier deallocators -mirrormode MirrorMode +mirrormode loopDetect SIGHUP authMethodNotSupported @@ -606,8 +611,8 @@ filtercomp expr syntaxes memrealloc -returncode returnCode +returncode OpenLDAP's exts bitstringa @@ -630,8 +635,8 @@ lastName lldap cachesize slapauth -attributeType attributetype +attributeType GSER olcDbNosync typedef @@ -665,9 +670,9 @@ proxying organisations rewriteMap monitoredInfo -modrDN -ModRDN modrdn +ModRDN +modrDN HREF inline multiproxy @@ -679,8 +684,8 @@ reqReferral rlookups siiiib LTSTATIC -timelimitExceeded timeLimitExceeded +timelimitExceeded XKYnrjvGT subtrees unixODBC @@ -730,8 +735,8 @@ POSIX pathname noSuchObject proxyOld -BerElement berelement +BerElement sbiod plugin http @@ -741,8 +746,8 @@ ldbm numericStringSubstringsMatch internet storages -WhoAmI whoami +WhoAmI criticality addBlanks logins @@ -804,6 +809,7 @@ logold proxyattrset proxyAttrSet proxyAttrset +mary crlcheck olcBdbConfig kadmin @@ -989,6 +995,7 @@ subord namingViolation inappropriateAuthentication mixin +suders syntaxOID olcTLSCACertificateFile IGJlZ @@ -1099,6 +1106,7 @@ dynamicObject objectclass objectClass sizeLimitExceeded +accountadm reqControls modme shtool @@ -1408,8 +1416,8 @@ reqOld kbyte monitorCounter quickstart -olcConstraintConfig UUID +olcConstraintConfig rootpw veryclean syslogged @@ -1555,6 +1563,6 @@ slimit ali attributeoptions uidNumber -CA's CAs +CA's namingContext diff --git a/doc/guide/admin/master.sdf b/doc/guide/admin/master.sdf index 9ec081a91c307d500c8455dd1f20bb967a9d54f0..d42e9e1daa91dd43764de1cf6c7156341382d8fe 100644 --- a/doc/guide/admin/master.sdf +++ b/doc/guide/admin/master.sdf @@ -42,6 +42,9 @@ PB: !include "slapdconfig.sdf"; chapter PB: +!include "access-control.sdf"; chapter +PB: + !include "runningslapd.sdf"; chapter PB: diff --git a/doc/guide/admin/set-following-references.png b/doc/guide/admin/set-following-references.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6ef93f4aeb216df2248e17985f55c87affa755 Binary files /dev/null and b/doc/guide/admin/set-following-references.png differ diff --git a/doc/guide/admin/set-memberUid.png b/doc/guide/admin/set-memberUid.png new file mode 100644 index 0000000000000000000000000000000000000000..0b8e03742c27e4133bbcbeb461d39e32d62c3333 Binary files /dev/null and b/doc/guide/admin/set-memberUid.png differ diff --git a/doc/guide/admin/set-recursivegroup.png b/doc/guide/admin/set-recursivegroup.png new file mode 100644 index 0000000000000000000000000000000000000000..3a733b74f751f7b24334b998a405e449ded32c59 Binary files /dev/null and b/doc/guide/admin/set-recursivegroup.png differ diff --git a/doc/guide/admin/slapdconf2.sdf b/doc/guide/admin/slapdconf2.sdf index c8026294fac5ffd1799dd36a8d2f3a07e7c8e326..d4c595c4f98b9dc6021cc0368e7df805edae3088 100644 --- a/doc/guide/admin/slapdconf2.sdf +++ b/doc/guide/admin/slapdconf2.sdf @@ -399,8 +399,7 @@ H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+ This directive grants access (specified by <accesslevel>) to a set of entries and/or attributes (specified by <what>) by one or more requestors (specified by <who>). -See the {{SECT:Access Control}} section of this chapter for a -summary of basic usage. +See the {{SECT:Access Control}} section of this guide for basic usage. !if 0 More detailed discussion of this directive can be found in the @@ -946,534 +945,3 @@ H4: Sample Entry >olcDbConfig: set_flags DB_LOG_AUTOREMOVE >olcDbIDLcacheSize: 3000 >olcDbIndex: objectClass eq - - -H2: Access Control - -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 - - -H2: 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 - - -H2: Converting from slapd.conf(8) to a {{B:cn=config}} directory format - -Discuss slap* -f slapd.conf -F slapd.d/ (man slapd-config) diff --git a/doc/guide/admin/slapdconfig.sdf b/doc/guide/admin/slapdconfig.sdf index 248c18041a8c1292ccbddfa19b821f7423f28887..def96454157c891e0c651bbd05ec24b6e3b1cabf 100644 --- a/doc/guide/admin/slapdconfig.sdf +++ b/doc/guide/admin/slapdconfig.sdf @@ -91,9 +91,8 @@ H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+ This directive grants access (specified by <accesslevel>) to a set of entries and/or attributes (specified by <what>) by one or more -requestors (specified by <who>). See the {{SECT:The access -Configuration Directive}} section of this chapter for a summary of -basic usage. +requestors (specified by <who>). See the {{SECT:Access Control}} section of +this guide for basic usage. !if 0 More details discussion of this directive can be found in the @@ -503,418 +502,3 @@ containing the database and associated indices live. \Default: > directory /usr/local/var/openldap-data - - -H2: The access Configuration Directive - -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 - - -H2: 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