Public/Target/Get-TargetDataAD.ps1
|
<#
.SYNOPSIS Retrieve current Active Directory users, groups, and OUs as the AD target snapshot. .DESCRIPTION Pulls every AD user with a rich property set (UPN, EmployeeID, MemberOf, extensionAttribute1-5, etc.), all groups (excluding AD.groupsExcluded name patterns), and all organizational units. Resolves each user's MemberOf into a CurrentGroups name list, detects duplicate EmployeeIDs, and builds a LookupByID hashtable keyed by EmployeeID (excluding duplicates) for fast source-to-target matching. Throws if AD returns no users, groups, or OUs. .OUTPUTS [pscustomobject] @{ Users; Groups; OrgUnits; DuplicateUsers; LookupByID }. .EXAMPLE $adData = Get-TargetDataAD .NOTES Created by: Sam Cattanach Modified: 2026-06-26 #> function Get-TargetDataAD { [CmdletBinding()] param () #User Properties to load $userPropertyAD = @( "UserPrincipalName" "Title" "Surname" "SamAccountName" "physicalDeliveryOfficeName" "Name" "GivenName" "employeeType" "EmployeeID" "EmployeeNumber" "DisplayName" "DistinguishedName" "Company" "Department" "CN" "CanonicalName" "MemberOf" "objectGUID" "Description" "OfficePhone" "EmailAddress" "PasswordNeverExpires" "extensionAttribute1" "extensionAttribute2" "extensionAttribute3" "extensionAttribute4" "extensionAttribute5" ) Write-Log -Message "AD: Starting Target Data Retrieval" -Level Info #Get all Users from AD try { Write-Log -Message "AD: Fetching Users" -Level Trace $ADUsers = Get-ADUser -Filter * -Properties $userPropertyAD if ($ADUsers) { Write-Log -Message "AD: Successfully fetched Users" -Level Trace } else { Throw "AD: Connected to AD but no users fetched" } } catch { Write-Log -Message "AD: No users fetched" -Level Error Throw $_ } #Get all Groups from AD try { Write-Log -Message "AD: Fetching Groups" -Level Trace $ADGroups = Get-ADGroup -Filter * -Properties DistinguishedName | Select-Object Name, DistinguishedName if ($ADGroups) { Write-Log -Message "AD: Successfully fetched Groups" -Level Trace } else { Throw "AD: Connected to AD but no groups fetched" } } catch { Write-Log -Message "AD: No groups fetched" -Level Error Throw $_ } #Remove excluded groups (AD.groupsExcluded - wildcard patterns matched against the group name). #Excluded groups become invisible to ALL group processing: no adds, no removes, no deactivate strips. $IDConfig = Get-IDBridgeConfig foreach ($pattern in $IDConfig.AD.groupsExcluded) { $excludedGroups = @($ADGroups | Where-Object {$_.Name -like $pattern}) if ($excludedGroups.Count -gt 0) { Write-Log -Message "AD: Excluding $($excludedGroups.Count) group(s) matching '$pattern' from group processing: $($excludedGroups.Name -join ', ')" -Level Trace $ADGroups = $ADGroups | Where-Object {$_.Name -notlike $pattern} } } # Build a hashtable mapping DistinguishedName -> Group Name to avoid repeated Get-ADGroup calls $groupDnToName = @{} foreach ($item in $ADGroups) { if ($item.DistinguishedName) { $groupDnToName[$item.DistinguishedName] = $item.Name } } #Add the groups to the users foreach ($user in $ADUsers) { #Add groups if they exist if ($user.MemberOf) { foreach ($item in $user.MemberOf) { if ($groupDnToName.ContainsKey($item)) { $user.CurrentGroups += $groupDnToName[$item] } } } else { $user.CurrentGroups = $null } } #Get all OUs from AD try { Write-Log -Message "AD: Fetching Org Units" -Level Trace $ADOrgUnits = Get-ADOrganizationalUnit -LDAPFilter '(name=*)' | Select-Object -ExpandProperty DistinguishedName if ($ADOrgUnits) { Write-Log -Message "AD: Successfully fetched Org Units" -Level Trace } else { Throw "AD: Connected to AD but no org units fetched" } } catch { Write-Log -Message "AD: No org units fetched" -Level Error Throw $_ } #Get AD users with duplicate employeeID $duplicateADUsers = ($ADUsers.where{$_.employeeID} | Select-Object -Property UserPrincipalName, employeeID | Group-Object -Property employeeID | Where-Object { $_.Count -gt 1 } ).group if ($duplicateADUsers) { Write-Log -Message ("AD: Users found with Duplicate External IDs: " + ($duplicateADUsers | ConvertTo-Json -Compress)) } # Build the lookup tables once to make the search faster $adUsersLookupByID = @{} foreach ($adUser in $ADUsers) { if ($adUser.EmployeeID -and ($adUser.EmployeeID -notin $duplicateADUsers.employeeID)) { $adUsersLookupByID[$adUser.EmployeeID] = $adUser } } Write-Log -Message "AD: Finished Target Data Retrieval" -Level Info #Return a single object with all data return [PSCustomObject]@{ Users = $ADUsers Groups = $ADGroups.Name OrgUnits = $ADOrgUnits DuplicateUsers = $duplicateADUsers LookupByID = $adUsersLookupByID } } |