Find Latest Date Transform


:spiral_notepad: Description This transform compares multiple dates to determine which is the latest.
:balance_scale: Legal Agreement By using this CoLabitem, you are agreeing to SailPoint’s Terms of Service for our developer community and open-source CoLab.
:hammer_and_wrench: Repository Link colab-transforms/transforms/find-latest-date/transform.json at 343bcea144c75eb7cd3e95c13550d780eab86a0c · sailpoint-oss/colab-transforms · GitHub
:open_book: New to Transforms in the CoLab? Read the getting started guide for Transforms in the CoLab.
:hospital: Supported by Community Developed

Overview

Use this transform to compare a list of dates to determine the latest date.

The following transform operations are used as well as the Apache velocity templating language to accomplish this task.

Requirements

  • Access to Identity Security Cloud

Guide

With this transform you will be able to determine the latest date from the dates given.

The whole transform is wrapped in a firstValid operation. This will ensure that our result will be our latest date or if something went wrong during processing the transform will return null.

The first item of the firstValid is where we setup and calculate the latest date using a couple different transform operations and the apache velocity templating language.

The first date adLastLogin is from an Active Directory source with the attribute name lastLogon. The transform pulls that value and converts it to the format yyMMddHH from it’s original epoch format. If there is an issue pulling that value, the transform will use the placeholder value of 125911584000000000 which equates to January 1, 2000 12:00:00am.

NOTE:

  • All dates should have the same fallback value.
  • The placeholder value used in the static operation needs to be adjusted for the inputFormat used so that the dateFormat operation can properly read and convert the date.
 "adLastLogon": {
        "type": "dateFormat",
        "attributes": {
            "input": {
                "type": "firstValid",
                "attributes": {
                    "values": [
                        {
                            "type": "accountAttribute",
                            "attributes": {
                                "attributeName": "lastLogon",
                                "sourceName": "Active Directory"
                            }
                        },
                        {
                            "attributes": {
                                "value": "125911584000000000"
                            },
                            "type": "static"
                        }
                    ]
                }
            },
            "inputFormat": "EPOCH_TIME_WIN32",
            "outputFormat": "yyMMddHH"
        }
    }

Repeat this step until you have all of the dates you wish to compare. Make sure that you replace the attributeName and sourceName for each date.

  • The inputFormat of your date can be any supported format.
  • The outputFormat must always be yyMMddHH.

We must parse the dates as integers in order for the comparisons to work.

NOTE:
Integers have a max value of 2147483647. The values returned by EPOCH_TIME_WIN32 and EPOCH_TIME_JAVA are both way beyond that. The transform needs something much, much smaller… but we can’t just create our own epoch time from a different year that we specify. This transform tries to find the last time an account was logged in so that an admin can determine whether it’s been inactive long enough to justify disabling it. In this example we use year-month-date-hour. A little bit of precision is lost here, but it’s good enough for this purpose. If you intend to implement similar logic, you will need to decide whether this level of precision is sufficient for your use case.

The main logic can be broken down as follows:

#set($max=-10) ## Instantiate a variable as an int; this will be our base for comparison as well as an int that will help us parse the dates as integers so we can compare them
#set($array = [$max.parseInt($adLastLogon),$max.parseInt($adLastLogonTimestamp),$max.parseInt($adPwdLastSet),$max.parseInt($adWhenCreated),$max.parseInt($azureLastInteractive),$max.parseInt($azureLastNonInteractive)]) ## Build an array of integers representing our dates
#foreach($val in $array) ## Iterate through the array
    #if($val > $max) ## Compare each value in the array against the current max value (which started at -10)
        #set($max = $val) ## If the current value is greater than the max, that value becomes the new max
    #end
#end
#if($max > 0) ## If the max value is greater than 0, return the max value
    $max
#end
4 Likes

Hello!

I can’t seem to get this transform to work in my environment. I consistently return null values despite keeping the transform very close to the same as what is in the github.

