Managing Manual and Automatic Lifecycle State (LCS) Updates in Identity Data Aggregation

Problem Statement
In identity management within ISC systems, a significant challenge arises when manually set Lifecycle States (LCS) need to be reverted to automatically calculated states during subsequent data aggregations. Despite various attempts using methods such as optimized and unoptimized aggregation, modifying direct identity attributes, identity-profile refresh and creating workflows, the problem persists. The goal is to synchronize the manually set state with the calculated state and revert to automatic updates while maintaining the accuracy and integrity of identity information.

Key Insight
When a lifecycle state is manually set, the automated calculation is overridden until the calculated state matches the manual state. This ensures that immediate manual interventions, such as terminations, are respected until the corresponding data from the HR system catches up.

Scenario
Consider a scenario where you have a flat file with identity data. For example,

  • Emp_No – 1000
  • First_Name – Henry
  • Last_Name – Lucas
  • Email_Address – [email protected]
  • Status – A
  • Start_Date – 05/01/2024
  • End_Date – Null

This data is aggregated, and the LCS is calculated and displayed in Identity Details on ISC. However, some identities have manually set Lifecycle States. During subsequent aggregations, the transform should recalculate the LCS and update it automatically. Let’s explore how to handle this process.

Pre-Requisites
Before diving into the process, ensure you have the following in place:

  1. An Authoritative Source must be created.
  2. An Identity Profile should be created and mapped with the Authoritative Source.
  3. Enable the Provisioning Settings in Provisioning Tab on the Identity Profile.
  4. Postman setup with v3, beta API’s and should be connected with SailPoint ISC tenant.

LCS Calculation Transform
Let’s say, there are three cloudLifecycleSates namely – prehire, active and terminated.
The condition for identities which lies under these states are,

  • prehire – status should be ‘A’ and start_Date should be greater than the present_Date
  • active - start_Date should be lesser than the present_Date and (end_Date should be null or greater than the present_Date)
  • terminated - end_Date should be not_null and lesser than the present_Date
{
    "name": "Sample_LCS",
    "type": "static",
    "attributes": {
        "status": {
            "attributes": {
                "sourceName": "Source_Name",
                "attributeName": "Status"
            },
            "type": "accountAttribute"
        },
        "StartDate_Compare": {
            "attributes": {
                "firstDate": {
                    "attributes": {
                        "inputFormat": "dd/MM/yyyy",
                        "outputFormat": "ISO8601",
                        "input": {
                            "attributes": {
                                "sourceName": "Source_Name",
                                "attributeName": "Start_Date"
                            },
                            "type": "accountAttribute"
                        }
                    },
                    "type": "dateFormat"
                },
                "secondDate": {
                    "attributes": {
                        "inputFormat": "yyyy-MM-dd'T'HH:mm'Z'",
                        "outputFormat": "ISO8601",
                        "input": {
                            "attributes": {
                                "expression": "now/d"
                            },
                            "type": "dateMath"
                        }
                    },
                    "type": "dateFormat"
                },
                "operator": "gt",
                "positiveCondition": "greater",
                "negativeCondition": "lesser"
            },
            "type": "dateCompare"
        },
        "endDate_compare": {
            "attributes": {
                "firstDate": {
                    "attributes": {
                        "input": {
                            "attributes": {
                                "values": [
                                    {
                                        "attributes": {
                                            "sourceName": "Source_Name",
                                            "attributeName": "End_Date"
                                        },
                                        "type": "accountAttribute"
                                    },
                                    "30/12/5000"
                                ]
                            },
                            "type": "firstValid"
                        },
                        "inputFormat": "dd/MM/yyyy",
                        "outputFormat": "ISO8601"
                    },
                    "type": "dateFormat"
                },
                "secondDate": {
                    "attributes": {
                        "inputFormat": "yyyy-MM-dd'T'HH:mm'Z'",
                        "outputFormat": "ISO8601",
                        "input": {
                            "attributes": {
                                "expression": "now/d"
                            },
                            "type": "dateMath"
                        }
                    },
                    "type": "dateFormat"
                },
                "operator": "gte",
                "positiveCondition": "greater",
                "negativeCondition": "lesser"
            },
            "type": "dateCompare"
        },
        "value": "#if($status=='A' && $StartDate_Compare=='greater')prehire#elseif($StartDate_Compare=='lesser' && $endDate_compare=='greater')active#{else}terminated#end",
        "requiresPeriodicRefresh": "true"
    }
}

