6.3. Creating ACIs Manually
You can create access control instructions manually using LDIF statements and add them to your directory tree using the ldapmodify utility, similar to the instructions in Section 2.4, “LDIF Update Statements”. The following sections explain in detail how to create the LDIF statements.
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.
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.
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:
A directory entry or all of the entries in a subtree, as described in Section 6.3.2.1, “Targeting a Directory Entry”.
Attributes of an entry, as described in Section 6.3.2.2, “Targeting Attributes”.
A set of entries or attributes that match a specified LDAP filter, as described in Section 6.3.2.4, “Targeting Entries or Attributes Using LDAP Filters”.
An attribute value, or a combination of values, that match a specified LDAP filter, as described in Section 6.3.2.5, “Targeting Attribute Values Using LDAP Filters”.
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 6.1, “LDIF Target Keywords” lists each keyword and the associated expressions.
| Keyword | Valid Expressions | Wildcard Allowed |
|---|---|---|
| target | ldap:///distinguished_name | Yes |
| targetattr | attribute | Yes |
| targetfilter | LDAP_filter | Yes |
| targetattrfilters | LDAP_operation:LDAP_filter | Yes |
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.com 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 (...)..
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")
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.com 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.com node with a uid ending in Anderson.
(target="ldap:///uid=C*A,dc=example,dc=com") — Matches every entry directly under the example.com 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.com 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.com 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.com 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.
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.
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")
You can target multiple attributes by using the targetattr keyword with the following syntax:
(targetattr = "attribute1||attribute2...||attributen")
attributeX is the name of the targeted attribute. For example, this targets the common name (cn) attribute:
(targetattr = "cn")
To target an entry's common name, surname, and UID attributes, use the following:
(targetattr = "cn || sn || uid")
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.
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.
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 Appendix B, 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";)
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.
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, you must use the targattrfilters keyword with the following syntax:
(targattrfilters="add=attr1:F1 && attr2:F2... && attrn:Fn,del=attr1:F1 &&attr2:F2... &&attrn:Fn")
add represents the operation of creating an attribute.
del represents the operation of deleting an attribute.
attrx represents the target attributes.
Fx represents filters that apply only to the associated attribute.
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:
(targattrfilters="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.
You cannot create value-based ACIs from the Directory Server Console.
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:
By creating a bind rule that matches user input in the bind request with an attribute value stored in the targeted entry. For more details, see Section 6.4.5, “Defining Access Based on Value Matching”.
By using the targetattr and targetfilter keywords.
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.
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
You can either explicitly allow or deny access permissions to the directory tree.
From the Directory Server Console, you cannot explicitly deny access, only grant permissions.
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:
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.
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 6.9.11, “Proxied Authorization ACI Example”.
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 targattrfilters 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 targattrfilters 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 targattrfilters 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 targattrfilters 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 -hhost-sbase-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";)
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;)
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,o=example.com group from renaming any entries in the set specified by the pattern cn=*,ou=people,o=example.com, add the following ACI:
aci: (target="ldap:///cn=*,ou=people,o=example.com")
(version 3.0; acl "Deny modrdn rights to the helpDeskGroup";
deny(write) groupdn="ldap:///cn=helpDeskGroup,ou=groups,o=example.com";)