SLAPO-ACCESSLOG(5)

πŸ¦‹ NAME πŸ¦‹

okay so this manual page is for slapo-accesslog β€” the Access Logging overlay to slapd. It's giving section 5, File Formats Manual energy, so it's all about the config file, not a command you run directly. bestie, this is where you learn how to make your LDAP server keep receipts. πŸ’…

✨ SYNOPSIS ✨

The config lives here:

/etc/openldap/slapd.conf

πŸ’– DESCRIPTION πŸ’–

The Access Logging overlay can be used to record all accesses to a given backend database on another database. Translation? Your backend activity can be reviewed using arbitrary LDAP queries instead of just logging to local flat text files. It's literally the main character of audit setups. πŸ‘‘

Configuration options are available for selecting a subset of operation types to log, and to automatically prune older log records from the logging database. Log records are stored with audit schema (see below) to assure their readability whether viewed as LDIF or in raw form. no cap, that's the whole vibe.

πŸŽ€ CONFIGURATION πŸŽ€

These slapd.conf options apply to the Access Logging overlay. They should appear after the overlay directive. order matters, bestie, don't just yeet them anywhere. 🫢

  • logdb <suffix> β€” Specify the suffix of a database to be used for storing the log records. The specified database must be defined elsewhere in the configuration and must support an ordered return of results such as slapd-mdb(5). The access controls on the log database should prevent general access. The suffix entry of the log database will be created automatically by this overlay. The log entries will be generated as the immediate children of the suffix entry. lock it down, fr fr. πŸ”₯
  • logops <operations> β€” Specify which types of operations to log. The valid operation types are abandon, add, bind, compare, delete, extended, modify, modrdn, search, and unbind. Aliases for common sets of operations are also available:
    • writes β€” add, delete, modify, modrdn
    • reads β€” compare, search
    • session β€” abandon, bind, unbind
    • all β€” all operations
  • logbase <operations> <baseDN> β€” Specify a set of operations that will only be logged if they occur under a specific subtree of the database. The operation types are as above for the logops setting, and delimited by a '|' character. it's giving subtree-specific surveillance. πŸ•΅οΈ
  • logold <filter> β€” Specify a filter for matching against Deleted and Modified entries. If the entry matches the filter, the old contents of the entry will be logged along with the current request. old data said hold my purse. πŸ’…
  • logoldattr <attr> ... β€” Specify a list of attributes whose old contents are always logged in Modify and ModRDN requests that match any of the filters configured in logold. Usually only the contents of attributes that were actually modified will be logged; by default no old attributes are logged for ModRDN requests. so pick your faves and they'll always show up in the receipt. πŸŽ€
  • logpurge <age> <interval> β€” Specify the maximum age for log entries to be retained in the database, and how often to scan the database for old entries. Both the age and interval are specified as a time span in days, hours, minutes, and seconds. The time format is [ddd+]hh:mm[:ss] i.e., the days and seconds components are optional but hours and minutes are required. Except for days, which can be up to 5 digits, each numeric field must be exactly two digits. For example:
logpurge 2+00:00 1+00:00

would specify that the log database should be scanned every day for old entries, and entries older than two days should be deleted. When using a log database that supports ordered indexing on generalizedTime attributes, specifying an eq index on the reqStart attribute will greatly benefit the performance of the purge operation. so if you want that speed, do the index. iykyk. ⚑

  • logsuccess TRUE | FALSE β€” If set to TRUE then log records will only be generated for successful requests, i.e., requests that produce a result code of 0 (LDAP_SUCCESS). If FALSE, log records are generated for all requests whether they succeed or not. The default is FALSE. yes, it logs the flops too unless you say otherwise. 😭

🌈 EXAMPLES 🌈

            database mdb
            suffix dc=example,dc=com
            ...
            overlay accesslog
            logdb cn=log
            logops writes reads
            logbase search|compare ou=testing,dc=example,dc=com
            logold (objectclass=person)

            database mdb
            suffix cn=log
            ...
            index reqStart eq
            access to *
              by dn.base="cn=admin,dc=example,dc=com" read

πŸ’Ύ SCHEMA πŸ’Ύ

okay bestie, deep breath, because this is the part where the accesslog overlay shows you its whole blueprint. The accesslog overlay runs on the audit schema, which is written right here in this very page. And lowkey, this schema exists for accesslog auditing and nothing else β€” it's not meant to be used any other way. Also important: this schema is a work in progress, so it can change without notice. πŸ’€ The overlay loads it automatically though, so you don't have to do anything. 🫢

