Workflow and using value generated by rule expression with script

Hi,

I am currently attempting to write a workflow that would dynamically update the AD attribute "accountExpires" for all users provisioned via our HRIS system.

My idea was to use a workflow to search for any user with an expiring account within 15 days or less. For all found accounts, I would update the "accountExpires" attribute with a date 1-year in the future of whatever the current date is of the accountExpires attribute.

So, if the current date of the "accountExpires" attribute is 05/07/2023, then we would update the value to /05/07/2024.

Within the workflow, I am using a "Search for objects" following by a "Change object properties > Target Properties > Property: "accountExpires" > "Value generated by rule expression".

The problem I am running into is I don't know how to reference the found object. I have tried the following method:

    $user = (Get-QADUser -Identity ($workflow.FoundObject("Search for objects").get("distinguishedName"))).UserPrincipalName

This generated the follow error:

DEBUG:     ! CALL function 'GenerateAccountExpiration'
DEBUG:    5+      >>>> $user = (Get-QADUser -Identity ($workflow.FoundObject("Search for objects").get("distinguishedName"))).UserPrincipalName

  Call '$Workflow.FoundObject'
ERROR: 
At line: 5 char:5. You cannot call a method on a null-valued expression.

Here is the code within the script I am running:

 function GenerateAccountExpiration ()
 {
 
    $user = (Get-QADUser -Identity ($workflow.FoundObject("Search for objects").get("distinguishedName"))).UserPrincipalName

    $Integer8 = ((Get-ADUser -Filter { userPrincipalName -eq $user } -Properties accountExpires).accountExpires)
    $newExpiryDate = ([datetime]::FromFileTimeUTC($Integer8)).AddDays(365)
 
    $newExpiryDate
    
 }
 

I know this script can probably be more efficient, I am just trying to work on a POC at the moment Slight smile

Is it not possible to reference the $workflow.FoundObject values from within a "Change object properties" script?

Thank you!

P.S. Does anyone know how to post screenshots? I saw someone else ask this and they said you can just paste the screenshot in. When I try that the space I am pasting into just gets deleted. Do you have to post screenshots on an external source first?

Parents
  • This is the code sample for this functionality from the Active Roles SDK:

    Function SavedDisplayName($Request)
    {
        return $workflow.SavedObjectProperties("Save Object Properties 1").get("displayName") 
    }

    Notice that you have to pass the $Request object into your custom function in order to get access to the constructed variables.

    You missed that in your function. Try and add $Request into your GenerateAccountExpiration declaration and see if that helps.

Reply
  • This is the code sample for this functionality from the Active Roles SDK:

    Function SavedDisplayName($Request)
    {
        return $workflow.SavedObjectProperties("Save Object Properties 1").get("displayName") 
    }

    Notice that you have to pass the $Request object into your custom function in order to get access to the constructed variables.

    You missed that in your function. Try and add $Request into your GenerateAccountExpiration declaration and see if that helps.

