Planning of LDAP DIT Structure and Config of Overlays ( access, ppolicy )

This entry is part 4 of 8 in the series Openldap Tutorial

LDAP DIT Structure Plan

Based on the scenario discussed in the first article, we need to plan our Directory Interface Tree (DIT) before doing the real implementation. This will give us a clear idea on what we should do which would be difficult otherwise. The below LDAP DIT Structure Plan diagram provides a complete overview of what we need.



If you could recollect our requirement, we need to integrate LDAP with  linux clients, graylog and basic authentication for apps.

The suffix we already have is dc=devopsideas,dc=com. The suffix will have 4 containers (organization units)

- people

- group

- pwpolicies

- service_ids


This container/node will hold all the user entries. To make it simple we will be creating only two users. One user is assumed to be from Dev Team and the other from Admin Team. So in this example,

cn=chris.sam (Admin)
cn=aron.francis (Dev)


Distinguished Name (DN) for users

Based on the diagram the distinguished name for the users within the ou=people container will be,

# Distinguished Name for users



The ObjectClass that will be used in order to get the required attributes for the users are,








This container will hold all the groups entires. In this case we are creating separate containers for graylog, Linux servers and basic authentication which in turn contains entries.


The graylog group (ou=graylog,ou=group,dc=devopsideas,dc=com) will have two entries, graylog_dev and graylog_admin. The objectClass that will be used to create this entry is groupOfNames.

People who are part of Dev and need only limited access will be member of graylog_dev entry

People who are part of Admin and need full access will be member of graylog_admin entry

So in this example, the user chris.sam will be member of graylog_admin and the user aron.francis will be member of graylog_dev. Thus by using memberOf attribute we are enforcing Access Control.


NoteThe memberOf is a special attribute that does not come out of the box. We need to load it externally and add it as part of overlay. You can refer the Overlay section for this.




The server group (ou=server,ou=group,dc=devopsideas,dc=com) will have two entries similar to graylog, server_dev and server_admin. The objectClass that will be used to create this entry is groupOfNames and posixGroup.

People who are part of Dev team and who requires minimal access ( non sudo ) will be member of server_dev

People who are part of Admin team and who requires complete access ( sudo ) will be member of server_admin


Basic Authentication

The basic authentication group (ou=basic_authentication,ou=group,dc=devopsideas,dc=com) has two entries app1 and app2. The objectClass that will be used to create this entry is groupOfNames. For this example, both the users will be member of both the entries.



The service_ids (ou=service_ids,dc=devopsideas,dc=com) container will contain the list of service id’s that will be used for binding (authenticating) the client to LDAP. We will be using two service id’s in this example.

# Will be used for binding graylog with LDAP

# Will be used for binding Linux clients with LDAP

We will be using inetOrgPerson objectClass to create this entry



This container will hold the entries for Password Policy. Password policy is nothing but setting rules for password. We will be creating two password policy. One for end users and the other for the service id’s.

# Password policy for users

# Password policy for service id's

Apart from the default password policy that comes with pwdPolicy objectClass, we will also be including an external module pqchecker ( Password Quality Checker ) to meet our needs. Basically this is needed to set additional password quality contraints like Number of upper case letters, No of special characters etc which are not available in the default pwdPolicy.

The objectClasses that we will use for the entries of pwpolicies are  pwdPolicy, pwdPolicyChecker and person

Next we


From the official definition, Overlays are software components that provide hooks to functions analogous to those provided by backends, which can be stacked on top of the backend calls and as callbacks on top of backend responses to alter their behaviour.

LDAP Overlay

Overlays are used to influence the behaviour of an existing backend without having to adapt or rewrite the backend itself. For this purpose, the overlay is connected upstream to the slapd server to ensure that messages reach the server in a filtered way or leave it in a changed manner. Most overlays are to be used at the database level, but often not restricted to a backend type.

Overlays basically sits in between the frontend and the backend and performs operations based on their type.

For example, let us assume that we need to perform auditing of our LDAP server. In order to achieve this, we should have audit overlay module enabled. Auditlog overlay basically keeps track of who modified what at what times?. This will provide us with required details for performing auditing

Similarly we can use Ppolicy overlay to check if the password set by the user meets the required standard, set as part of that specific overlay.


Enable Auditlog overlay

For enabling audit logging, we first need to load the auditlog module.  Create a file with the name auditlog.ldif and copy the below content.

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad

