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=config
directory. 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