Configuring Privileges & Access Control
OpenDJ supports use of both access control instructions and privileges.
Access control instructions can be added to directory data for fine-grained
control over what a given user or group member is authorized to do.
Privileges are implemented independently from access control. By default,
privileges restrict administrative access to directory root users. You can
configure OpenDJ to extend privileges to other administrators as well.
This chapter covers both access control instructions and privileges,
demonstrating how to configure both.
About Access Control Instructions
OpenDJ directory server access control instructions (ACIs) exist as
aci attribute values in the directory data. ACIs apply
to a scope defined in the instruction, and set permissions that depend on
what operation is requested, who requested the operation, and how the client
connected to the server. For example, the ACIs on the following
entry allow anonymous read access to all attributes except passwords, and
allow full read-write access to directory administrators under
dc=example,dc=com.
dn: dc=example,dc=com
objectClass: domain
objectClass: top
dc: example
aci: (target ="ldap:///dc=example,dc=com")(targetattr !=
"userPassword")(version 3.0;acl "Anonymous read-search access";
allow (read, search, compare)(userdn = "ldap:///anyone");)
aci: (target="ldap:///dc=example,dc=com") (targetattr =
"*")(version 3.0; acl "allow all Admin group"; allow(all) groupdn =
"ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
ACI attribute values use a specific language described in this section.
Although ACI attribute values can become difficult to read in LDIF, the
basic syntax is simple.
targets(version 3.0;acl "name";permissions subjects;)
The following list briefly explains the variables in the syntax above.
targets
The targets specifies entries, attributes,
controls, and extended operations to which the ACI applies.
To include multiple targets, enclose
each individual target in parentheses, (). When you specify multiple
targets, all targets must match for the ACI to apply
(AND).
name
Supplies a human-readable description of what the ACI does.
permissions
Defines which actions to allow, and which to deny. Paired with
subjects.
subjects
Identify clients to which the ACI applies depending on
who connected, and when, where, and how they connected. Paired with
permissions.
Separate multiple pairs of permissions
subjects definitions with semicolons, ;. When you
specify multiple permissions-subjects pairs, at least one must match
(OR).
ACI Targets
The seven types of ACI targets identify the objects to which the ACI
applies.
(target = "ldap:///DN")
(target != "ldap:///DN")
Sets the scope to the entry with distinguished name
DN, and to child entries.
You can use asterisks, *, to replace attribute types, attribute
values, and entire DN components. In other words, the following
specification targets both
uid=bjensen,ou=People,dc=example,dc=com and also
cn=Frank Zappa,ou=Musicians,dc=example,dc=com.
(target = "ldap:///*=*,*,dc=example,dc=com")
The DN must be in the subtree of the
entry on which the ACI is defined.
(targetattr = "attr-list")
(targetattr != "attr-list")
Replace attr-list with a list of
attribute type names, such as userPassword, separating
multiple attribute type names with ||.
This specification affects the entry where the ACI is located, or
the entries specified by other targets in the ACI.
You can use an asterisk, *, to specify all non-operational
attributes, although you will see better performance when explicitly
including or excluding attribute types needed. You can use a plus, +, to
specify all operational attributes.
If you do not include this target specification, then by default
no attributes are affected by the ACI.
(targetfilter = "ldap-filter")
(targetfilter != "ldap-filter")
Sets the scope to match the ldap-filter
dynamically, as in an LDAP search. The
ldap-filter can be any valid LDAP filter.
(targattrfilters = "expression")
(targattrfilters != "expression")
Use this target specification when managing changes made to
particular attributes.
Here expression takes one of the
following forms. Separate expressions with semicolons, ;.
op=attr1:filter1[&& attr2:filter2 ...][;op=attr3:filter3[&& attr4:filter4 ...] ...]
Here op can be either
add for operations creating attributes, or
delete for operations removing them.
Replace attr with an attribute type.
Replace filter with an LDAP filter that
corresponds to the attr attribute type.
(targetscope = "base|onelevel|subtree|subordinate")
Here base refers to the entry where the ACI is
defined, onelevel to immediate children,
subtree to the base entry and all children, and
subordinate to all children only.
If you do not specify targetscope, then the
default is subtree.
(targetcontrol = "OID")
(targetcontrol != "OID")
Replace OID with the object identifier
for the LDAP control to target. Separate multiple OIDs with ||.
This target cannot be restricted to a specific subtree by combining
it with another target.
(extop = "OID")
(extop != "OID")
Replace OID with the object identifier
for the extended operation to target. Separate multiple OIDs with ||.
This target cannot be restricted to a specific subtree by combining
it with another target.
ACI Permissions
ACI permission definitions take one of the following forms.
allow(action[, action ...])
deny(action[, action ...])
Although deny is supported, avoid restricting
permissions by using deny. Instead, explicitly
allow access only where needed. What looks harmless and
simple in your lab examples can grow difficult to maintain in a real-world
deployment with nested ACIs.
Replace action with one of the following.
add
Entry creation, as for an LDAP add operation
all
All permissions
compare
Attribute value comparison, as for an LDAP compare operation
delete
Entry deletion, as for an LDAP delete operation
export
Entry export during a modify DN operation
import
Entry import during a modify DN operation
proxy
Access the ACI target using the rights of another user
read
Read entries and attributes
search
Search the ACI targets. Needs to be combine with
read in order to read the search results.
selfwrite
Add or delete own DN from a group
write
Modify attributes on ACI target entries
ACI Subjects
ACI subjects match characteristics of the client connection to the
server. Use subjects to restrict whether the ACI applies depending on who
connected, and when, where, and how they connected.
authmethod = "none|simple|ssl|sasl mech"
authmethod != "none|simple|ssl|sasl mech"
Here you use none to mean do not check,
simple for simple authentication, ssl
for LDAPS, sasl mech for
SASL where mech is DIGEST-MD5, EXTERNAL, or
GSSAPI.
dayofweek = "day[, day ...]"
dayofweek != "day[, day ...]"
Replace day with one of
sun, mon, tue,
wed, thu, fri,
sat.
dns = "hostname"
dns != "hostname"
You can use asterisks, *, to replace name components, such as
dns = "*.myCompany.com".
groupdn = "ldap:///DN[|| ldap:///DN ...]"
groupdn != "ldap:///DN[|| ldap:///DN ...]"
Replace DN with the distinguished name
of a group to permit or restrict access for members.
ip = "addresses"
ip != "addresses"
Here addresses can be specified for
IPv4 or IPv6. IPv6 addresses are specified in brackets as
ldap://[address]/subnet-prefix
where /subnet-prefix is optional.
You can specify individual IPv4 addresses, addresses with asterisks (*) to
replace subnets and host numbers, CIDR notation, and forms such as
192.168.0.*+255.255.255.0 to specify subnet masks.
ssf = "strength"
ssf !=! "strength"
ssf > "strength"
ssf >= "strength"
ssf < "strength"
ssf <= "strength"
Here the security strength factor pertains to the cipher key
strength for connections using DIGEST-MD5, GSSAPI, SSL, or TLS.
timeofday = "hhmm"
timeofday != "hhmm"
timeofday > "hhmm"
timeofday >= "hhmm"
timeofday < "hhmm"
timeofday <= "hhmm"
Here hhmm is expressed as on a 24-hour
clock. For example, 1:15 PM is written 1315.
userattr = "attr#value"
userattr != "attr#value"
userattr = ldap-url#LDAPURL"
userattr != ldap-url#LDAPURL"
userattr = "[parent[child-level].]attr#GROUPDN|USERDN"
userattr != "[parent[child-level].]attr#GROUPDN|USERDN"
The userattr subject specifies an attribute
that must match on both the bind entry and the target of the ACI.
To match when the attribute on the bind DN entry corresponds
directly to the attribute on the target entry, replace
attr with the attribute type, and
value with the attribute value.
To match when the target entry is identified by an LDAP URL, and
the bind DN is in the subtree of the DN of the LDAP URL, use
ldap-url#LDAPURL.
To match when the bind DN corresponds to a member of the group
identified by the attr value on the target
entry, use attr#GROUPDN.
To match when the bind DN corresponds to the
attr value on the target entry, use
attr#USERDN.
The optional inheritence specification,
parent[child-level]., lets
you specify how many levels below the target entry inherit the ACI.
Here child-level is a number from 0 to 9, with
0 indicating the target entry only. Separate multiple
child-level digits with commas (,).
userdn = "ldap-url++[|| ldap-url++ ...]"
userdn != "ldap-url++[|| ldap-url++ ...]"
To match the bind DN, replace ldap-url++
with either a valid LDAP URL such as
ldap:///uid=bjensen,ou=People,dc=example,dc=com,
ldap:///dc=example,dc=com??sub?(uid=bjensen),
or a special LDAP URL-like keyword from the following list.
ldap:///all
Match authenticated users.
ldap:///anyone
Match anonymous and authenticated users.
ldap:///parent
Match when the bind DN is a parent of the ACI target.
ldap:///self
Match when the bind DN entry corresponds to ACI target.
About Privileges
Privileges provide access control for server administration
independently from access control instructions.
Directory root users, such as cn=Directory Manager,
are granted privileges in the following list and marked with an asterisk (*)
by default. Other administrator users can be assigned privileges, too.
backend-backup*
Request a task to backup data
backend-restore*
Request a task to restore data from backup
bypass-acl*
Perform operations without regard to ACIs
cancel-request*
Cancel any client request
config-read*
Read the server configuration
config-write*
Change the server configuration
data-sync
Perform data synchronization
disconnect-client*
Close any client connection
jmx-notify
Subscribe to JMX notifications
jmx-read
Read JMX attribute values
jmx-write
Write JMX attribute values
ldif-export*
Export data to LDIF
ldif-import*
Import data from LDIF
modify-acl*
Change ACIs
password-reset*
Reset other users' passwords
privilege-change*
Change the privileges assigned to users
proxied-auth
Use the Proxied Authorization control
server-restart*
Request a task to restart the server
server-shutdown*
Request a task to stop the server
unindexed-search*
Search using a filter with no correponding index
update-schema*
Change OpenDJ schema definitions
* = default directory root user privileges
Configuring Privileges
For root directory administrators, by default cn=Directory
Manager, you configure privileges using the
dsconfig command.
For non-root directory administrators, you add privileges with
the ldapmodify command.
To Change Root DN Privileges
Start dsconfig in interactive mode.
$ dsconfig -p 4444 -h `hostname` -D "cn=Directory Manager" -w password
Select the Root DN menu.
Select View and edit the Root DN.
Edit the default-root-privilege-name.
Make sure you apply the changes when finished.
To Add Privileges on an Individual Entry
Privileges are specified using the ds-privilege-name
operational attribute, which you can change on the command-line using
ldapmodify.
Determine the privileges to add.
$ cat privilege.ldif
dn: uid=kvaughan,ou=People,dc=example,dc=com
changetype: modify
add: ds-privilege-name
ds-privilege-name: config-read
ds-privilege-name: password-reset
This example lets the user read the server configuration, and reset
user passwords. In order for the user to be able to change a user password,
you must also allow the modification using ACIs. For this example, Kirsten
Vaughan is a member of the Directory Administrators group for Example.com,
and already has access to modify user entries.
Prior to having the privileges, Kirsten gets messages about
insufficent access when trying to read the server configuration, or
reset a user password.
$ ldapsearch -p 1389 -D "uid=kvaughan,ou=People,dc=example,dc=com" \
> -w bribery -b cn=config "(objectclass=*)"
SEARCH operation failed
Result Code: 50 (Insufficient Access Rights)
Additional Information: You do not have sufficient privileges to perform
search operations in the Directory Server configuration
$ ldappasswordmodify -p 1389 -D "uid=kvaughan,ou=People,dc=example,dc=com" \
> -w bribery -a "dn:uid=scarter,ou=People,dc=example,dc=com" -n changeit
The LDAP password modify operation failed with result code 50
Error Message: You do not have sufficient privileges to perform password
reset operations
Apply the change as a user with the
privilege-change privilege.
$ ldapmodify -p 1389 -D "cn=Directory Manager" -w password -f privilege.ldif
Processing MODIFY request for uid=kvaughan,ou=People,dc=example,dc=com
MODIFY operation successful for DN uid=kvaughan,ou=People,dc=example,dc=com
At this point, Kirsten can perform the operations requiring
privileges.
$ ldapsearch -p 1389 -D "uid=kvaughan,ou=People,dc=example,dc=com" \
> -w bribery -b cn=config "(objectclass=*)"
dn: cn=config
ds-cfg-return-bind-error-messages: false
ds-cfg-default-password-policy: cn=Default Password Policy,cn=Password Policies,
cn=config
...
$ ldappasswordmodify -p 1389 -D "uid=kvaughan,ou=People,dc=example,dc=com" \
> -w bribery -a "dn:uid=scarter,ou=People,dc=example,dc=com" -n changeit
The LDAP password modify operation was successful
To Add Privileges For a Group of Administrators
For deployments with more than one administrator, you no doubt use
a group to define adminstrative rights. You can use a collective attribute
subentry to specify privileges for the administrator group.
Collective attributes provide a standard mechanism for defining
attributes that appear on all the entries in a particular subtree. OpenDJ
extends collective attributes to give you fine-grained control over the
which entries in the subtree are targetted. Also, OpenDJ lets you use
virtual attributes, such as isMemberOf to construct the
filter for targetting entries to which the collective attributes apply. This
allows you, for example, to define administrative privileges that apply to
all users who belong to an administrator group.
Create an LDAP subentry that specifies the collective attributes.
$ cat collective.ldif
dn: cn=Administrator Privileges,dc=example,dc=com
objectClass: collectiveAttributeSubentry
objectClass: extensibleObject
objectClass: subentry
objectClass: top
cn: Administrator Privileges
ds-privilege-name;collective: config-read
ds-privilege-name;collective: config-write
ds-privilege-name;collective: ldif-export
ds-privilege-name;collective: modify-acl
ds-privilege-name;collective: password-reset
ds-privilege-name;collective: proxied-auth
subtreeSpecification: {base "ou=people", specificationFilter
"(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" }
$ ldapmodify -p 1389 -D "cn=Directory Manager" -w password -a -f collective.ldif
Processing ADD request for cn=Administrator Privileges,dc=example,dc=com
ADD operation successful for DN cn=Administrator Privileges,dc=example,dc=com
The Directory Administrators group for Example.com includes members
like Kirsten Vaughan.
Observe that the change takes effect immediately.
$ ldappasswordmodify -p 1389 -D "uid=kvaughan,ou=People,dc=example,dc=com" \
> -w bribery -a "dn:uid=scarter,ou=People,dc=example,dc=com" -n changeit
The LDAP password modify operation was successful
Configuring Access Control
Access control instructions are defined in the data, as values for
aci attributes. They can be imported in LDIF. They can
be modified over LDAP. Yet in order to make changes to ACIs users first
need the modify-acl privilege described previously.
By default, only the root DN user has the modify-acl
privilege.
Global ACIs on cn=Access Control Handler,cn=config
can be set using the dsconfig command. Global ACIs have
attribute type ds-cfg-global-aci. Modify global ACIs from
the Access Control Handler menu in dsconfig.
Default global ACIs set up the following access rules.
Users can employ LDAP controls and perform extended operations.
Anonymous read access is allowed for most user data attributes.
Users can read password values on their own entries after binding.
(Also by default, password values are hashed.)
Anonymous read access is allowed for schema-related operational
attributes.
Anonymous read access is allowed for root DSE attributes describing
what the server supports.
Anonymous read access is allowed for operational attributes related
to entry updates and entry identification.
Access to replication data is denied.
Users with write access to add ACIs and with the
modify-acl privilege can use the
ldapmodify command to change ACIs located in user
data.
This section therefore focuses on ACI examples, rather than
demonstrating how to directory data for each example.
ACI: Anonymous Reads & Searches
This works when the only attributes you do not want world-readable
are password attributes.
aci: (target ="ldap:///dc=example,dc=com")(targetattr !=
"authPassword || userPassword")(version 3.0;acl "Anonymous read-search access";
allow (read, search, compare)(userdn = "ldap:///anyone");)
ACI: Full Access for Administrators
Directory Administrators need privileges as well for full access to
administrative operations.
aci: (target="ldap:///dc=example,dc=com") (targetattr =
"*")(version 3.0;acl "Admins can run amok"; allow(all) groupdn =
"ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
ACI: Change Own Password
By default this capability is set in a global ACI.
aci: (target ="ldap:///ou=People,dc=example,dc=com")(targetattr =
"authPassword || userPassword")(version 3.0;acl "Allow users to change pass
words"; allow (write)(userdn = "ldap:///self");)
ACI: Manage Own Group Membership
For some static groups such as carpoolers and social club members,
you might choose to let users manage their own memberships.
aci: (target ="ldap:///ou=Self Service,ou=Groups,dc=example,dc=com")(
targetattr = "member")(version 3.0;acl "Self registration"; allow(selfwrite)(
userdn = "ldap:///uid=*,ou=People,dc=example,dc=com");)
ACI: Manage Self Service Groups
Let users create and delete self-managed groups.
aci: (target ="ldap:///ou=Self Service,ou=Groups,dc=example,dc=com")(
targattrfilters="add=objectClass:(objectClass=groupOfNames)")(version 3.0;
acl "All can create self service groups"; allow (add)(userdn= "
ldap:///uid=*,ou=People,dc=example,dc=com");)
aci: (target ="ldap:///ou=Self Service,ou=Groups,dc=example,dc=com")(version 3
.0; acl "Owner can delete self service groups"; allow (delete)(userattr= "
owner#USERDN");)
ACI: Permit Clear Text Access Over Loopback Only
This ACI uses IP address and Security Strength Factor subjects.
aci: (target = "ldap:///dc=example,dc=com")(targetattr =
"*")(version 3.0;acl "Use loopback only for LDAP in the clear"; deny (all)(
ip != "127.0.0.1" and ssf <= "1");)
The ssf is one for example when using SSL but you
have not configured a cipher, so the packets are checksummed for integrity
checking by all content is nevertheless sent in clear text.
Viewing Effective Rights
Once you set up a number of ACIs, you might find it difficult to
understand by inspection what rights a user actually has to a given entry.
The Get Effective Rights control can help.
The control OID, 1.3.6.1.4.1.42.2.27.9.5.2, is
not allowed by the default global ACIs.
In this example, Babs Jensen is the owner of a small group of people
who are willing to carpool.
$ ldapsearch -p 1389 -D "uid=bjensen,ou=people,dc=example,dc=com" -w hifalutin \
> -b "ou=Self Service,ou=Groups,dc=example,dc=com" "cn=*"
dn: cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
objectClass: top
member: uid=bjensen,ou=People,dc=example,dc=com
description: People who are willing to carpool
owner: uid=bjensen,ou=People,dc=example,dc=com
cn: Carpoolers
Performing the same search with the get effective rights control, and
asking for the aclRights attribute, shows what rights
Babs has on the entry.
$ ldapsearch -J effectiverights -p 1389 \
> -D "uid=bjensen,ou=people,dc=example,dc=com" -w hifalutin \
> -b "ou=Self Service,ou=Groups,dc=example,dc=com" "cn=*" aclRights
dn: cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com
aclRights;entryLevel: add:0,delete:1,read:1,write:0,proxy:0
Requesting the aclRightsInfo attribute results in
information about the ACIs applied to arrive at the results.
$ ldapsearch -J effectiverights -p 1389 \
> -D "uid=bjensen,ou=people,dc=example,dc=com" -w hifalutin \
> -b "ou=Self Service,ou=Groups,dc=example,dc=com" "cn=*" aclRights \
> aclRightsInfo
dn: cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com
aclRightsInfo;logs;entryLevel;read: acl_summary(main): access allowed(read) on e
ntry/attr(cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com, objectClas
s) to (uid=bjensen,ou=People,dc=example,dc=com) (not proxied) ( reason: evaluat
ed allow , deciding_aci: Anonymous read-search access)
aclRightsInfo;logs;entryLevel;write: acl_summary(main): access not allowed(write
) on entry/attr(cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com, NULL
) to (uid=bjensen,ou=People,dc=example,dc=com) (not proxied) ( reason: no acis
matched the subject )
aclRightsInfo;logs;entryLevel;add: acl_summary(main): access not allowed(add) on
entry/attr(cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com, NULL) to
(uid=bjensen,ou=People,dc=example,dc=com) (not proxied) ( reason: no acis matc
hed the subject )
aclRightsInfo;logs;entryLevel;delete: acl_summary(main): access allowed(delete)
on entry/attr(cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com, NULL)
to (uid=bjensen,ou=People,dc=example,dc=com) (not proxied) ( reason: evaluated
allow , deciding_aci: Owner can delete self service groups)
aclRights;entryLevel: add:0,delete:1,read:1,write:0,proxy:0
aclRightsInfo;logs;entryLevel;proxy: acl_summary(main): access not allowed(proxy
) on entry/attr(cn=Carpoolers,ou=Self Service,ou=Groups,dc=example,dc=com, NULL
) to (uid=bjensen,ou=People,dc=example,dc=com) (not proxied) ( reason: no acis
matched the subject )