OpenLDAP: Implementing the Password Policy Overlay
Sometimes I tend to be verbose. Click here to get to the meat of the post. Otherwise, read on.It's been some time since I configured OpenLDAP but I decided to use it on a new project I'm working on. Prior to this new effort, I used a simple database table to store user credentials because my requirements were, well, simple. Now, I need to extend the management capabilities of my project and delegate access according to group membership. In addition, I want to implement basic password management functions such as minimum password length, aging, etc. OpenLDAP's password policy overlay is perfect for this second criterion.
Only, something is missing: documentation. How I loathe missing documentation. The only thing worse is incorrect, incomplete, or out-of-date documentation. That's exactly what I found myself with when attempting to configure the password policy overlay for OpenLDAP using the the dynamic configuration backend:
cn=config.For more information on overlays, see http://www.openldap.org/doc/admin24/overlays.html. You'll note, unfortunately, that the documentation for the password policy overlay still references the
slapd.conf-method of configuring that overlay.NOTE: I used
slaptest to convert a temporary instance of slapd.conf into the cn=config backend objects I needed. Perhaps I'll post more on that process later.
I dig the
cn=config methodology. It makes sense to me and I've had no issues implementing custom backends for new directory instances. However, there is a dearth of clear, concise information available on how to configure the password policy overlay using the dynamic cn=config backend. Until now.Assumptions
To get started, I'll tell you what my assumptions are and what we'll end up with:- I'll assume (onerously, conceitedly) you're working on the same platform as me (AWS Micro Instance) running a generic Linux AMI.
- I'll assume you're familiar with the
ldap*andslap*commands. - I'll assume that you like the name of my directory instance:
snafoobar.com.
- You'll end up with a working, simple password policy overlay that is used to create a default password policy for one of your directory instances.
The Meat
For this example, the configuration lives in/etc/openldap/slapd.d/cn=config/. Our directory instance is specified in a file named olcDatabase={3}snafoobar.com.ldif:/etc/openldap/slapd.d/cn=config/
|
`-- olcDatabase={3}snafoobar.com.ldif
File Preparation
To create and configure the password policy overlay, start by creating a few files:cn=module{0}.ldif: The attributes in this file will tell LDAP which library to pull in so that the password policy overlay support is available.- Create a directory named
olcDatabase={3}snafoobar.com/in the root of thecn=configdirectory. This directory is named similar to the LDIF file used to define the directory instance; this is not an accident.
olcDatabase={3}snafoobar.com/olcOverlay={0}ppolicy.ldif: This LDIF file will contain the necessary configuration to define that we're implementing a password policy overlay, and, in turn, points to the actual password policy we will define..
/etc/openldap/slapd.d/cn=config/
|
|-- cn=module{0}.ldif
|-- olcDatabase={3}snafoobar.com
| `-- olcOverlay={0}ppolicy.ldif
`-- olcDatabase={3}snafoobar.com.ldif
cn=module{0}.ldif
cn=module{0}.ldif specifies which shared library LDAP should load to support the password policy overlay. Its contents should be as follows:dn: cn=module{0}
objectClass: olcModuleList
cn: module{0}
olcModuleLoad: {0}ppolicy.la
structuralObjectClass: olcModuleList
olcOverlay={0}ppolicy.ldif
olcOverlay={0}ppolicy.ldif should have the following attributes defined:dn: olcOverlay={0}ppolicy
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: {0}ppolicy
olcPPolicyDefault: cn=passwordDefault,ou=policies,dc=snafoobar,dc=com
olcPPolicyHashCleartext: FALSE
olcPPolicyUseLockout: FALSE
olcPPolicyForwardUpdates: FALSE
structuralObjectClass: olcPPolicyConfig
NOTE: I've already created the
ou=policies,dc=snafoobar,dc=com organizational unit in my directory instance. You'll need to do the same to follow this example.
Restart slapd
Do it. Restart slapd. I'll wait.passwordPolicy.ldif
You'll need to create an LDIF file that will contain the default password policy definition. I didn't mention this above as this file is not part of thecn=config hierarchy. Create a file named passwordPolicy.ldif (anywhere, except within the cn=config/ hierarchy) and add the following contents:dn: cn=passwordDefault,ou=policies,dc=snafoobar,dc=com
objectClass: pwdPolicy
objectClass: person
objectClass: top
cn: passwordDefault
sn: passwordDefault
pwdAttribute: userPassword
pwdCheckQuality: 0
pwdMinAge: 0
pwdMaxAge: 0
pwdMinLength: 5
pwdInHistory: 5
pwdMaxFailure: 3
pwdFailureCountInterval: 0
pwdLockout: TRUE
pwdLockoutDuration: 0
pwdAllowUserChange: TRUE
pwdExpireWarning: 0
pwdGraceAuthNLimit: 0
pwdMustChange: FALSE
pwdSafeModify: TRUE
NOTE: I'm leaving it as an exercise to you, the reader, to determine what the above attributes are and what is appropriate for your environment. I need these attributes configured with these values. You may require something different.
Add the entry into the directory instance (my LDIF lives in
~/ldif/):[root@awsInstance ~/ldif]# ldapadd -c -f passwordPolicy.ldif -D "cn=root,dc=snafoobar,dc=com" -x -w cleverBoysNeverTell
adding new entry "cn=passwordDefault,ou=policies,dc=snafoobar,dc=org"If you want to confirm that the new entry exists and a default password policy has been implemented, execute an
ldapsearch:[root@awsInstance ~/ldif]# ldapsearch -x -D cn=root,dc=snafoobar,dc=com -H ldap:// -b "dc=snafoobar,dc=com" -w cleverBoysNeverTell
# extended LDIF
#
# LDAPv3
# base with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
...
# policies, snafoobar.com
dn: ou=policies,dc=snafoobar,dc=com
ou: policies
objectClass: organizationalUnit
description: Default directory policies
# passwordDefault, policies, snafoobar.com
dn: cn=passwordDefault,ou=policies,dc=snafoobar,dc=com
objectClass: pwdPolicy
objectClass: person
objectClass: top
cn: passwordDefault
sn: passwordDefault
pwdAttribute: userPassword
pwdCheckQuality: 0
pwdMinAge: 0
pwdMaxAge: 0
pwdMinLength: 5
pwdInHistory: 5
pwdMaxFailure: 3
pwdFailureCountInterval: 0
pwdLockout: TRUE
pwdLockoutDuration: 0
pwdAllowUserChange: TRUE
pwdExpireWarning: 0
pwdGraceAuthNLimit: 0
pwdMustChange: FALSE
pwdSafeModify: TRUE
...
Fini!
You should now have an LDAP instance with a default password policy defined. Test it out by modifying user accounts' passwords (i.e. via your favorite LDAP browser or custom code).Tags