The schema is a whole crew of object classes plus their attribute types, all described down below.


🏠 the root entry

The root entry of the underlying accesslog database rocks the auditContainer class, and it looks exactly like this:

(  1.3.6.1.4.1.4203.666.11.5.2.0
    NAME 'auditContainer'
    DESC 'AuditLog container'
    SUP top STRUCTURAL
    MAY ( cn $ reqStart $ reqEnd ) )

🌳 the object class family tree

There's a basic auditObject class, and from it two more classes are derived: auditReadObject and auditWriteObject. Then object classes for each type of LDAP operation branch off from those. It's giving flexible-yet-efficient, because this hierarchy lets you search the log either by one specific operation type's class or by the more general classifications. iconic design tbh.

Here's the auditObject definition:

(  1.3.6.1.4.1.4203.666.11.5.2.1
    NAME 'auditObject'
    DESC 'OpenLDAP request auditing'
    SUP top STRUCTURAL
    MUST ( reqStart $ reqType $ reqSession )
    MAY ( reqDN $ reqAuthzID $ reqControls $ reqRespControls $
        reqEnd $ reqResult $ reqMessage $ reqReferral $ reqEntryUUID
) )
ngl heads up: every single OID in this logging schema currently lives under the OpenLDAP Experimental branch. The plan is for them to migrate to a Standard branch in the future. ✨

πŸ“‹ the attributes, one by one

A lil overview tour, bestie:

  • reqStart and reqEnd β€” the start time and end time of the operation, respectively. They use generalizedTime syntax. Bonus: reqStart also does double duty as the RDN for each log entry. main character energy fr. πŸ‘‘
  • reqType β€” a simple string holding the type of operation being logged, e.g. add, delete, search, etc. For extended operations, the type also includes the OID of the extended operation, e.g. extended(1.1.1.1).
  • reqSession β€” an implementation-specific identifier that's common to all the operations tied to the same LDAP session. Currently this is slapd's internal connection ID, stored in decimal.
  • reqDN β€” the distinguishedName of the target of the operation. Like, for a Bind request this is the Bind DN. For an Add request it's the DN of the entry being added. For a Search request it's the base DN of the search. slay. πŸŽ€
  • reqAuthzID β€” the distinguishedName of the user who performed the operation. Usually it's the same name established at the start of a session by a Bind request (if any), but it may get altered in various circumstances.
  • reqControls and reqRespControls β€” any controls sent by the client on the request, and any returned by the server in the response, respectively. The values are just uninterpreted octet strings, no decoding, no drama.
  • reqResult β€” the numeric LDAP result code of the operation, showing either success or a particular LDAP error code. An error code may come with a text error message, and that message gets recorded in the reqMessage attribute.
  • reqReferral β€” carries any referrals that came back with the result of the request.
  • reqEntryUUID β€” records the entryUUID attribute of the entry that was operated on. For an Add request, this is the entryUUID of the newly created entry. baby's first UUID πŸ₯Ή

πŸ› οΈ the operation-specific classes

These have extra attributes to carry all the relevant params of their operation:

abandon

(  1.3.6.1.4.1.4203.666.11.5.2.4
    NAME 'auditAbandon'
    DESC 'Abandon operation'
    SUP auditObject STRUCTURAL
    MUST reqId )

For the Abandon operation, reqId contains the message ID of the request that got abandoned.

add

(  1.3.6.1.4.1.4203.666.11.5.2.5
    NAME 'auditAdd'
    DESC 'Add operation'
    SUP auditWriteObject STRUCTURAL
    MUST reqMod )

The Add class inherits from auditWriteObject, and Add and Modify are basically twinsies. The reqMod attribute carries all the attributes of the original entry being added. (Or, for a Modify operation, all of the modifications being performed.) The values are formatted as:

attribute:<+|-|=|#> [ value]

Where '+' means Add of a value, '-' means Delete, '=' means Replace, and '#' means Increment. And fun fact: in an Add operation, all the reqMod values will carry the '+' designator. πŸ’…

bind

(  1.3.6.1.4.1.4203.666.11.5.2.6
    NAME 'auditBind'
    DESC 'Bind operation'
    SUP auditObject STRUCTURAL
    MUST ( reqVersion $ reqMethod ) )

The Bind class includes reqVersion, which holds the LDAP protocol version specified in the Bind, plus reqMethod, which holds the Bind Method used in the Bind. That'll be the string SIMPLE for LDAP Simple Binds, or SASL(<mech>) for SASL Binds.

