tests/Test-Assessment.61009.ps1
|
<#
.SYNOPSIS Conditional Access policies cover both agent identities and agent users. .DESCRIPTION This test checks whether at least one enabled Conditional Access policy targets agent identities and at least one enabled Conditional Access policy targets agent users, both with the 'block' grant control. Both conditions must hold for the check to pass. .NOTES Test ID: 61009 Workshop Task: AI_003 Pillar: AI Category: AI Identity & Access Risk Level: High Supported Clouds: Global Required Permission: Policy.Read.All or Policy.Read.ConditionalAccess #> function Test-Assessment-61009 { [ZtTest( Category = 'AI Identity & Access', ImplementationCost = 'Low', MinimumLicense = ('AAD_PREMIUM', 'AGENT_365'), CompatibleLicense = ('AAD_PREMIUM&AGENT_365', 'AAD_PREMIUM_P2&AGENT_365'), Pillar = 'AI', Service = ('Graph'), RiskLevel = 'High', SfiPillar = 'Protect identities and secrets', TenantType = ('Workforce'), TestId = 61009, Title = 'Conditional Access policies cover both agent identities and agent users', UserImpact = 'Low' )] [CmdletBinding()] param() #region Data Collection Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose $activity = 'Checking Conditional Access coverage for agent identities and agent users' Write-ZtProgress -Activity $activity -Status 'Querying Conditional Access policies' $queryError = $null try { $allCAPolicies = Get-ZtConditionalAccessPolicy -ErrorAction Stop } catch { $queryError = $_ Write-PSFMessage "Failed to retrieve Conditional Access policies: $_" -Tag Test -Level Warning } #endregion Data Collection #region Assessment Logic $passed = $false $testResultMarkdown = '' $agentIdentityPolicies = @() $agentUserPolicies = @() $agentIdentityBlockPolicies = @() $agentUserBlockPolicies = @() if ($queryError) { $testResultMarkdown = "❌ Unable to determine Conditional Access policy configuration for agent principals due to a query failure or insufficient permissions.`n`n**Error:** ``$queryError```n`n%TestResult%" } else { # Policies targeting agent identities via clientApplications (includeAgentIdServicePrincipals or agentIdServicePrincipalFilter.rule). $agentIdentityPolicies = @($allCAPolicies | Where-Object { $null -ne $_.conditions.clientApplications -and ( ($null -ne $_.conditions.clientApplications.includeAgentIdServicePrincipals -and $_.conditions.clientApplications.includeAgentIdServicePrincipals.Count -gt 0) -or (-not [string]::IsNullOrEmpty($_.conditions.clientApplications.agentIdServicePrincipalFilter.rule)) ) }) # Policies targeting agent users via the reserved token conditions.users.includeUsers = ["AllAgentIdUsers"]. $agentUserPolicies = @($allCAPolicies | Where-Object { $null -ne $_.conditions.users.includeUsers -and $_.conditions.users.includeUsers -contains 'AllAgentIdUsers' }) # Enabled agent-identity policies that apply the 'block' grant control $agentIdentityBlockPolicies = @($agentIdentityPolicies | Where-Object { $_.state -eq 'enabled' -and $_.grantControls.builtInControls -contains 'block' }) # Enabled agent-user policies that apply the 'block' grant control $agentUserBlockPolicies = @($agentUserPolicies | Where-Object { $_.state -eq 'enabled' -and $_.grantControls.builtInControls -contains 'block' }) $passed = ($agentIdentityBlockPolicies.Count -ge 1) -and ($agentUserBlockPolicies.Count -ge 1) if ($passed) { $testResultMarkdown = "✅ At least one enabled Conditional Access policy blocks agent identities, and at least one enabled Conditional Access policy blocks agent users.`n`n%TestResult%" } else { $testResultMarkdown = "❌ No enabled Conditional Access policy targets agent identities with the ``block`` control, OR no enabled Conditional Access policy targets agent users with the ``block`` control. Agent traffic for the uncovered principal type bypasses Conditional Access enforcement.`n`n%TestResult%" } } #endregion Assessment Logic #region Report Generation $mdInfo = '' $reportTitle = 'Conditional Access policies covering agent principals' $portalLink = 'https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/ConditionalAccessBlade/~/Policies' $portalPolicyBaseUrl = 'https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/PolicyBlade/policyId/' $formatTemplate = @' ### [{0}]({1}) | Policy | Targeted Agent Identity types | State | Grant controls | Status | | :----- | :---------------------------- | :---- | :------------- | :----- | {2} '@ $agentPolicies = @() if (-not $queryError) { foreach ($policy in ($agentIdentityPolicies | Sort-Object displayName)) { $clientApps = $policy.conditions.clientApplications $targetedType = if ($null -ne $clientApps -and $clientApps.includeAgentIdServicePrincipals -contains 'All' -and ($null -eq $clientApps.excludeAgentIdServicePrincipals -or $clientApps.excludeAgentIdServicePrincipals.Count -eq 0)) { 'All Agent Identities' } else { 'Some Agent Identities or Blueprints' } $agentPolicies += [PSCustomObject]@{ Policy = $policy TargetedType = $targetedType IsBlocking = ($agentIdentityBlockPolicies | Where-Object { $_.id -eq $policy.id }).Count -gt 0 } } foreach ($policy in ($agentUserPolicies | Sort-Object displayName)) { $agentPolicies += [PSCustomObject]@{ Policy = $policy TargetedType = 'All Agent Users' IsBlocking = ($agentUserBlockPolicies | Where-Object { $_.id -eq $policy.id }).Count -gt 0 } } } $tableRows = '' if ($agentPolicies.Count -gt 0) { foreach ($entry in $agentPolicies) { $pol = $entry.Policy $policyName = Get-SafeMarkdown -Text $pol.displayName $grants = if ($pol.grantControls -and $pol.grantControls.builtInControls) { $pol.grantControls.builtInControls -join ', ' } else { '(none)' } $status = if ($entry.IsBlocking) { '✅ Pass' } else { '❌ Fail' } $tableRows += "| [$policyName]($portalPolicyBaseUrl$($pol.id)) | $($entry.TargetedType) | $(Get-ZtCaPolicyState -State $pol.state) | $grants | $status |`n" } $mdInfo = $formatTemplate -f $reportTitle, $portalLink, $tableRows } $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo #endregion Report Generation $params = @{ TestId = '61009' Title = 'Conditional Access policies cover both agent identities and agent users' Status = $passed Result = $testResultMarkdown } Add-ZtTestResultDetail @params } |