Private/Get-TLSyncAccountUpn.ps1
|
function Get-TLSyncAccountUpn { <# .SYNOPSIS Returns the UPNs of non-interactive directory-synchronization accounts. .DESCRIPTION Entra Connect / cloud sync service accounts hold the "Directory Synchronization Accounts" role, which Microsoft reports flag as an admin - but they never perform interactive MFA and cannot. Rules that judge human admins (MFA registration) exclude them via this helper so a Critical finding is not inflated by accounts that are non-actionable by design. Uses role assignments when available (precise) and falls back to the well-known sync-account UPN patterns. Returns a case-insensitive HashSet of UPNs. #> [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Snapshot ) $set = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) $syncRoles = @('Directory Synchronization Accounts', 'On Premises Directory Sync Account') $upnPattern = '(?i)^(sync_[^@]+|adtoaadsyncserviceaccount|on-premises directory synchronization service account)' # Precise: any principal holding a directory-sync role. if ($Snapshot.PSObject.Properties['RoleAssignments'] -and $Snapshot.RoleAssignments -and $Snapshot.RoleAssignments.PSObject.Properties['assignments']) { foreach ($assignment in @($Snapshot.RoleAssignments.assignments)) { if (($syncRoles -contains [string]$assignment._tlRoleName) -and $assignment._tlPrincipalUpn) { [void]$set.Add([string]$assignment._tlPrincipalUpn) } } } # Fallback: UPN pattern across the user-bearing areas (works without roles). foreach ($areaName in @('MfaRegistration', 'StaleAccounts')) { if ($Snapshot.PSObject.Properties[$areaName] -and $Snapshot.$areaName -and $Snapshot.$areaName.PSObject.Properties['users']) { foreach ($user in @($Snapshot.$areaName.users)) { if ([string]$user.userPrincipalName -match $upnPattern) { [void]$set.Add([string]$user.userPrincipalName) } } } } return , $set } |