- Openldap Tutorial – Practical Realtime Implementation and Integration
- Installation and configuration of openldap in Ubuntu
- Installing phpLDAPadmin – Web based LDAP Client
- Planning of LDAP DIT Structure and Config of Overlays ( access, ppolicy )
- OpenLDAP – Graylog LDAP Integration
- openLDAP – Linux Client LDAP Integration
- openLDAP – Basic Authentication using LDAP
- openLDAP – Self Service Password and Adhoc LDAP utilities
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.
Plan Debrief
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
ou=people
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 cn=chris.sam,ou=people,dc=devopsideas,dc=com cn=aron.francis,ou=people,dc=devopsideas,dc=com
The ObjectClass that will be used in order to get the required attributes for the users are,
inetOrgPerson person top ldapPublicKey posixAccount
ou=group
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.
Graylog
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.
Note: The 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.
Server
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.
ou=service_ids
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 cn=serviceid,ou=service_ids,dc=devopsideas,dc=com # Will be used for binding Linux clients with LDAP cn=serverid,ou=service_ids,dc=devopsideas,dc=com
We will be using inetOrgPerson objectClass to create this entry
ou=pwpolicies
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 cn=userPasswordPolicy,ou=service_ids,dc=devopsideas,dc=com # Password policy for service id's cn=servicePasswordPlicy,ou=service_ids,dc=devopsideas,dc=com
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
Overlays
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.
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 olcModuleLoad: auditlog.la
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 olcModuleLoad: ppolicy.la
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 http://www.meddeb.net/data/pqchecker-1.2.2-amd64.deb.tgz $ 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
01010101
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 pwdCheckModule: pqchecker.so 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,
cn=userPasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com.
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 pwdCheckModule: pqchecker.so 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 olcModuleLoad: accesslog.la
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 olcModuleLoad: memberof.la
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
olcAccessLogOps: Defines 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.