Skip to content

Instantly share code, notes, and snippets.

@darrenjrobinson
Last active February 1, 2021 19:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrenjrobinson/f7677013a454ef933fa0d8b39ee204a7 to your computer and use it in GitHub Desktop.
Save darrenjrobinson/f7677013a454ef933fa0d8b39ee204a7 to your computer and use it in GitHub Desktop.
Workday PowerShell Management Agent with Delta Sync Support - Import Script for Microsoft Identity Manager. Associated Blog Post can be found here https://blog.darrenjrobinson.com/adding-delta-sync-support-to-the-microsoft-identity-manager-powershell-management-agent-for-workday-hr/
param (
$Username,
$Password,
$Credentials,
$OperationType,
[bool] $usepagedimport,
$pagesize
)
$DebugFilePath = "C:\PROGRA~1\MICROS~2\2010\SYNCHR~1\EXTENS~2\Workday\Debug\WDUsersImport.txt"
$WaterMarkFilePath = "C:\PROGRA~1\MICROS~2\2010\SYNCHR~1\EXTENS~2\Workday\DeltaWaterMark.txt"
if (!(Test-Path $DebugFilePath)) {
$DebugFile = New-Item -Path $DebugFilePath -ItemType File
}
else {
$DebugFile = Get-Item -Path $DebugFilePath
}
"Starting Import as : " + $OperationType + " - " + (Get-Date) | Out-File $DebugFile -Append
"Paged Import : " + $usepagedimport | Out-File $DebugFile -Append
"PageSize : " + $pagesize | Out-File $DebugFile -Append
# Workday Powershell Module
import-module -name "WorkdayAPI"
# Setup WorkdayAPI Module
$creds = New-Object System.Management.Automation.PSCredential ($Username, $Password)
Set-WorkdayCredential -Credential $creds
Set-WorkdayEndpoint -Endpoint Human_Resources -Uri 'https://SERVICE.workday.com/ccx/service/TENANT/Human_Resources/v30.2'
Save-WorkdayConfiguration
if (!$global:tenantObjects) {
# Directory and file for Differential Watermark File
# Read in Delta Cookie if it exists, if not create the file for storing the cookie
if (!(Test-Path $WaterMarkFilePath)) {
$cookie = New-Item -Path $WaterMarkFilePath -ItemType File
"Creating new WaterMark Delta File" | Out-File $DebugFile -Append
}
else {
$cookie = Get-Item -Path $WaterMarkFilePath
"WaterMark Delta File present" | Out-File $DebugFile -Append
}
# Delta or Full Sync based on Run Type and WaterMark File ?
if ((Get-Item $cookie).length -gt 0kb -and $OperationType -eq "Delta") {
# Delta WaterMark value exists. Get it
$waterMark = Get-Content $cookie.FullName
$waterMark | Out-File $DebugFile -Append
# *********************** DELTA IMPORT **********************************
# Get Workday Users
$datenow = Get-date
$now = $datenow.AddMinutes(-1).ToString('o')
$WDayRecordsBase = Get-WorkdayWorkerAdv -WorkerType WID -FromDate $waterMark -ToDate $now
if ($WDayRecordsBase.Count -gt 0) {
# store the WaterMark in a file for next time we run the MA
$now | Out-File $cookie
}
"Retrieved Base Workday Records for $($WDayRecordsBase.Count) Users" | Out-File $DebugFile -Append
# ***************************************************************
"Delta Import" | Out-File $DebugFile -Append
}
else {
# no WaterMark Cookie, so first run OR Full Sync so return everything
# *********************** FULL IMPORT **********************************
# Get Workday Users
$now = $datenow.AddMinutes(-1).ToString('o')
$WDayRecordsBase = Get-WorkdayWorkerAdv -WorkerType WID
if ($WDayRecordsBase.Count -gt 0) {
# store the WaterMark in a file for next time we run the MA
$now | Out-File $cookie
}
"Retrieved Base Workday Records for $($WDayRecordsBase.Count) Users" | Out-File $DebugFile -Append
# ***************************************************************
"Full Import" | Out-File $DebugFile -Append
}
# Counter to know where we are up to processing the Import
# Starting at minus 1 as our first object is 0 and I'm incrementing at the start of the loop.
[int]$global:objectsImported = -1
# An Array for the retuned objects to go into
$global:tenantObjects = @()
# Add in our first objects
$global:tenantObjects += $WDayRecordsBase
# Set last object ID
$global:lastsourceObjectID = "randomstringthatwillnevermatchaGUIDforthefirstiteration"
}
# ********************* Process users into the MA *******************
[int]$objectpagecount = 0
foreach ($global:user in $global:tenantObjects) {
$global:user = $global:tenantObjects[$global:objectsImported + 1]
if (!$global:user -or ($global:objectsImported + 1 -eq $global:tenantObjects.count)) {
# nothing left to process
$global:MoreToImport = $false
break
}
if ($global:user.WorkerWid) {
# Get Full Record
$userRecord = $null
$userRecord = Get-WorkdayWorkerAdv -WorkerType WID $global:user.WorkerWid -IncludeWork -IncludePersonal
if ($userRecord) {
$obj = @{}
$obj.Add("WorkerWid", $userRecord.WorkerWid)
$obj.Add("objectClass", "WDUser")
$obj.Add("BusinessTitle", $userRecord.BusinessTitle)
$obj.Add("FirstName", $userRecord.FirstName)
$obj.Add("JobProfileName", $userRecord.JobProfileName)
$obj.Add("LastName", $userRecord.LastName)
$obj.Add("Location", $userRecord.Location)
$obj.Add("PreferredName", $userRecord.PreferredName)
$obj.Add("UserId", $userRecord.UserId)
$obj.Add("WorkerDescriptor", $userRecord.WorkerDescriptor)
$obj.Add("WorkerId", $userRecord.WorkerId)
$obj.Add("WorkerType", $userRecord.WorkerType)
$obj.Add("WorkerTypeReference", $userRecord.WorkerTypeReference)
$obj.Add("WorkSpace", $userRecord.WorkSpace)
$obj.Add("HireDate", $userRecord.HireDate)
$obj.Add("StartDate", $userRecord.StartDate)
$obj.Add("EndDate", $userRecord.EndDate)
if($userRecord.Active = 1){ $obj.Add("WorkdayActive", $true)}else{ $obj.Add("WorkdayActive", $false)}
$obj.Add("Supplier", $userRecord.Supplier)
"UserObjectID: " + $userRecord.WorkerId | Out-File $DebugFile -Append
# Pass the User Object to the MA
$obj
$objectpagecount++
$global:objectsImported++
"Paged Import User count: " + $objectpagecount | Out-File $DebugFile -Append
"Objects Imported count: " + $global:objectsImported | Out-File $DebugFile -Append
"Objects Remaining count: " + ($global:tenantObjects.count - $global:objectsImported - 1) | Out-File $DebugFile -Append
}
if ($objectpagecount -eq $pagesize) {
$global:MoreToImport = $true
"More to Import: " + $objectpagecount | Out-File $DebugFile -Append
break
}
}
}
# ***********************************************************
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment