tests/Test-Assessment.21941.ps1
<# .SYNOPSIS Checks if token protection policies are configured in Conditional Access. #> function Test-Assessment-21941{ [ZtTest( Category = 'Access control', ImplementationCost = 'Medium', Pillar = 'Identity', RiskLevel = 'Medium', SfiPillar = 'Protect identities and secrets', TenantType = ('Workforce','External'), TestId = 21941, Title = 'Token protection policies are configured', UserImpact = 'Low' )] [CmdletBinding()] param() Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose $activity = "Checking Token protection policies are configured" Write-ZtProgress -Activity $activity -Status "Getting Conditional Access policies" # Get all Conditional Access policies with Windows platform filtering $filter = "conditions/platforms/includePlatforms/any(p:p eq 'windows')" $allCAPolicies = Invoke-ZtGraphRequest -RelativeUri "identity/conditionalAccess/policies" -ApiVersion 'beta' -Filter $filter $policiesWithTokenProtection = $allCAPolicies | Where-Object { $_.sessionControls -and $_.sessionControls.secureSignInSession -and ($_.sessionControls.secureSignInSession.PSObject.Properties.Name -contains 'isEnabled') } # Required application IDs for token protection $requiredAppIds = @( "00000002-0000-0ff1-ce00-000000000000", # Office 365 Exchange Online "00000003-0000-0ff1-ce00-000000000000" # Microsoft Graph / SharePoint Online ) # Loop through each policy to validate token protection requirements $allPolicyDetails = @() $tokenProtectionPolicies = @() $enabledTokenProtectionPolicies = @() foreach ($policy in $policiesWithTokenProtection) { # Check if policy meets token protection criteria $meetsTokenProtectionCriteria = $true $failureReasons = @() # Validate 1: sessionControls.secureSignInSession.isEnabled is true $hasSecureSignInSession = $policy.sessionControls.secureSignInSession.isEnabled -eq $true if (-not $hasSecureSignInSession) { $meetsTokenProtectionCriteria = $false $failureReasons += "Secure sign-in session is not enabled" } # Validate 2: users.includeUsers has value $hasIncludeUsers = $policy.conditions.users.includeUsers -and ($policy.conditions.users.includeUsers -notcontains "None") -and ($policy.conditions.users.includeUsers.Count -gt 0) if (-not $hasIncludeUsers) { $meetsTokenProtectionCriteria = $false $failureReasons += "No users specified in includeUsers" } $includeUsersDisplay = if ($policy.conditions.users.includeUsers -contains "All") { "All" } elseif ($hasIncludeUsers) { "Selected" } else { "None" } # Validate 3: Applications include required app IDs or "All" $hasRequiredApps = $false $includeAppsDisplay = "None" if ($policy.conditions.applications.includeApplications -and $policy.conditions.applications.includeApplications.Count -gt 0 -and $policy.conditions.applications.includeApplications -notcontains "None") { if ($policy.conditions.applications.includeApplications -contains "All") { $hasRequiredApps = $true $includeAppsDisplay = "All" } else { $hasOfficeApp = $policy.conditions.applications.includeApplications -contains $requiredAppIds[0] $hasGraphApp = $policy.conditions.applications.includeApplications -contains $requiredAppIds[1] if ($hasOfficeApp -and $hasGraphApp) { $hasRequiredApps = $true $includeAppsDisplay = "Selected" } else { $includeAppsDisplay = "Other apps" } } } if (-not $hasRequiredApps) { $meetsTokenProtectionCriteria = $false $failureReasons += "Missing required applications (Office 365 Exchange Online and Microsoft Graph/SharePoint Online)" } $policyStatus = ($meetsTokenProtectionCriteria -eq $true) -and ($policy.state -eq 'enabled') # Create policy detail object $policyDetail = [PSCustomObject]@{ PolicyId = $policy.id DisplayName = $policy.displayName State = $policy.state IncludeUsers = $includeUsersDisplay IncludeApplications = $includeAppsDisplay TokenProtectionEnabled = $meetsTokenProtectionCriteria SecureSignInEnabled = $hasSecureSignInSession FailureReasons = $failureReasons Policy = $policy PolicyStatus = $policyStatus } $allPolicyDetails += $policyDetail if ($meetsTokenProtectionCriteria) { $tokenProtectionPolicies += $policy if ($policy.state -eq 'enabled') { $enabledTokenProtectionPolicies += $policy } } } # Determine test result - Pass if at least one policy has token protection enabled AND is in enabled state $passed = $enabledTokenProtectionPolicies.Count -gt 0 $portalTemplate = "https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/PolicyBlade/policyId/{0}" if ($passed) { $testResultMarkdown = "Token protection policies are configured.`n`n" } else { $testResultMarkdown = "Token protection policies are not configured.`n`n" } # Build detailed markdown information $mdInfo = "" if ($allCAPolicies.Count -eq 0) { $mdInfo += "No Conditional Access policies found targeting Windows platforms.`n`n" } elseif ($policiesWithTokenProtection.Count -eq 0) { $mdInfo += "No Conditional Access policies found with secure sign-in session controls.`n`n" } else { $mdInfo += "### Token protection policy summary`n`n" $mdInfo += "The table below lists all the token protection Conditional Access policies found in the tenant.`n`n" $mdInfo += "| Name | Policy state | Users | Applications | Token protection | Status |`n" $mdInfo += "| :--- | :---: | :---: | :---: | :---: | :---: |`n" # Sort policies: passing first, then by display name $sortedPolicyDetails = $allPolicyDetails | Sort-Object -Property @{ Expression = { -not $_.TokenProtectionEnabled } }, DisplayName foreach ($policyDetail in $sortedPolicyDetails) { $portalLink = $portalTemplate -f $policyDetail.PolicyId $policyName = "[$(Get-SafeMarkdown $policyDetail.DisplayName)]($portalLink)" $policyState = Get-ZtCaPolicyState -State $policyDetail.State $tokenProtectionStatus = Get-ZtPassFail -Condition $policyDetail.TokenProtectionEnabled -EmojiType 'Bubble' $status = Get-ZtPassFail -Condition $policyDetail.PolicyStatus -IncludeText $mdInfo += "| $policyName | $policyState | $($policyDetail.IncludeUsers) | $($policyDetail.IncludeApplications) | $tokenProtectionStatus | $status |`n" } } $testResultMarkdown += $mdInfo $params = @{ Status = $passed Result = $testResultMarkdown GraphObjectType = 'ConditionalAccess' GraphObjects = $tokenProtectionPolicies } Add-ZtTestResultDetail @params } |