I have verified source names many times as well as the account schema. Also had a peer review this and we can’t figure out what’s missing unless the way these are processed changed somehow.

    "name": "LastActive",
    "type": "firstValid",
    "attributes": {
        "values": [
            {
                "type": "dateFormat",
                "attributes": {
                    "input": {
                        "type": "static",
                        "attributes": {
                            "adLastLogonTimestamp": {
                                "type": "dateFormat",
                                "attributes": {
                                    "input": {
                                        "type": "firstValid",
                                        "attributes": {
                                            "values": [
                                                {
                                                    "type": "accountAttribute",
                                                    "attributes": {
                                                        "attributeName": "lastLogonTimestamp",
                                                        "sourceName": "hcgg primary"
                                                    }
                                                },
                                                {
                                                    "attributes": {
                                                        "value": "125911584000000000"
                                                    },
                                                    "type": "static"
                                                }
                                            ]
                                        }
                                    },
                                    "inputFormat": "EPOCH_TIME_WIN32",
                                    "outputFormat": "yyMMddHH"
                                }
                            },
                            "adPwdLastSet": {
                                "type": "dateFormat",
                                "attributes": {
                                    "input": {
                                        "type": "firstValid",
                                        "attributes": {
                                            "values": [
                                                {
                                                    "type": "accountAttribute",
                                                    "attributes": {
                                                        "attributeName": "pwdLastSet",
                                                        "sourceName": "hcgg primary"
                                                    }
                                                },
                                                {
                                                    "attributes": {
                                                        "value": "125911584000000000"
                                                    },
                                                    "type": "static"
                                                }
                                            ]
                                        }
                                    },
                                    "inputFormat": "EPOCH_TIME_WIN32",
                                    "outputFormat": "yyMMddHH"
                                }
                            },
                            "adWhenCreated": {
                                "type": "dateFormat",
                                "attributes": {
                                    "input": {
                                        "type": "firstValid",
                                        "attributes": {
                                            "values": [
                                                {
                                                    "type": "accountAttribute",
                                                    "attributes": {
                                                        "attributeName": "whenCreated",
                                                        "sourceName": "hcgg primary"
                                                    }
                                                },
                                                {
                                                    "attributes": {
                                                        "value": "20000101010000.0Z"
                                                    },
                                                    "type": "static"
                                                }
                                            ]
                                        }
                                    },
                                    "inputFormat": "yyyyMMddHHmmss.S'Z'",
                                    "outputFormat": "yyMMddHH"
                                }
                            },
                            "azureLastInteractive": {
                                "type": "dateFormat",
                                "attributes": {
                                    "input": {
                                        "type": "firstValid",
                                        "attributes": {
                                            "values": [
                                                {
                                                    "type": "accountAttribute",
                                                    "attributes": {
                                                        "attributeName": "lastSignInDateTime",
                                                        "sourceName": "Azure AD Nonprod"
                                                    }
                                                },
                                                {
                                                    "attributes": {
                                                        "value": "2000-01-01T00:00:00Z"
                                                    },
                                                    "type": "static"
                                                }
                                            ]
                                        }
                                    },
                                    "inputFormat": "yyyy-MM-dd'T'HH:mm:ss'Z'",
                                    "outputFormat": "yyMMddHH"
                                }
                            }
                        },
                        "value": "#set($max=-10)#set($array=[$max.parseInt($adLastLogonTimestamp),$max.parseInt($adPwdLastSet),$max.parseInt($adWhenCreated),$max.parseInt($azureLastInteractive)])#foreach($val in $array)#if($val > $max)#set($max = $val)#end#end#if($max > 0)$max#end"
                    },
                    "inputFormat": "yyMMddHH",
                    "outputFormat": "ISO8601"
                }
            },
            null
        ]
    },
    "internal": false
}

Any help would be greatly appreciated!

try breaking each of those variables out into separate transforms and see if any of them are failing on their own. they should all be either 00010100 or an 8-digit string starting with 2.

the only way a null value should be returned is if there’s an error being thrown by the velocity script, though it could be the case that since we’re converting to integers, the value returned by the velocity would be 10100 instead of 00010100 which could potentially be breaking on the inputFormat of yyMMddHH since it wouldn’t have enough characters… but this would only be the case if the identities you’re looking at don’t have values for any of the listed attributes, so this isn’t likely to be the issue.

1 Like

This seemed to resolve the problem. Stepping through every section of the transform. Thank you!

1 Like