Practical Examples for Scenario

Here, I have listed the three solutions by which we can obtain the goal. They are –

  • Using Set Lifecycle State API endpoint – using this endpoint, force update the manually set LCS to automatic.
  • Using Conditional or Apache Velocity transform – Get the list of identities which are manually set and in the present LCS calculation create a condition to match the manual state and do an identity-profile refresh. By this process, you can update the manually set LCS to automatic.
  • Modifying HR Data – Get the HR data and change it accordingly to the condition of the manually set LCS and aggregate it. After this revert the LCS to automatic state.

Initial Process

  1. Initial Aggregation:
  • Attributes: Emp_No – 1000, First_Name – Henry, Last_Name – Lucas, Email_Address – [email protected], Status – A, Start_Date – 05/01/2024, End_Date – Null

  • Calculated LCS: “active”

  1. Manual Override:
  • Manual LCS Change: “terminated (Manual)”

Solution 1 - Using Set Lifecycle State API endpoint

After the initial process,

  1. Open v3 API, under Lifecycle States, Set Lifecycle State API endpoint will be located.
    https://sailpoint.api.identitynow.com/v3/identities/:identity-id/set-lifecycle-state

  2. In Params, provide the ID of the identity in place of :identity-id (You can get the identity-id in UI directly else using “get identities” api.

  1. In Body, provide the lifecycleStateId. This ID can be got using Lists LifecycleStates API endpoint.

  1. By this way, you can change revert the Identity’s LCS.

Solution 2 - Using Conditional or Apache Velocity transform

After the Initial Process done,

  1. Modify the existing Transform (Here, I have used velocity transform):
  • First, get the manually terminated identities and check for the unique attribute. It may be the identities id, email, username or any.
  • Once you get the identity’s unique attribute, fetch that attribute in the transform as shown below (I have used email - identity attribute).
  • After this, you specify in the JSON that if any identity attribute has this specific value in a particular attribute, it should be changed back to the previous state (in this case, it’s active).
{
    "name": "Sample_LCS",
    "type": "static",
    "attributes": {
        "status": {
            "attributes": {
                "sourceName": "Source_Name",
                "attributeName": "Status"
            },
            "type": "accountAttribute"
        },
        "email": {
            "attributes": {
                "name": "email"
            },
            "type": "identityAttribute"
        },
	 …,
 "value":"#if($email=='[email protected]')active#elseif($status=='A' && $StartDate_Compare=='greater')prehire#elseif($StartDate_Compare=='lesser' && $endDate_compare=='greater')active#{else}terminated#end",
        "requiresPeriodicRefresh": "true"
    }
}
  1. Trigger – Identity Process using API:
  • You can trigger the identity Refresh process by two ways.
    a. Directly via UI (specifically for individual identities)
    b. Using API (will trigger process for all identities under IP)

  • Directly via UI

  • Via API

  • Result - LCS reverts to “active” after the final aggregation.

  1. Modify the Transform:
  • Just, modify the value attribute
"value": "#if($status=='A' && $StartDate_Compare=='greater')prehire#elseif($StartDate_Compare=='lesser' && $endDate_compare=='greater')active#{else}terminated#end"

Solution 3 - Modifying HR Data

After the Initial process is done,

  1. Subsequent Aggregation:
  • Updating the HR data to match the LCS state active, I am updating the Start_Date – 07/01/2024 instead of 05/01/2024.

  • Result: LCS remains “terminated (Manual)” due to the manual override.

  1. Synchronizing States:
  • Update the HR data to match the manually set state:
     Attributes: Emp_No – 1000, First_Name – Henry, Last_Name – Lucas, Email_Address – [email protected], Status – A, Start_Date – 05/01/2024, End_Date – 30/06/2024

  • Calculated LCS: “terminated”

  1. Reverting to Automatic State:
  • Once the HR data reflects the “inactive” state, revert the data back:
     Attributes: Emp_No – 1000, First_Name – Henry, Last_Name – Lucas, Email_Address – [email protected], Status – A, Start_Date – 05/01/2024, End_Date – Null

  1. Final Aggregation:
  • Result: LCS reverts to “active” after the final aggregation.

10 Likes