Best Practices from Oracle Development's A‑Team

Last Login Tracking in Oracle Unified Directory

Earlier I posted about the performance impact of last login tracking in Oracle Internet Directory (OID). I was asked, do the same performance concerns apply to Oracle Unified Directory (OUD)?

Well, OUD also supports last login tracking, and enabling it will have some performance impact. However, OUD does last login tracking in a smarter way than OID does, so the performance impact of enabling it for OUD is potentially substantially less.

OID stores the last login time to the nearest second. Which means if a single account binds once per a second, then every second OID will perform a modify operation to update the orcllastlogintime. Potentially this can be a substantial extra modify load on storage and on replication.

OUD by contrast allows you to configure the granularity at which the last login time is stored. You can set it to second granularity to get the same behaviour as OID. Alternatively, you can set it to daily granularity; in which case, no matter how many times in the same day a single user logs in, only the first login for that day will be recorded. Although it depends on your exact requirements, you may well find that daily granularity is all you need from a security/auditing viewpoint, and thus you can take advantage of the substantial performance benefits it offers.

The granularity is implemented by enabling you to specify a custom date/time format for storing the last login attribute. So, for example, you can use yyyyMddHHmmSS'z' to get the same format which OID uses. Or you could use yyyyMMdd to only record the year, month and day, and exclude the time of day. To make it easier to read, you could add dashes such as yyyy-MM-dd. The syntax to use is that of the java.text.SimpleDateFormat class, which is documented here: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Just like OID does, OUD supports having different password policies for different sets of users, so last login tracking can be turned on for some but not others. To enable last login tracking for a password policy, you need to set the last-login-time-attribute property to the name of the attribute in which you wish to store the last login time. We can do this through either ODSM, or through the command line. In this post, I’m going to focus on the command-line approach. So, this is how to check if it is turned on for a given password policy:

$ dsconfig -h localhost -p 4444 -D "cn=oudadmin" -j pwdfile -X \
-n get-password-policy-prop --policy-name "Default Password Policy"
Property                                 : Value(s)
account-status-notification-handler       : -
allow-expired-password-changes            : false
allow-user-password-changes               : true
default-password-storage-scheme           : Salted SHA-512
deprecated-password-storage-scheme        : -
expire-passwords-without-warning          : false
force-change-on-add                       : false
force-change-on-reset                     : false
grace-login-count                         : 0
idle-lockout-interval                     : 0 s
last-login-time-attribute                 : -
last-login-time-format                    : -
lockout-duration                          : 0 s
lockout-failure-count                     : 10
lockout-failure-expiration-interval       : 0 s
lockout-soft-duration                     : 0 s
lockout-soft-failure-count                : 0
max-password-age                          : 0 s
max-password-reset-age                    : 0 s
min-password-age                          : 0 s
password-attribute                        : userpassword
password-change-requires-current-password : false
password-expiration-warning-interval      : 5 d
password-generator                        : Random Password Generator
password-history-count                    : 0
password-history-duration                 : 0 s
password-validator                        : -
previous-last-login-time-format           : -
require-change-by-time                    : -
require-secure-authentication             : false
require-secure-password-changes           : false

You can see how, in the default configuration last-login-time-attribute is not set, so last login time tracking is disabled.

(Note: pwdfile is the path to a file containing the admin password. This is more secure than providing the password on the command line using the -w option, in which case someone running “ps” at the same time may see the command line including the password.)

So, let’s enable last login tracking in OUD. While OID has an out-of-the-box attribute to store the last login time - orcllastlogintime - for OUD we need to define a custom attribute in which to store it. So let’s start by creating a custom LDAP attribute (customLastLogin) and an object class to contain it (customUser).

We’ll create an LDIF file to contain our schema additions, and load it using ldapmodify. This is lastLogin.ldif:

dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( customLastLogin-oid
NAME 'customLastLogin'
DESC 'Contains last login time'
X-ORIGIN 'Custom'
USAGE userApplications )
add: objectClasses
objectClasses: ( customUser-oid
NAME 'customUser'
DESC 'Custom user'
SUP inetOrgPerson
MAY customLastLogin
X-ORIGIN 'Custom' )

Next we’ll load that LDIF file into our OUD:

$ ldapmodify -h localhost -p 1389 -D "cn=oudadmin" -j pwdfile -f lastlogin.ldif
Processing MODIFY request for cn=schema
MODIFY operation successful for DN cn=schema

OK, now let’s create a new password policy and tell it to store the last login time in the attribute we just created:

$ dsconfig -h localhost -p 4444 -D "cn=oudadmin" -j pwdfile -X -n \
create-password-policy \
--policy-name "Test Password Policy" \
--set password-attribute:userPassword \
--set default-password-storage-scheme:"Salted SHA-1" \
--set lockout-duration:300s --set lockout-failure-count:3 \
--set password-change-requires-current-password:true \
--set last-login-time-attribute:customLastLogin \
--set last-login-time-format:yyyy-MM-dd

Let’s create a container in which to store our test users, in testUsers.ldif:

dn: ou=testUsers,dc=example,dc=com
objectClass: organizationalUnit
ou: testUsers

And we’ll load that LDIF file

$ ldapmodify -h localhost -p 1389 -D "cn=oudadmin" -j ~/pwdfile -a -f ~/testUsers.ldif

Finally, let’s create a user:

dn: cn=testUser1,ou=testUsers,dc=example,dc=com
objectclass: customUser
sn: testUser1
givenName: testUser1
userPassword: welcome1

Load the LDIF file in the same way as before.

Now we’ll assign the “Test Password Policy” to the testUsers container. Let’s do that using a collective attribute:

dn: cn=testUsers password policy,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: collectiveAttributeSubentry
objectClass: extensibleObject
cn: testUsers password policy
ds-pwp-password-policy-dn;collective:cn=Test Password Policy,cn=Password Policies,cn=config
subtreeSpecification: {base "ou=testUsers", minimum 1}
collectiveConflictBehavior: real-overrides-virtual

Let’s check the user confirm the attribute set

$ ldapsearch -h localhost -p 1389 -D "cn=oudadmin" -j ~/pwdfile -b "cn=testuser1,ou=testusers,dc=example,dc=com" -s base '(objectclass=*)' ds-pwp-password-policy-dn
dn: cn=testUser1,ou=testUsers,dc=example,dc=com
ds-pwp-password-policy-dn: cn=Test Password Policy,cn=Password Policies,cn=config

Yes we see the ds-pwp-password-policy-dn set. So let’s try logging in as the user,:

$ ldapsearch -h localhost -p 1389 -D "cn=testuser1,ou=testusers,dc=example,dc=com" -w welcome1 -b "" -s base '(objectclass=*)'
objectClass: ds-root-dse
objectClass: top

And check to see if customLastLogin gets populated:

$ ldapsearch -h localhost -p 1389 -D "cn=oudadmin" -j ~/pwdfile -b "cn=testuser1,ou=testusers,dc=example,dc=com" -s base '(objectclass=*)' customLastLogin
dn: cn=testUser1,ou=testUsers,dc=example,dc=com
customLastLogin: 2014-10-26

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha