Search code examples
coldfusionlucee

How can I evaluate Active Directory lastlogondatetimestamp in Lucee 5.x?


Looking for some help with Active Directory datetime format, specifically the attribute lastlogondatetimestamp.

According to google, The LastLogonTimeStamp attribute of the Active Directory stores the last logon timestamp value in the System.Int64 data type format. This timestamp is the number of 100-nanoseconds intervals since Jan 1, 1601, UTC.

How can I convert/evaluate this so that I can see if the lastlogondatetimestamp is more than 90 days? I'm not displaying the data anywhere, simply need to take action if the result is more than 90 days old to purge old user accounts from my application.

I tried this:

startDate = createdatetime( '1601','01','01','00','00','00' ); dateConvert( "utc2Local", dateadd( 's', arguments.lastlogondatetimestamp, startDate ) ); but my result ends up as:

{ts '124795117-01-18 18:00:18'} which tells me I did something incorrectly.

I also tried startDate = createdatetime( '1601','01','01','00','00','00' ); datetimeNow = dateConvert( "local2Utc", now() ); but when I dump datediff( 's', startdate, datetimeNow ); I am not clear on what to do with the value returned.

UPDATE I've since learned the dateconvert is not available in Lucee 5.


Solution

  • Here is how I ended up working this out using Windows time service (w32tm.exe).

    1. query db to obtain users in application
    2. loop over results
      1. query ldap and return the LastLogonTimestamp
      2. pass LastLogonTimestamp to a the helper function (see further down) which returns a string of text including a datetime string that can be evaluated.
      3. parse the timestamp returned from results (listlast on the hyphen worked for me)
        • it'll look something like: 567890 20:14:47.6024208 - 9/1/2022 3:14:47 PM
      4. get the date difference between now() and the timestamp
        • if the results are gte somevalue, take further action
        • if the results are lte somevalue, no action needed

    My use case, I'm only looking up about a 1k users and it's done after hours via a scheduled task.

    I also don't have to deal with leap years, rounding errors, etc.; all I need to do is compare two dates.

    Helper function (which is what really what answers this question):

    function w32tm(timestampcode){
        fileWrite( "\foldername\w32tm.cmd", "c:\windows\system32\w32tm.exe /ntte #arguments.timestampcode# > #expandPath('\foldername\w32tm-results.txt')#" );
    
        cfexecute(
            name="C:\Windows\System32\cmd.exe"
            arguments="/C #expandPath('\foldername\w32tm.cmd')#"
            timeout="#settings.timeout#"
            terminateOnTimeout="true"
        );
        
        local.rtn.w32tm_response = fileRead("#expandPath('\foldername\w32tm-results.txt')#", "utf-8");
    
        return local.rtn.w32tm_response;
    }