The dn, cn=module{0},cn=config is where the module details are present. We are updating this entry to add the auditlog module.

Run the below command to import the LDIF file and load the auditlog module

ldapmodify -W -D cn=admin,cn=config -f auditlog.ldif

Now that we have the module loaded for auditlog, we need to configure and enable the auditlog overlay. Create a file with the name audit_config.ldif and copy the below content.

changetype: add
objectClass: olcOverlayConfig
objectClass: olcAuditLogConfig
olcOverlay: auditlog
olcAuditlogFile: /var/log/openldap/auditlog.ldif

Here we are specifying the logfile path using olcAuditlogFile attribute. olcOverlay:  auditlog indicates that this configuration is for auditlog overlay. The olcAuditlogFile attribute is available through olcAuditLogConfig.

Import audit_config.ldif file as below,

ldapadd -W -D cn=admin,cn=config -f audit_config.ldif

Auditlog is configured and good to go now.


Enable ppolicy overlay

First we need to load the ppolicy schema into OLC.

ldapmodify -W -D "cn=admin,cn=config" -f /etc/ldap/schema/ppolicy.ldif

Next we need to load the ppolicy module similar to what we did for auditlog. Create a file named ppolicymodule.ldif and copy the below content

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad

Load the module,

ldapmodify -W -D "cn=admin,cn=config" -f ppolicymodule.ldif


Next, configure ppolicy overlay. Create a file named ppolicyoverlay.ldif and copy the below content.

dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=userPasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com
olcPPolicyHashCleartext: TRUE
olcPPolicyUseLockout: FALSE
olcPPolicyForwardUpdates: FALSE


There are few important attributes to note here,

olcPPolicyDefault –  This attribute/directive defines the DN of a default password policy that will be used in the absence of any user specific password policy.  For now we are just specifying this DN now we will specify its entries later.

olcPPolicyHashCleartext – This attribute/directive tells the server to save cleartext passwords, supplied using normal Add or Modify requests, in the DIT using the server’s default hash algorithm. Without this directive the passwords would be stored in cleartext meaning that simple searches would return the cleartext password.

olcPPolicyUseLockout – Bind attempts to locked accounts will always return an error (by default InvalidCredentials). This attribute/directive allows the server to return a specific AccountLocked error code. As a note of caution returning an AccountLocked error code may assist hackers in that they can observe effects on the server of various access attempts and derive operational settings (such as lockout thresholds) which may assist them in subsequent attacks.

olcPPolicyForwardUpdates – This attribute/directive is only applicable for a slave (consumer) configuration. If present the attribute/directive indicates that password policy failures will not be maintained on the slave (consumer) but will be immediately written to the master (provider).


Load this configuration by running,

ldapadd -W -D cn=admin,cn=config -f ppolicyoverlay.ldif


We are done with enabling ppolicy overlay.


Install pqchecker module ( Password Quality )

As discussed earlier, ppolicy overlay module  does not provide option to check the quality of the password. Hence we need to make use of external modules for this. We will be using pqchecker in this example.

Follow the below steps to install pqchecker,

$ apt-get install jsvc
$ wget
$ tar -xvf pqchecker-1.2.2-amd64.deb.tgz
$ dpkg -i pqchecker_1.2.2_amd64.deb

Once installed, we need to set the complexity rule in the pqchecker configuration file.

vi  /etc/ldap/pqchecker/pqparams.dat

You can set the complexity based on your need. For this example we will keep the default rule. The comments in the file are self explanatory to define the rule.

# Data format UULLDDSS@)..
# U: Uppercase, L: Lowercase, D: Digit, S: Special, characters -> 8 first charaters
# From the 9th character begins the list of forbidden characters
# Default 1 Uppercase, 1 Lowercase, 1 digit, 1 Special and no forbidden characters


Password Policy Definition

userPasswordPolicy Definition:

We have enabled ppolicy overlay and gave the value for olcPPolicyDefault pointing to a DN. Let’s define the password policy. Create a file named ppolicyuserdef.ldif and copy the below content.

dn: cn=userPasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com
objectClass: pwdPolicy
objectClass: person
objectClass: top
objectClass: pwdPolicyChecker
cn: userPasswordPolicy
sn: userPasswordPolicy
pwdAttribute: userPassword
pwdCheckQuality: 2
pwdExpireWarning: 604800
pwdInHistory: 2
pwdLockout: TRUE
pwdLockoutDuration: 0
pwdMaxAge: 2592000
pwdMaxFailure: 3
pwdMinLength: 10
pwdGraceAuthNLimit: 0
pwdFailureCountInterval: 0
pwdAllowUserChange: TRUE
pwdMustChange: TRUE


The default password policy that we are applying is for the DN,


You can refer this site to get detailed explanation on the attribute used. To cover some basic rules,

pwdCheckModule – This attribute defines the name to a user supplied password quality check module that will be called to perform password quality checks

pwdMaxAge –  Defines how long the password is valid. In this case we are giving it as 2 months.

pwdMaxFailure – This attribute controls how many consecutive password failures are allowed before the action defined by pwdLockout is taken. A value of 3 here indicates the password will be locked after 3 unsuccessful attempts


Before importing this configuraiton, we need to create OU for pwpolicies. Create a file named pwpolicies_ou.ldif and copy the below content.

dn: ou=pwpolicies,dc=devopsideas,dc=com
objectClass: organizationalUnit
ou: pwpolicies
description: password policy branch


Run the below command to create the OU for pwpolicies

ldapadd -W -Z -D cn=admin,dc=devopsideas,dc=com -f pwpolicies_ou.ldif


Now that we have the OU ready, let’s load the password policy configuration by running the below command.

ldapadd -W -Z -D cn=admin,dc=devopsideas,dc=com -f ppolicyuserdef.ldif

Recollect we are passing -Z in the command to issue StartTLS since we have enforced TLS for this DIT.


servicePasswordPolicy Definition:

We will also be defining a policy for servicePasswordPolicy. This policy will be applied to the service id’s that we will create later. Basically we will be using service id’s to do the initial bind to the LDAP server from the client. Since this will be used only by application and not by end users, we need to tweak the password policy definition a bit. We need to update pwdMaxAge attribute such that the password doesn’t expire.

Create a file named ppolicyservicedef.ldif and copy the below content.

dn: cn=servicePasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com
objectClass: pwdPolicy
objectClass: person
objectClass: top
objectClass: pwdPolicyChecker
cn: servicePasswordPolicy
sn: servicePasswordPolicy
pwdAttribute: userPassword
pwdCheckQuality: 2
pwdLockoutDuration: 0
pwdMinLength: 10
pwdGraceAuthNLimit: 0
pwdFailureCountInterval: 0
pwdAllowUserChange: TRUE


We did not specify pwdMaxage in this definition which means it’ll take the default value which is 0 ( doesn’t expire ). We have included pqchecker module similar to user ppolicy definition for qualitiy check.

Run the below command to make the changes,

ldapadd -W -Z -D cn=admin,dc=devopsideas,dc=com -f ppolicyservicedef.ldif

With this, we have completed setting up password policy.


Enable Accesslog Overlay

The accesslog overlay is used to keep track of all or selected operations on a particular DIT (the target DIT, dc=devopsideas,dc=com) by writing details of the operations as entries to another DIT (the accesslog DIT). The accesslog DIT can be searched using standard LDAP queries. Accesslog overlay parameters control whether to log all or a subset of LDAP operations (logops) on the target DIT, to save related information such as the previous contents of attributes or entries (logold and logoldattr ) and when to remove log entries from the accesslog DIT. Accesslog DIT entries are stored using objectClasses and attributes in a specific audit schema.

If you are using accesslog DIT  for delta replication purposes, it must be defined as a provider through use of the syncprov overlay

Similar to all other overlays, we need to first enable the module for accesslog. Create a file named accesslog_module.ldif and copy the below content

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad

Run the below command to load the module,

ldapmodify -W -D "cn=admin,cn=config" -f accesslog_module.ldif



Enable memberOf overlay

In order to easily and efficiently do queries that enables you to see which users are part of which groups thereby applying access control, we need this thing called memberOf overlay

First enable the memberOf module by creating a file named memberOfmodule.ldif with the below content

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad

Run the below command to load the file and to make the change,

ldapadd -W -D cn=admin,cn=config -f memberOfmodule.ldif

Next, follow the below steps to configure and enable memberOf overlay. Create a file named memberOfconfig.ldif with the below content

