• Contact Us
  • Home
  • Installation
  • Configuration

Access Control Lists (ACLs)

Learn about Access Control Lists (ACLs), a method of controlling and managing network access, including how they work, their types, and their importance in network security.

Written by Maryanne Normann

Updated at July 27th, 2024

  • Quick Start
  • Installation
    Best Practices Configuration Troubleshooting Design Performance Platform
  • Maintenance
    Releases Upgrade
  • Reference
+ More

Table of Contents

Access Control Lists (ACLs) ACLs - The "to" Clause Entries DN Styles Attributes Attribute Specifier Examples ACLs - The "by" Clause "by" Specifiers dn.[dnstyle] group.[groupstyle] SSF (Security Strength Factor) ACLs - The "permission" Clause ACLs - ACL Controls Control Usage ACL Best Practices Regular Expressions

Access Control Lists (ACLs)

This article covers the basic and most commonly used features of ACLs.

  • ACLs (Access Control Lists) control access to entries and attributes in an LDAP database
  • ACLs are settings stored in the slapd configuration file (slapd.conf) or configuration database (cn=config)
  • ACLs can be defined globally when configured in the frontend database, or database-specific in the database definition in the configuration database
  • ACLs are evaluated in the order in which they appear in the configuration
  • Database-specific ACLs take precedence ACLs defined in the frontend database
  • The basic format of an ACL is: 

    to <what> by <who> <privilege>

ACLs - The "to" Clause

The "to" clause in an ACL defines what entries or attributes the rule will apply to.

Entries

Rules defining access to entries is done by selecting entries based on their naming context. The scope of the selection can, and should also be defined. The basic format of a DN specification is:

to dn.<specifier>="<pattern>"

DN Styles

DN Style Description
exact The exact entry
base(object) The exact entry
regex A DN matching the specified regular expression (POSIX 'extended')
one(level) The DN or any entry one level below the entry
sub(tree) Includes all entries in the subtree
children Includes all entries below (subordinate to) the DN

DN Style Examples

Get only the “cn=replicator,ou=admin,dc=example,dc=com” group:

to dn.exact="cn=replicator,ou=admin,dc=example,dc=com" by <who> <permission>

Get all entries in the “ou=accounting,dc=example,dc=com” subtree:

to dn.subtree="ou=accounting,dc=example,dc=com by <who> <permission>

Get all entries one level below the “ou=accounting,dc=example,dc=com” entry:

to dn.one="ou=accounting,dc=example,dc=com by <who> <permission>

Get all child entries of entries in the “ou=accounting,dc=example,dc=com” subtree:

to dn.children="ou=accounting,dc=example,dc=com" by <who> <permission>

Get entries whose CN starts with “application” in the “ou=administrators,dc=example,dc=com”  subtree:

to dn.regex="cn=application\w+,ou=administrators,dc=example,dc=com" by <who> <permission>

Attributes

Rules granting access to specified attributes is done by defining a list of attributes, objectClasses or both. The format is:

to attrlist=<attribute1>,<attribute2> by <who> <permission>

When an objectClass is specified, the rule will be applied to all required and optional attributes defined in that objectClass.

to attrlist=<objectClass>,<attribute> by <who> <permission>

Attribute Specifier Examples

To specify control to the "description" and "initials" attribute

to attrlist=description,initials by <who> <permission>

To specify control access to all the attributes defined in the person objectClass

to attrlist=person by <who> <permission>

ACLs - The "by" Clause

The "by" clause specifies which users the rule will be applied to.

"by" Specifiers

Specifier Description
* Everyone & everything
anonymous Connections before or without authentication
users Users that have successfully authenticated
self.<selfstyle> An authenticated user's own entry
dn.<dnstyle> The DN of a single, specific entry
group.<groupstyle> A group containing member entries
ssf The overall Security Strength Factor
tls_ssf Security Strength Factor for TLS connections
sasl_ssf Security Strength Factor for SASL connections
transport_ssf Security Strength Factor for all transport levels
peername The socket address of the client
sockname The socket address of the server listener
sockurl The URL of the server listener
domain The DNS name of the client
set ACL sets

While "*", "anonymous", "users" and "self" are simple, the "dn.<style>", "group.<style>"and "ssf" specifiers deserve further explanation:

dn.[dnstyle]

DN Style Description
exact/base A single entry
regex A POSIX 'extended' regular expression to match entries
one(level) Entries one level below the specified DN
sub(tree) Entries at any level below the specified DN
children Entries that are subordinate to the specified DN

DN Style Examples

By an exact DN:

to <what> by dn.exact="uid=replicator,ou=services,dc=example,dc=com" <permission>

By DNs that match a regular expression:

to <what> by dn.regex="uid=apache_\w+,ou=services,dc=example,dc=com" <permission>

By all DNs one level below dc=example,dc=com:

 to <what> by dn.one="dc=example,dc=com" <permission>

 By all DNs in the “dc=example,dc=com” subtree.

to <what> by dn.sub="dc=example,dc=com" <permission>

By all DNs that are children of “ou=people,dc=example,dc=com”.

to <what> by dn.children="ou=people,dc=example,dc=com" <permission>

group.[groupstyle]

The most common groupstyle is “exact”. There is also an “expand” style which uses variable substitution using regular expressions (see: 8.4.5 Managing Access with Groups in the OpenLDAP handbook).

For maximum flexibility, the syntax group/groupOfNames/member.exact="" can be used to cover types of groups or group membership. If using groups that require unique members, use group/groupOfUniqueNames/uniqueMember.exact="".