⚠️ real talk: unless it's configured as a global overlay, only Simple Binds using DNs that live in the current database get logged. So don't come for the log wondering where the rest went. 😭

compare

(  1.3.6.1.4.1.4203.666.11.5.2.7
    NAME 'auditCompare'
    DESC 'Compare operation'
    SUP auditObject STRUCTURAL
    MUST reqAssertion )

For the Compare operation, the reqAssertion attribute carries the Attribute Value Assertion used in the compare request.

delete

(  1.3.6.1.4.1.4203.666.11.5.2.8
    NAME 'auditDelete'
    DESC 'Delete operation'
    SUP auditWriteObject STRUCTURAL
    MAY reqOld )

The Delete operation needs no further parameters. That said, the reqOld attribute may optionally be used to record the contents of the entry before it got deleted πŸͺ¦ β€” the values are formatted as:

attribute: value

And heads up: reqOld is only populated if the entry being deleted matches the configured logold filter.

modify

(  1.3.6.1.4.1.4203.666.11.5.2.9
    NAME 'auditModify'
    DESC 'Modify operation'
    SUP auditWriteObject STRUCTURAL
    MAY ( reqOld $ reqMod ) )

The Modify operation holds a description of modifications in the reqMod attribute, which we already covered up in the Add operation. It may optionally hold the previous contents of any modified attributes in the reqOld attribute, using the same format as described above for the Delete operation. And again: reqOld is only populated if the entry being modified matches the configured logold filter.

modrdn

(  1.3.6.1.4.1.4203.666.11.5.2.10
    NAME 'auditModRDN'
    DESC 'ModRDN operation'
    SUP auditWriteObject STRUCTURAL
    MUST ( reqNewRDN $ reqDeleteOldRDN )
    MAY ( reqNewSuperior $ reqMod $ reqOld ) )

The ModRDN class uses reqNewRDN to carry the new RDN of the request. The reqDeleteOldRDN attribute is a Boolean showing TRUE if the old RDN was deleted from the entry, or FALSE if it was preserved. The reqNewSuperior attribute carries the DN of the new parent entry if the request specified the new parent. And reqOld is only populated if the entry being modified matches the configured logold filter and contains attributes in the logoldattr list.

(  1.3.6.1.4.1.4203.666.11.5.2.11
    NAME 'auditSearch'
    DESC 'Search operation'
    SUP auditReadObject STRUCTURAL
    MUST ( reqScope $ reqDerefAliases $ reqAttrsOnly )
    MAY ( reqFilter $ reqAttr $ reqEntries $ reqSizeLimit $
          reqTimeLimit ) )

For the Search class, reqScope holds the scope of the original search request using the values specified for the LDAP URL format β€” that's base, one, sub, or subord. The reqDerefAliases attribute is one of never, finding, searching, or always, showing how aliases get processed during the search. The reqAttrsOnly attribute is a Boolean showing TRUE if only attribute names were requested, or FALSE if attributes and their values were requested. The reqFilter attribute carries the filter used in the search request. The reqAttr attribute lists the requested attributes, if specific attributes were requested. The reqEntries attribute is the integer count of how many entries came back from this search request. And reqSizeLimit and reqTimeLimit tell you what limits were requested on the search operation.

extended

(  1.3.6.1.4.1.4203.666.11.5.2.12
    NAME 'auditExtended'
    DESC 'Extended operation'
    SUP auditObject STRUCTURAL
    MAY reqData )

The Extended class represents an LDAP Extended Operation. And like we said up above, the actual OID of the operation is included in the reqType attribute of the parent class. If any optional data was provided with the request, it'll be sitting in the reqData attribute as an uninterpreted octet string. 🌈


πŸ“ NOTES πŸ“

The Access Log implemented by this overlay can be used for a whole variety of other tasks too β€” for example as a ChangeLog for a replication mechanism, and also for security/audit logging purposes. multitasking queen πŸ’…


πŸ“ FILES πŸ“

  • /etc/openldap/slapd.conf β€” the default slapd configuration file

πŸ‘€ SEE ALSO πŸ‘€


🫢 ACKNOWLEDGEMENTS 🫢

This module was written in 2005 by Howard Chu of Symas Corporation. a legend, no cap. πŸ‘‘


and that's the whole page bestie!! 🌸 this was OpenLDAP 2.7.2, dated 2026/10/21, and SLAPO-ACCESSLOG(5) is officially a wrap. go forth and audit, you gorgeous nerd. πŸ¦‹πŸ’–βœ¨

πŸ“¦ where this page comes from