Controlling who can see and change what in the directory: the concepts of subject, object, and permission, the eight access levels, the olcAccess syntax, ACL examples for anonymous access, self password changes, and groups, plus least privilege practices.

In episode 9 you were free to search anything as admin. In the real world that's not what happens — a directory is used by hundreds of users, and each user should only see a subset of the data. Episode 10 covers access control lists (ACLs): the language that answers three questions — who, on what, and with what capability.
An ACL rule has three components:
| Component | Question | Example |
|---|---|---|
| Who | Who is the subject? | by dn.exact="cn=admin,dc=example,dc=com" write |
| What | Which entry or attribute is the object? | to attrs=userPassword |
| How | What permission is granted? | write |
Subjects can be a specific DN, a DN pattern (dn.subtree), a group, or special categories like self, users (those who bound successfully), anonymous, and * (everyone). Objects can be the whole entry (to *) or specific attributes (to attrs=mail). How evaluation works: rules are read top to bottom, and the first match wins.
OpenLDAP 2.5 defines eight levels, from weakest to strongest:
| Level | Capability |
|---|---|
none | No access at all |
disclose | Only allowed to know the entry or attribute exists |
auth | May be used for bind and authentication, without reading contents |
compare | May be compared with ldapcompare |
search | May appear in search results and be used in filters |
read | May read the attribute's contents |
write | May add, change, and delete |
manage | Full administrative control, including ACL management |
The level hierarchy is cumulative: read implies search and compare; write implies read; manage covers everything.
ACLs are stored as the olcAccess attribute on the olcDatabase entry in cn=config. The line format: an index sequence (0, 1, 2, and so on), then to for the object, followed by one or more by clauses for subjects and permissions:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to * by dn.exact="cn=admin,dc=example,dc=com" write by * readRead this rule: for all objects, the admin with that exact DN gets write, everyone else gets read. If a by clause doesn't match, evaluation moves to the next by in the same rule; if the whole rule doesn't match, it moves to the next olcAccess.
The default slapd pattern at installation already contains rules for userPassword and other basics. The bottom rule determines what happens when no rule matches:
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {1}to * by * readThe first rule restricts userPassword: owners can write, anonymous users get auth (for bind), everyone else none. The second rule grants general read access to the entire directory.
For public data like a phone directory:
olcAccess: {0}to dn.subtree="ou=People,dc=example,dc=com" by * readThe classic rule that lets users change their own password without being able to read anyone else's:
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * noneolcAccess: {0}to * by dn.exact="cn=admin,dc=example,dc=com" manage by * noneGiving read access to members of a specific group:
olcAccess: {0}to dn.subtree="ou=People,dc=example,dc=com" by group.exact="cn=devel,ou=Groups,dc=example,dc=com" read by * noneSeparating public attributes from private ones in the same entry:
olcAccess: {0}to attrs=mail,telephoneNumber by users read by * none
olcAccess: {1}to * by self read by * noneThe result: anyone can read other users' mail and telephoneNumber, but only the owner can read the other attributes on their entry.
Because evaluation follows a first-match-wins principle, more specific rules must come first. A to attrs=userPassword rule must appear before to *, and a to dn.subtree="ou=People,dc=example,dc=com" rule must appear before to *. Violating this order is the most common source of ACL bugs: a broad rule up front "swallows" the request before the specific rule is ever evaluated.
Important
When adding a new olcAccess, always state its index explicitly. Adding one without an index places the rule in the first position — and can suddenly block access that older rules previously allowed.
by * none, not by * read.ldapsearch -x -D "uid=budi,ou=People,dc=example,dc=com" -W -b dc=example,dc=com "(objectClass=*)"Note that attributes you're not allowed to see are hidden from the results, or appear with empty values, depending on the level granted.
olcAccess regularly with the security team.Episode 10 gives you full control over data visibility: the three ACL components who, what, how; the eight access levels from none to manage; the olcAccess syntax with the to and by directives; a range of examples from anonymous access, self password, admin, group, to per-attribute; and the golden rule of first-match-wins with specific rules first.
Key takeaways:
manage is the highest.by * none and apply least privilege.In the next episode, episode 11, we add OpenLDAP's modular features: overlays. You'll enable memberOf for automatic membership tracking, ppolicy for password policies, and syncprov for replication.