Group Style Example:

Allow access to members of the “cn=student-read,ou=groups,dc=example,dc=com” group to read specified resources.

to <what> by group/groupOfNames/member.exact="cn=student-read,ou=groups,dc=example,dc=com" <permission>

SSF (Security Strength Factor)

The server uses Security Strength Factors (SSF) to indicate the relative strength of protection. A SSF of zero (0) indicates no protections are in place. A SSF of one (1) indicates integrity protection are in place. A SSF greater than one (>1) roughly correlates to the effective encryption key length.

SSF Examples

Require encryption of any strength for read permission:

to <what> by ssf=1 read

Require 256 bit encryption for write operations performed via TLS connections:

to <what> by tls_ssf=256 write

ACLs - The "permission" Clause

Permissions can be granted by either assigning a level or privilege

Permissions (in order from least to most):

Level Privilege Description
none 0 No permission granted
disclose d Allow disclosure of information on error
auth x Permission to access attribute for authorization
compare c Permission to compare attributes
search s Permission to search for entries
read r Permission to read entries/attributes
write (add/modify/delete) w/a/z Permission to write, modify, add or delete resources
manage m All permissions + administrative access

When using levels, each level inherits all the permission levels above.

For example, the "read" level includes "disclose", "auth", "compare" and "search". The "write" level includes "read" and above levels.

Privileges are more granular, and allow assignment, escalation and deescalation using the "=", "+", and "-" operators.

Under most circumstances, using levels is sufficient.

Permission Examples

Allow access to the userPassword attribute by anonymous users for authorization and no access for anyone else. (Note: auth access allows an attribute to be used for authorization internally, but will not be readable externally):

to attrs=userPassword by anonymous auth by * none

Allow read access to "ou=janitorial,dc=example,dc=com" by the “cn=janitorial-read,ou=groups,dc=example,dc=com” and write access by the “cn=janitorial-write,ou=groups,dc=example,dc=com” group:

to dn.subtree="ou=janitorial,dc=example,dc=com"

by group/groupOfNames/member="cn=janitorial-read,ou=groups,dc=example,dc=com" read by group/groupOfNames/member="cn=janitorial-write,ou=groups,dc=example,dc=com" write

ACLs - ACL Controls

There are three types of controls:

stop = If a condition within the rule is matched, stop evaluating further access controls and return the access level.

continue = If a rule is matched, continue evaluating the conditions within that rule.

break = If a rule is matched, break out of that rule and start evaluating the next one.

The stop condition is the default, so if the "continue" and "break" controls are not specified, the "stop" condition is applied.

Control Usage

Controls come after a <permission>:

to <what> by <who> <permission> <control>

ACL Control Examples

Usual starting ACL, giving full access to "special" users:

access to *

  by dn.exact="cn=replicator,dc=example,dc=com" read

  by dn.exact="cn=appadmin,ou=services,dc=example,dc=com" write
by * break

Controlling access to an attribute, but entry type not specified, continues to next ACL:

access to attrs=userPassword
by anonymous auth
by self write
by dn.exact="uid=appadmin,ou=services,dc=example,dc=com" manage
by group/groupofmembers/member.exact="cn=Admins,ou=Groups,dc=example,dc=com" write
by dn.exact="cn=replicator,o=nyu" read

Continue control to "layer" access:

access to dn.subtree="ou=services,dc=example,dc=com"

  by by group/groupofmembers/member.exact="cn=Audit,ou=Groups,dc=example,dc=com" read continue
by group/groupofmembers/member.exact="cn=Admins,ou=Groups,dc=example,dc=com" write by * break

 ACL Best Practices

  • Start off with limited access to everything by everyone
  • Very specific and commonly encountered rules should be written first (replication and service accounts). This increases efficiency.
  • Specific rules regarding attribute should come next.

Regular Expressions

Always use dn.regex=<pattern> when you intend to use regular expression matching. dn=<pattern> alone defaults to dn.exact<pattern> (in some historic versions, it used to default to dn.regex=<pattern>). As a consequence, an explicit style clears any doubt about what you're doing.

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.

To include "dc=example,dc=com" in the matching patterns:

dn.subtree="dc=example,dc=com"

To exclude "dc=example,dc=com" from the matching patterns:

dn.children="dc=example,dc=com"

To allow exactly one sublevel matches only:

dn.onelevel="dc=example,dc=com"

Always use ^ and $ in regexes, whenever appropriate, because:

ou=(.+),ou=(.+),ou=adressbooks,o=basedn 

will match:

something=bla,ou=xxx,ou=yyy,ou=adressbooks,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.

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.

Copyright © 2020-2024 Symas Corporation. All rights reserved.
acls access control

Was this article helpful?

Yes
No
Give feedback about this article

Related Articles

  • Backup and Restore Process
  • Configuring PPolicy for OpenLDAP 2.4
  • Configuring Apache Fortress-OpenLDAP for High Availability
  • Referrals and Chaining
  • Symas Blog RSS Feed
  • Symas on Facebook
  • Symas on Twitter
  • Symas Blog
  • Symas on LinkedIn
  • Symas YouTube Channel

Copyright © 2023, Symas Corporation. All rights reserved. Privacy Statement (updated July 31, 2023)

Phone:

Main Office: +1.650.963.7601
Fax: +1.650.390.6284

Email:

Sales: sales@symas.com
Support: support@symas.com

Office Hours:

8:00 AM - 5:00 PM ET

Office Location:

Symas Corporation
PO Box 391
Grand Junction, CO 81507 USA

Expand