13.3. Creating ACIs Manually

You can create access control instructions manually using LDIF statements and add them to the directory tree using the ldapmodify utility, similar to the instructions in Section 3.3, “Using LDIF Update Statements to Create or Modify Entries”.

Note

LDIF ACI statements can be very complex. However, if you are setting access control for a large number of directory entries, using LDIF is the preferred because it is faster than using the Console. To familiarize yourself with LDIF ACI statements, however, you may want to use the Directory Server Console to set the ACI and then click the Edit Manually button on the Access Control Editor. This shows you the correct LDIF syntax. If your operating system allows it, you can even copy the LDIF from the Access Control Editor and paste it into your LDIF file.

13.3.1. The ACI Syntax

The aci attribute uses the following syntax:
aci: (target)(version 3.0;acl "name";permissionbind_rules;)
  • target specifies the entry, attributes, or set of entries and attributes for which to control access. The target can be a distinguished name, one or more attributes, or a single LDAP filter. The target is an optional part of the ACI.
  • version 3.0 is a required string that identifies the ACI version.
  • name is a name for the ACI. The name can be any string that identifies the ACI. The ACI name is required.
  • permission specifically outlines what rights are being allowed or denied; for example, read or search rights.
  • bind_rules specify the credentials and bind parameters that a user has to provide to be granted access. Bind rules can also specifically deny access to certain users or groups of users.
You can have multiple permission-bind rule pairs for each target. This allows you to set multiple access controls for a given target efficiently. For example:
target(permissionbind_rule)(permissionbind_rule)...
If you have several ACRs in one ACI statement, the syntax is in the following form:
aci: (target)(version 3.0;acl "name";permissionbind_rule; permissionbind_rule; ... permissionbind_rule;)
The following is an example of a complete LDIF ACI:
aci: (target="ldap:///uid=bjensen,dc=example,dc=com")(targetattr=*)
(version 3.0;acl "aci1";allow (write) userdn="ldap:///self";)
In this example, the ACI states that the user bjensen has rights to modify all attributes in her own directory entry.

13.3.2. Defining Targets

The target identifies to what the ACI applies. If the target is not specified, the ACI applies to the entry containing the aci attribute and to the entries below it. A target can be any of the following:
The general syntax for a target is as follows:
(keyword = "expression")
(keyword != "expression")
  • keyword indicates the type of target.
  • equal (=) indicates that the target is the object specified in the expression, and not equal (!=) indicates the target is not the object specified in the expression.
  • expression identifies the target.
The quotation marks ("") around expression are required. What you use for expression is dependent upon the keyword that you supply.
Table 13.1, “LDIF Target Keywords” lists each keyword and the associated expressions.

Table 13.1. LDIF Target Keywords

Keyword Valid Expressions Wildcard Allowed
target ldap:///distinguished_name Yes
targetattr attribute Yes
targetfilter LDAP_filter Yes
targetattrfilters operation=attribute:LDAP_filter [a] Yes
[a] Supported operations: add and del.
In all cases, you must keep in mind that when you place an ACI on an entry, if it is not a leaf entry, the ACI also applies to all entries below it. For example, if you target the entry ou=accounting,dc=example,dc=com, the permissions you set apply to all entries in the accounting branch of the example tree.
As a counter example, if you place an ACI on the ou=accounting,dc=example,dc=com entry, you cannot target the uid=sarette,ou=people,dc=example,dc=com entry because it is not located under the accounting tree.
Be wary of using != when specifying an attribute to deny. ACLs are treated as a logical OR, which means that if you created two ACLs as shown below, the result allows all values of the target attribute.
acl1: ( target=...)( targetattr!=a )(version 3.0; acl "name";allow (...)..
acl2: ( target=...)( targetattr!=b )(version 3.0; acl "name";allow (...)..
The first ACL (acl1) allows b and the second ACL (acl2) allows a. The result of these two ACLs is the same as the one resulting from using an ACL of the following form:
acl3: ( targetattr="*" ) allow (...) ...
In the second example, nothing is denied, which could give rise to security problems.
When you want to deny access to a particular attribute, use deny in the permissions clause rather than using allow with ( targetattr != value ). For example, usages such as these are recommended:
acl1: ( target=...)( targetattr=a )(version 3.0; acl "name";deny (...).. 
acl2: ( target=...)( targetattr=b )(version 3.0; acl "name";deny (...)..

13.3.2.1. Targeting a Directory Entry

To target a directory entry (and the entries below it), you must use the target keyword. The target keyword can accept a value of the following format:
target="ldap:///distinguished_name
This identifies the distinguished name of the entry to which the access control rule applies. For example:
(target = "ldap:///uid=bjensen,dc=example,dc=com")

Note

If the DN of the entry to which the access control rule applies contains a comma, escape the comma with a single backslash (\), such as (target="ldap:///uid=lfuentes,dc=example.com Bolivia\,S.A.").
Wildcards can be used when targeting a distinguished name using the target keyword. The wildcard indicates that any character or string or substring is a match for the wildcard. Pattern matching is based on any other strings that have been specified with the wildcard.
The following are legal examples of wildcard usage:
  • (target="ldap:///uid=*,dc=example,dc=com") — Matches every entry in the entire example tree that has the uid attribute in the entry's RDN.
  • (target="ldap:///uid=*Anderson,dc=example,dc=com") — Matches every entry directly under the example node with a uid ending in Anderson.
  • (target="ldap:///uid=C*A,dc=example,dc=com") — Matches every entry directly under the example node with a uid beginning with C and ending with A.
  • (target="ldap:///uid=*,dc=example,dc=com") — Matches every entry in the entire example tree that has the uid attribute in the entry's RDN.
  • (target="ldap:///uid=*,ou=*,dc=example,dc=com") — Matches every entry in the example tree whose distinguished name contains the uid and ou attributes. Thus, uid=fchen,ou=Engineering,dc=example,dc=com or uid=claire,ou=Engineering,ou=people,dc=example,dc=com would match, but uid=bjensen,dc=example,dc=com ou=Engineering,dc=example,dc=com would not.
Depending on the position of the wildcard, it can apply to the full DN, not only to attribute values. Therefore, the wildcard can be used as a substitute for portions of the DN. For example, uid=andy*,dc=example,dc=com targets all the directory entries in the entire example tree with a matching uid attribute and not just the entries that are immediately below the dc=example,dc=com node. In other words, this target matches with longer expressions such as uid=andy,ou=eng,dc=example,dc=com or uid=andy,ou=marketing,dc=example,dc=com.

Note

You cannot use wildcards in the suffix part of a distinguished name. That is, if your directory uses the suffixes c=US and c=GB, then you cannot use (target="ldap:///dc=example,c=*") as a target to reference both suffixes. Neither can you use a target such as uid=bjensen,dc=*.com.

13.3.2.2. Targeting Attributes

In addition to targeting directory entries, you can also target one or more attributes included in the targeted entries. This is useful to deny or allow access to partial information about an entry. For example, you could allow access to only the common name, surname, and telephone number attributes of a given entry while denying access to sensitive information such as passwords.
You can specify that the target is equal (=) or is not equal (!=) to a specific attribute. The attributes you supply do not need to be defined in the schema. This absence of schema checking makes it possible to implement an access control policy when you set up your directory service for the first time, even if the ACLs you create do not apply to the current directory content.
To target attributes, use the targetattr keyword. The keyword uses the following syntax:
(targetattr = "attribute")
For example, to target the common name (cn) attribute:
(targetattr = "cn")
You can target multiple attributes by using the targetattr keyword with the following syntax:
(targetattr = "attribute1 || attribute2 || ...")
To target all attributes:
(targetattr = "*")

Note

If the targetattr keyword is not set, the rights granted by the ACI applies to no attributes.
The attributes specified in the targetattr keyword apply to the entry that the ACI is targeting and to all the entries below it. If you target the password attribute on the entry uid=bjensen,ou=Marketing,dc=example,dc=com, only the password attribute on the bjensen entry is affected by the ACI because it is a leaf entry.
If, however, you target the tree's branch point ou=Marketing,dc=example,dc=com, then all the entries beneath the branch point that can contain a password attribute are affected by the ACI.

13.3.2.3. Targeting Both an Entry and Attributes

By default, the entry targeted by an ACI containing a targetattr keyword is the entry on which the ACI is placed. That is, putting an ACI such as aci: (targetattr = "uid")(access_control_rules;) on the ou=Marketing,dc=example,dc=com entry means that the ACI applies to the entire Marketing subtree. However, you can also explicitly specify a target using the target keyword:
aci: (target="ldap:///ou=Marketing,dc=example,dc=com")(targetattr="uid")(access_control_rules;)
The order in which you specify the target and the targetattr keywords is not important.

13.3.2.4. Targeting Entries or Attributes Using LDAP Filters

You can use LDAP filters to target a group of entries that match certain criteria. To do this, you must use the targetfilter keyword with an LDAP filter. The syntax of the targetfilter keyword is as follows:
(targetfilter = "LDAP_filter")
LDAP_filter is a standard LDAP search filter. For more information on the syntax of LDAP search filters, see Chapter 10, Finding Directory Entries.
For example, suppose that all entries in the accounting department include the attribute-value pair ou=accounting, and all entries in the engineering department include the attribute-value pair ou=engineering subtree. The following filter targets all the entries in the accounting and engineering branches of the directory tree:
(targetfilter = "(|(ou=accounting)(ou=engineering))")
This type of filter targets whole entries. You can associate the targetfilter and the targetattr keywords to create ACIs that apply to a subset of attributes in the targeted entries.
The following LDIF example allows members of the Engineering Admins group to modify the departmentNumber and manager attributes of all entries in the Engineering business category. This example uses LDAP filtering to select all entries with businessCategory attributes set to Engineering:
dn: dc=example,dc=com
objectClass: top
objectClass: organization
aci: (targetattr="departmentNumber || manager")
  (targetfilter="(businessCategory=Engineering)")
  (version 3.0; acl "eng-admins-write"; allow (write)
  groupdn ="ldap:///cn=Engineering Admins,dc=example,dc=com";)

Note

Although using LDAP filters can be useful when you are targeting entries and attributes that are spread across the directory, the results are sometimes unpredictable because filters do not directly name the object for which you are managing access. The set of entries targeted by a filtered ACI is likely to change as attributes are added or deleted. Therefore, if you use LDAP filters in ACIs, you should verify that they target the correct entries and attributes by using the same filter in an ldapsearch operation.

13.3.2.5. Targeting Attribute Values Using LDAP Filters

You can use access control to target specific attribute values. This means that you can grant or deny permissions on an attribute if that attribute's value meets the criteria defined in the ACI. An ACI that grants or denies access based on an attribute's value is called a value-based ACI.
For example, you might grant all users in your organization permission to modify the nsroledn attribute in their own entry. However, you would also want to ensure that they do not give themselves certain key roles, such as Top Level Administrator. LDAP filters are used to check that the conditions on attribute values are satisfied.
To create a value-based ACI, use the targetattrfilters keyword with the following syntax:
  • For one operation with one attribute and filter combination:
    (targetattrfilters="operation=attribute:filter")
  • For one operation with multiple attribute and filter combinations:
    (targetattrfilters="operation=attribute_1:filter_1 && attribute_2:filter_2 ... && attribute_m:filter_m")
  • For two operations, each with multiple attribute and filter combinations:
    (targetattrfilters="operation_1=attribute_1_1:filter_1_1 && attribute_1_2:filter_1_2 ... && attribute_1_m:filter_1_m , operation_2=attribute_2_1:filter_2_1 && attribute_2_2:filter_2_2 ... & attribute_2_n:filter_2_n ")
In the previous syntax examples, you can set the operations either to add or del. The attribute:filter combination sets the filter and the attribute the filter is applied to.
When creating an entry, if a filter applies to an attribute in the new entry, then each instance of that attribute must satisfy the filter. When deleting an entry, if a filter applies to an attribute in the entry, then each instance of that attribute must also satisfy the filter.
When modifying an entry, if the operation adds an attribute, then the add filter that applies to that attribute must be satisfied; if the operation deletes an attribute, then the delete filter that applies to that attribute must be satisfied. If individual values of an attribute already present in the entry are replaced, then both the add and delete filters must be satisfied.
For example, consider the following attribute filter:
(targetattrfilters="add=nsroledn:(!(nsroledn=cn=superAdmin)) && telephoneNumber:(telephoneNumber=123*)")
This filter can be used to allow users to add any role (nsroledn attribute) to their own entry, except the superAdmin role. It also allows users to add a telephone number with a 123 prefix.

Note

You cannot create value-based ACIs from the Directory Server Console.

13.3.2.6. Targeting a Single Directory Entry

Targeting a single directory entry is not straightforward because it goes against the design philosophy of the access control mechanism. However, it can be done in either of two ways:
You can use the targetattr keyword to specify an attribute that is only present in the entry you want to target, and not in any of the entries below your target. For example, if you want to target ou=people,dc=example,dc=com, and there are not any organizational units (ou) defined below that node, you could specify an ACI that contains targetattr=ou.
A safer method is to use the targetfilter keyword and to specify explicitly an attribute value that appears in the entry alone. For example, during the installation of the Directory Server, the following ACI is created:
aci: (targetattr="*")(targetfilter=(o=NetscapeRoot))(version 3.0; 
     acl "Default anonymous access"; allow (read, search) userdn="ldap:///anyone";)
This ACI can apply only to the o=NetscapeRoot entry.
The risk associated with these method is that your directory tree might change in the future, and you would have to remember to modify this ACI.

13.3.3. Defining Permissions

Permissions specify the type of access you are allowing or denying. You can either allow or deny permission to perform specific operations in the directory. The various operations that can be assigned are known as rights.
There are two parts to setting permissions:
  • Allowing or denying access
  • Assigning rights

13.3.3.1. Allowing or Denying Access

You can either explicitly allow or deny access permissions to the directory tree.

Note

From the Directory Server Console, you cannot explicitly deny access, only grant permissions.

13.3.3.2. Assigning Rights

Rights detail the specific operations a user can perform on directory data. You can allow or deny all rights, or you can assign one or more of the following rights:

Table 13.2. User Rights

Right Description
Read Indicates whether users can read directory data. This permission applies only to the search operation.
Write Indicates whether users can modify an entry by adding, modifying, or deleting attributes. This permission applies to the modify and modrdn operations.
Add Indicates whether users can create an entry. This permission applies only to the add operation.
Delete Indicates whether users can delete an entry. This permission applies only to the delete operation.
Search Indicates whether users can search for the directory data. Users must have Search and Read rights in order to view the data returned as part of a search result. This permission applies only to the search operation.
Compare Indicates whether the users can compare data they supply with data stored in the directory. With compare rights, the directory returns a success or failure message in response to an inquiry, but the user cannot see the value of the entry or attribute. This permission applies only to the compare operation.
Selfwrite Indicates whether users can add or delete their own DN from a group. This right is used only for group management.
Proxy Indicates whether the specified DN can access the target with the rights of another entry.
All Indicates that the specified DN has all rights (read, write, search, delete, compare, and selfwrite) to the targeted entry, excluding proxy rights.
Rights are granted independently of one another. This means, for example, that a user who is granted add rights can create an entry but cannot delete it if delete rights have not been specifically granted. Therefore, when planning the access control policy for your directory, you must ensure that you grant rights in a way that makes sense for users. For example, it does not usually make sense to grant write permission without granting read and search permissions.

Note

The proxy mechanism is very powerful and must be used sparingly. Proxy rights are granted within the scope of the ACL, and there is no way to restrict who an entry that has the proxy right can impersonate; that is, when you grant a user proxy rights, that user has the ability to proxy for any user under the target; there is no way to restrict the proxy rights to only certain users. For example, if an entity has proxy rights to the dc=example,dc=com tree, that entity can do anything. Make sure you set the proxy ACI at the lowest possible level of the DIT; see Section 13.9.12, “Proxied Authorization ACI Example”.

13.3.3.3. Rights Required for LDAP Operations

This section describes the rights you need to grant to users depending on the type of LDAP operation you want to authorize them to perform.
  • Adding an entry:
    • Grant add permission on the entry being added.
    • Grant write permission on the value of each attribute in the entry. This right is granted by default but could be restricted using the targetattrfilters keyword.
  • Deleting an entry:
    • Grant delete permission on the entry to be deleted.
    • Grant write permission on the value of each attribute in the entry. This right is granted by default but could be restricted using the targetattrfilters keyword.
  • Modifying an attribute in an entry:
    • Grant write permission on the attribute type.
    • Grant write permission on the value of each attribute type. This right is granted by default but could be restricted using the targetattrfilters keyword.
  • Modifying the RDN of an entry:
    • Grant write permission on the entry.
    • Grant write permission on the attribute type used in the new RDN.
    • Grant write permission on the attribute type used in the old RDN, if you want to grant the right to delete the old RDN.
    • Grant write permission on the value of attribute type used in the new RDN. This right is granted by default but could be restricted using the targetattrfilters keyword.
  • Comparing the value of an attribute:
    • Grant compare permission on the attribute type.
  • Searching for entries:
    • Grant search permission on each attribute type used in the search filter.
    • Grant read permission on attribute types used in the entry.
The permissions granted on individual attributes or entries can affect a broad range of actions; for example, there are several different permissions users must have to search the directory like the following ldapsearch operation:
ldapsearch -D "cn=directory manager" -w secret -p 389 -h server.example.com -x -b "uid=bkolics,dc=example,dc=com" objectclass=* mail
The following ACI is used to determine whether user bkolics can be granted access:
aci: (targetattr = "mail")(version 3.0; acl "self access to
    mail"; allow (read, search) userdn = "ldap:///self";)
The search result list is empty because this ACI does not grant access to the objectclass attribute. If you want the search operation described above to be successful, modify the ACI to allow read and search access for the mail and objectclass attributes.
aci: (targetattr = "mail || objectclass")(version 3.0; acl "self
    access to mail"; allow (read, search) userdn = "ldap:///self";)

13.3.3.4. Permissions Syntax

In an ACI statement, the syntax for permissions is allow|deny (rights). rights is a list of 1 to 8 comma-separated keywords enclosed within parentheses. Valid keywords are read, write, add, delete, search, compare, selfwrite, proxy, or all.
In the following example, read, search, and compare access is allowed, provided the bind rule is evaluated to be true:
aci: (target="ldap:///dc=example,dc=com") (version 3.0;acl "example"; 
     allow (read, search, compare) bind_rule;)

13.3.3.5. Access Control and the modrdn Operation

To explicitly deny modrdn rights using ACIs, target the relevant entries but omit the targetattr keyword. For example, to prevent the cn=helpDeskGroup,ou=groups,dc=example,dc=com group from renaming any entries in the set specified by the pattern cn=*,ou=people,dc=example,dc=com, add the following ACI:
aci: (target="ldap:///cn=*,ou=people,dc=example,dc=com")
     (version 3.0; acl "Deny modrdn rights to the helpDeskGroup";
     deny(write) groupdn="ldap:///cn=helpDeskGroup,ou=groups,dc=example,dc=com";)