public/xspm/Test-MtXspmAppRegWithPrivilegedUnusedPermissions.ps1
|
<# .SYNOPSIS Tests if app registration have assigned privileged API permissions which are unused. .DESCRIPTION This function checks all Entra ID app registrations with privileged API permissions and checks if any of them are unused. .OUTPUTS [bool] - Returns $true if no owners on app registrations with privileged API permissions, $false if any owners have been assigned, $null if skipped or prerequisites not met. .EXAMPLE Test-MtXspmAppRegWithPrivilegedUnusedPermissions .LINK https://maester.dev/docs/commands/Test-MtXspmAppRegWithPrivilegedUnusedPermissions #> function Test-MtXspmAppRegWithPrivilegedUnusedPermissions { [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'This test checks for multiple permissions.')] [OutputType([bool])] param() $UnifiedIdentityInfoExecutable = Get-MtXspmUnifiedIdentityInfo -ValidateRequiredTablesOnly if ( $UnifiedIdentityInfoExecutable -eq $false) { Add-MtTestResultDetail -SkippedBecause 'Custom' -SkippedCustomReason 'This test requires availability of MDA App Governance and MDI to get data for Defender XDR Advanced Hunting tables. Check https://maester.dev/docs/tests/MT.1079/#Prerequisites for more information.' return $null } try { Write-Verbose "Get details from UnifiedIdentityInfo ..." $UnifiedIdentityInfo = Get-MtXspmUnifiedIdentityInfo } catch { Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ return $null } $Severity = "Medium" $HighPrivilegedAppsByApiPermissions = $UnifiedIdentityInfo | where-object {$_.ApiPermissions.Classification -eq "ControlPlane" -or $_.ApiPermissions.Classification -eq "ManagementPlane" -or $_.ApiPermissions.PrivilegeLevel -eq "High" } $SensitiveAppsWithUnusedPermissions = $HighPrivilegedAppsByApiPermissions | Where-Object { $_.ApiPermissions.InUse -eq $false } if ($return -or [string]::IsNullOrEmpty($SensitiveAppsWithUnusedPermissions)) { $testResultMarkdown = "Well done. No application and workload identity has a privileged API permission which are unused" } else { $testResultMarkdown = "At least one application has unused sensitive API permissions.`n`n%TestResult%" $result = "| ApplicationName | Enterprise Access Level | Sensitive App Role | API Provider |`n" $result += "| --- | --- | --- | --- | `n" Write-Verbose "Found $($SensitiveAppsWithUnusedPermissions.Count) app registrations with unused sensitive API permissions." foreach ($SensitiveApp in $SensitiveAppsWithUnusedPermissions) { $filteredApiPermissions = $SensitiveApp.ApiPermissions | Where-Object { ($_.Classification -eq "ControlPlane" -or $_.Classification -eq "ManagementPlane" -or $_.PrivilegeLevel -eq "High") -and $_.InUse -eq $false } | Select-Object AppDisplayName, AppRoleDisplayName, Classification | sort-object Classification, AppDisplayName if($filteredApiPermissions) { foreach ($filteredApiPermission in $filteredApiPermissions) { if ($filteredApiPermission.Classification -eq "") { $filteredApiPermission.Classification = "Unknown" } $ServicePrincipalLink = "[$($SensitiveApp.AccountDisplayName)](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/ManagedAppMenuBlade/~/Overview/objectId/$($SensitiveApp.AccountObjectId)/appId/$($SensitiveApp.AppId))" $AdminTierLevelIcon = Get-MtXspmPrivilegedClassificationIcon -AdminTierLevelName $SensitiveApp.Classification $result += "| $($AdminTierLevelIcon) $($ServicePrincipalLink) | $($filteredApiPermission.Classification) | $($filteredApiPermission.AppRoleDisplayName) | $($filteredApiPermission.AppDisplayName) |`n" } } } $testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $result } Add-MtTestResultDetail -Result $testResultMarkdown -Severity $Severity $result = [string]::IsNullOrEmpty($SensitiveAppsWithUnusedPermissions) return $result } |