dn: olcOverlay=memberof,olcDatabase={1}mdb,cn=config
changetype: add
objectClass: olcConfig
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: top
olcOverlay: memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf

Create memberOf overlay configuration by running below command,

ldapadd -W -D cn=admin,cn=config -f memberOfconfig.ldif


Create an LDIF file to activate referential integrity for the memberOf attributes. This overlay is useful to ensure that when user accounts are modified or deleted from the directory, the corresponding member attribute in groups in which the user was a member is also handled accordingly.

Enable refint, module by creating a file named refintmod.ldif containing the below content,

dn: cn=module{0},cn=config
add: olcmoduleload
olcmoduleload: refint

Run the below command to load the module,

ldapmodify -W -D cn=admin,cn=config -f refintmod.ldif

Create a file named refintconfig.ldif and copy the below content

dn: olcOverlay=refint,olcDatabase={1}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: refint
olcRefintAttribute: memberof member manager owner

Run the below command to apply the change

ldapadd -W -D cn=admin,cn=config -f refintconfig.ldif


We are done enabling memberOf overlay and configuring referential integrity for the same.


Accesslog DIT Creation:

Since accesslog overlay writes its entries in a separate DIT, we need to create the DIT first. Create a file named accesslogdit.ldif and copy the below content

dn: olcDatabase={2}mdb,cn=config
changetype: add
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {2}mdb
olcDbDirectory: /var/lib/ldap/accesslog
olcSuffix: cn=accesslog
olcRootDN: cn=admin,dc=devopsideas,dc=com
olcDbIndex: default eq
olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart

We are specifying olcDatabase as {2} mdb since {1}mdb contains are existing DIT dc=devopsideas,dc=com. Also note that we have specified /var/lib/ldap/accesslog as the DB directory. We need to make sure the directory exists with the right permission.

mkdir /var/lib/ldap/accesslog
chown openldap:openldap /var/lib/ldap/accesslog

Run the below command to create the accesslog DIT

ldapmodify -W -D cn=admin,cn=config -f accesslogdit.ldif


Enable Accesslog Overlay:

Copy the below content to a file named accesslogoverlay.ldif

dn: olcOverlay=accesslog,olcDatabase={1}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcAccessLogConfig
olcOverlay: accesslog
olcAccessLogDB: cn=accesslog
olcAccessLogOps: all
olcAccessLogSuccess: TRUE
olcAccessLogPurge: 30+00:00 01+00:00

olcAccessLogOpsDefines which types of operations on the target DIT to log to the accesslog DIT in a space separated list. The valid operation types are writes, reads, session, all. In this example we are logging all operations

olcAccessLogSuccess: If set to TRUE then accesslog entries will only be logged for successful requests, that is, requests that produce a result code of 0 (LDAP_SUCCESS). If FALSE, accesslog entries are added for defined operations irrespective of the result code. The default is FALSE. For use with delta-synchronization logsuccess must be set TRUE.

olcAccessLogPurge: Defines both the maximum age for log entries to be retained in the database and how often to scan the database for old entries. Both age and interval are specified as a time span in days, hours, minutes, and seconds. The time format is [ddd+]hh:mm[:ss], for example, 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

In this example we are keeping retaining the logs for a month and the scanning for old entries takes place every day.

Run the below command to execute the change,

ldapmodify -W -D cn=admin,cn=config -f accesslogoverlay.ldif



Activity Logging

Activity logging for slapd is indispensible when implementing an OpenLDAP-based solution yet it must be manually enabled after the installation. Otherwise, only rudimentary messages will appear in the logs.

OpenLDAP comes with multiple logging subsystems (levels) with each one containing the lower one (additive). A good level to try is stats. The slapd-config man page has more to say on the different subsystems.

Create the file logging.ldif with the following contents:

dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats

Implement the change:

ldapmodify -W -D cn=admin,cn=config -f logging.ldif


With that we have all the configurations in place for integrating our clients with openLDAP. In the next section we will create the necessary entries ( users, groups etc ) based on our DIT plan before integrating our clients.




Series Navigation<< Installing phpLDAPadmin – Web based LDAP ClientOpenLDAP – Graylog LDAP Integration >>


Established in 2016, a community where system admins and devops practitioners can find useful in-depth articles, latest trends and technologies, interview ideas, best practices and much more on Devops

Leave a Reply

Your email address will not be published. Required fields are marked *

seven + 11 =