Rules/ID-007.no-service-accounts-privileged.psd1
|
@{ Id = 'ID-007' Title = 'No service accounts hold privileged directory roles' Area = 'RoleAssignments' Severity = 'High' References = @( 'https://learn.microsoft.com/entra/identity/role-based-access-control/best-practices' ) Rationale = 'Service accounts (MDM bindings, sync, backup, automation) with admin roles combine standing privilege with credentials that live in configs and never see an interactive MFA prompt.' Remediation = 'Remove the admin role from the flagged accounts; most integrations need it only during setup. Use app registrations with least-privilege application permissions or scoped roles instead.' Test = { param($Snapshot) $privilegedRoles = @( 'Global Administrator', 'Privileged Role Administrator', 'Security Administrator', 'User Administrator', 'Exchange Administrator', 'SharePoint Administrator', 'Intune Administrator', 'Application Administrator', 'Cloud Application Administrator', 'Conditional Access Administrator' ) $serviceNamePattern = '(?i)(svc|service|automation|mdm|sync|backup|daemon|scanner|noreply|robot)' $hits = @($Snapshot.RoleAssignments.assignments | Where-Object { ($privilegedRoles -contains [string]$_._tlRoleName) -and ( ([string]$_._tlPrincipalName -match $serviceNamePattern) -or ([string]$_._tlPrincipalUpn -match $serviceNamePattern) ) }) if ($hits.Count -gt 0) { New-TLRuleResult -Status Fail -Evidence @($hits | ForEach-Object { "{0} ({1}) holds {2} - looks like a service account" -f $_._tlPrincipalName, $_._tlPrincipalUpn, $_._tlRoleName }) } else { New-TLRuleResult -Status Pass -Evidence 'No privileged role assignment matches common service-account naming patterns.' } } } |