Children
  • Thank you, Terrance.

    I tested out the snippet of code above, it still generates an error, but it is slightly different:

     Call method '$Request.Get'
         Arguments list:
             [1] : Value=distinguishedName : Type=System.String
    DEBUG:    5+      >>>> Write-Output "GUID $Request.GUID" | Out-File -Append C:\Temp\GenerateAccountExpiry.txt
    
    DEBUG:    9+      >>>> $user = return $workflow.SavedObjectProperties("Save object properties").get("UserPrincipalName")
    
    DEBUG:    9+     $user = return  >>>> $workflow.SavedObjectProperties("Save object properties").get("UserPrincipalName")
    
      Call '$Workflow.SavedObjectProperties'
    ERROR: 
    At line: 9 char:20. Exception calling "SavedObjectProperties" with "1" argument(s): "The given key was not present in the dictionary."

    Not sure if I am interpreting the error properly, but it would seem to indicate that $Request doesn't contain the "$workflow.SavedObjectProperties" values.

    I also tried outputting $Request.GUID to see if this would give me the GUID of the user who is currently going through the workflow, but the GUID is blank.

    Just curious if this could have anything to do with the age of our ARS. We are currently running version 7.4.3 (which we are planning to upgrade next week). Maybe this is working in a newer version.

  • These new errors are good - they mean that the $Workflow object now exists and is accessible inside your function.

    "The given key was not present in the dictionary." tells me that either the name of the "Save object properties" activity is incorrect, or that the userPrincipalName attribute isn't in it.

    Don't forget that you can export the entire object to a file in order to see what it contains:

    $Request | Select * | Out-File C:\temp\request.txt

    $Workflow | Select * | Out-File C:\temp\workflow.txt

    If you see something that interests you, export that to a file using a dot-reference and/or select with -expandProperty

    You can also use Get-Member to dig into the methods of these constructed objects, as well as Get-Variable to find things that you didn't know were there.

    There absolutely were some issues with Active Roles 7.4.3 related to instantiating the $Workflow object correctly... I'm not sure if you are experiencing something like that in this scenario, but examining your Out-Files should confirm if the expected properties and methods exist.

  • Thank you for correcting my interpretation of the error message. I will need to remember for that for next. I have been reading that error message entirely.

    I was also curious about how to properly dump the contents of $Request and $Workflow. I will give this a try and see what I can figure out.

    Will provide an update.

    As a side note, I did get it working with a PowerShell script. But it would be cool if I could get it working the way I originally wanted to do it.

  • In an Update Properties Activity, you can select "Workflow Date and Time" as the value to apply to an attribute and further choose "Use the current date and time plus this number of days".  By using an Activity you don't need to worry about how you reference the object because the Search Activity will pass the object to the Update Properties Activity.  Would this be an acceptable solution for your use case?


  • Hi Johnny,

    I thought about doing it this way.

    In the workflow "Search for objects" actions I am looking for any account expiring in the "Next 15 days". This is to cover a situation where the ARS is down for maintenance or whatever.

    With the 15-day advance, it means that the user accounts expiry will continue to drift each year. Does this really matter, likely it doesn't. But in the event I get asked, I want to ensure I can have the account renew each year at the same time.

    Hopefully I explained the properly.

  • A way to maybe get this working the way you originally wanted to is to use a global variable, declared within the Workflow's Options and Start Conditions -> Initialization Script.

    Declare a global variable here such as: $global:NewExpirationDate. I feel you might need to make sure this gets declared/cast properly. The accountExpires appears as an Integer8 attribute.

    Then, within the Search activity, the first step would be a Script step, which can directly access the found user, calculate the new expiration date and save it to the global variable: $global:NewExpirationDate = $newexpirationdate.

    Then, within the Update activity, the script here would simply return the value of the global variable: return $global:NewExpirationDate which would be mapped to the accountExpires attribute.

    Search the Active Roles Admin Guide for the term '$global:' for a little more information. According to the Admin Guide, you might not need to use $global: when initially declaring the varibale, but I've not encountered issues when doing so.

  • Yep - I get it.  So if I understand this right, this Workflow Found Objects call you are making is not returning the DN of the "current" found user?

  • I tried exporting the contents of $Request and $Workflow.

    $Request had information in it, but there wasn't anything that I could find that represented the user object I was trying to interact with.

    $Workflow was empty entirely. I tried outputting the value of $Workflow in another workflow that I know is working and exported $Workflow from there and saw that there is data outputted. So, it would seem that $Workflow isn't getting initialized properly.

    I learned a lot from doing this though and it will be helpful in the future no doubt.

  • This is an interesting solution. I have never worked with the $global variable. I think I understand how it works. I need to find some examples where it is used to fully understand how I can take advantage of it in the future.

    After considering this solution and the solution I currently have working, I have decided that I am satisfied with just using a PowerShell to set the 'accountExpires' attribute. I also started to suspect I might run into issues setting the attribute because it is a an Integer8 value. Set-QADUser has a specific switch called 'AccountExpires'. This switch accepts a standard date. It seems without this; you might need to convert your date back to an Integer8 value (which should be easy but is an extra step).

    My final solution is to create a workflow that does a search for upcoming expiring accounts and then it executes the following script:

     function GenerateAccountExpiration ()
     {
     
        # Get user details returned by the search function of the workflow. We then pull the UserPrincipalName
        $user = (Get-QADUser -Identity ($workflow.FoundObject("Search for objects").get("distinguishedName"))).UserPrincipalName
    
        # Get the existing accountExpires value and convert it from Integer8 to date
        $Integer8 = ((Get-ADUser -Filter { userPrincipalName -eq $user } -Properties accountExpires).accountExpires)
        $newExpiryDate = ([datetime]::FromFileTimeUTC($Integer8)).AddDays(365)
          
        # Set the new account expiry date
        Set-QADUser -Identity $user -AccountExpires $newExpiryDate -Proxy
        
     }

    Not sure if it as elegant as it can be, but it does get the job done.

    Really appreciate Richard's and Johnny's feedback.

  • I wouldn't expect there to be anything in $Request actually because you are using an Automation Workflow (aren't you?) which is, in effect its own "Request".

    From an AR workflows point of view, $Request will contain the "payload" of the transaction that triggered a Change workflow (for example, user modify, user create) . 

    Automation Workflows are triggered manually or by a schedule so there is no external $Request.  The closest thing you will find to a $Request in the context of an Automation Workflow is the Search Results but even then, this is just a list of objects.