Anyone who has worked with the Netscape /Iplanet /Sun /Redhat /Oracle family of LDAP directory servers knows you can set a global password policy for all user entries on the directory (you really can). What they might not realize is that it is possible to set a specialized password policy (i.e. a “targeted password policy”) that can be discretely applied to just one or more entries.
Everything that follows applies to the latest Oracle DSEE product. Important details will differ in other products, like 389 Directory.
Start by reviewing the documentation (link is to the latest Oracle DSEE 11gR1 release).
This Worksheet is a very helpful tool for recording the details of your password policy design.
Here is how to check the settings for the global password policy on a DSEE instance:
dsconf get-server-prop -h localhost -v -i | grep ^pwd-
Just some quick notes:
Here is what a specialized password policy entry looks like (this example is actually from the Sun Directory Server 5.2 Administration Guide):
dn: cn=TempPwdPolicy,dc=example,dc=com objectClass: top objectClass: passwordPolicy objectClass: LDAPsubentry cn: TempPwdPolicy passwordChange: on passwordMustChange: on passwordCheckSyntax: on passwordExp: on passwordMinLength: 6 passwordMaxAge: 8640000 passwordMinAge: 0 passwordWarning: 259200 passwordInHistory: 6 passwordLockout: on passwordMaxFailure: 3 passwordUnlock: on passwordLockoutDuration: 3600 passwordResetFailureCount: 600 passwordRootdnMayBypassModsChecks: on
By default DSEE 6+ (including ODSEE 11g) directories are created in “DS5 Compatibility Mode” for password policy purposes. This is to insure interoperability with older directory servers. As a result, if you use the above code to create a policy on a post version 5.2 DSEE, it will add the new attribute names and values appropriate to the later version. Thus:
dn: cn=TempPwdPolicy,dc=example,dc=com objectClass: top objectClass: ldapsubentry objectClass: passwordpolicy objectClass: pwdPolicy objectClass: sunPwdPolicy cn: TempPwdPolicy passwordChange: on passwordCheckSyntax: on passwordExp: on passwordInHistory: 6 passwordLockoutDuration: 3600 passwordMaxAge: 8640000 passwordMaxFailure: 3 passwordMinAge: 0 passwordMinLength: 6 passwordResetFailureCount: 600 passwordRootdnMayBypassModsChecks: on passwordUnlock: on passwordWarning: 259200 pwdAllowUserChange: TRUE pwdCheckQuality: 2 pwdExpireWarning: 259200 pwdFailureCountInterval: 600 pwdInHistory: 6 pwdMaxAge: 8640000 pwdMaxFailure: 3 pwdMinAge: 0 pwdMinLength: 6
This can be a real pain, since it requires the same change to be made in more than one place (for example, for password expiration times).
Here’s a purely post 5.2 DSEE (i.e. DSEE 6+) version of the same policy:
dn: cn=TempPwdPolicy,dc=example,dc=com objectClass: top objectClass: pwdPolicy objectClass: sunPwdPolicy objectClass: LDAPsubentry cn: TempPwdPolicy pwdAttribute: userPassword pwdAllowUserChange: TRUE pwdCheckQuality: 2 pwdLockout: TRUE pwdLockoutDuration: 3600 pwdMaxFailure: 3 pwdMustChange: TRUE pwdExpireWarning: 259200 pwdFailureCountInterval: 600 pwdInHistory: 6 pwdMaxAge: 8640000 pwdMaxFailure: 3 pwdMinAge: 0 pwdMinLength: 6 passwordRootdnMayBypassModsChecks: on
(note that pwdAttribute is required to create a post DS 5.2 password policy)
Loading this will still result in both old and new attribute types and values being added so long as compatibility mode is turned on.
This is how you would search for a specialized password policy (or any other “special” object of the “ldapsubentry” class):
ldapsearch -x -h localhost -D "cn=directory manager" -W -b "dc=example,dc=com" -s sub "(objectclass=ldapsubentry)"
(Note: Searching for “(objectclass=passwordpolicy)” will yield nothing — I don’t know why)
Most LDAP tree editors will not display ldapsubentry objects automatically. They need to be searched for explicitly because they are system/operational in nature. Apache Directory Studio will show them if you perform a “Quick” or regular search for “(objectclass=ldapsubentry)”.
There are a couple of ways to make a specialized policy apply to a given user. The “brute force” (or “blunt instrument”) method is to add an attribute and value to each entry you want it to apply to:
In Sun directories prior to DSEE 6, you’d use this:
Because this is a system attribute, some LDAP editors (like Apache Directory Studio) will not be able to add it. Use the command line ldapmodify utility instead.
You can search for all entries that have a password policy assignment with the following:
ldapsearch -x -h localhost -D "cn=directory manager" -W -b "dc=example,dc=com" -s sub "(pwdPolicySubentry=*)" pwdPolicySubentry
(note you’d need to substitute “passwordPolicySubentry” when querying a pre-DSEE 6 directory server)
This will return the dn of each entry with a password policy, as well as the dn of the password policy assigned to each. Again, as this is a system attribute you need to explicitly ask for it when performing a search.
That’s all easy enough, but could get tedious once you get up over a few entries.
Another way to do this is by employing CoS (Class of Service) and filtered roles to apply the policy to a class of entries. An important caveat to using CoS for something like this is that it always involves a performance penalty that can become significant depending on the number of affected entries. As a result I’ve decided to avoid using it in my own implementations, and to instead rely on batch update processes whose impact on the system can be controlled more closely.