Entra/Get-ConditionalAccessReport.ps1
|
<#
.SYNOPSIS Reports all Conditional Access policies in the Entra ID tenant. .DESCRIPTION Queries Microsoft Graph for every Conditional Access policy and produces a flattened report showing policy state, conditions, grant controls, and session controls. Essential for reviewing Zero Trust posture and identifying policy gaps during security assessments. Requires Microsoft.Graph.Identity.SignIns module and Policy.Read.All permission. .PARAMETER OutputPath Optional path to export results as CSV. If not specified, results are returned to the pipeline. .EXAMPLE PS> . .\Common\Connect-Service.ps1 PS> Connect-Service -Service Graph -Scopes 'Policy.Read.All' PS> .\Entra\Get-ConditionalAccessReport.ps1 Displays all Conditional Access policies with their configuration details. .EXAMPLE PS> .\Entra\Get-ConditionalAccessReport.ps1 -OutputPath '.\ca-policies.csv' Exports Conditional Access policy details to CSV. #> [CmdletBinding()] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$OutputPath ) $ErrorActionPreference = 'Stop' # Verify Graph connection if (-not (Assert-GraphConnection)) { return } # Ensure required Graph submodule is loaded (PS 7.x does not auto-import) Import-Module -Name Microsoft.Graph.Identity.SignIns -ErrorAction Stop # Retrieve all Conditional Access policies try { Write-Verbose "Retrieving Conditional Access policies..." $policies = Get-MgIdentityConditionalAccessPolicy -All } catch { Write-Error "Failed to retrieve Conditional Access policies: $_" return } $allPolicies = @($policies) Write-Verbose "Processing $($allPolicies.Count) Conditional Access policies..." if ($allPolicies.Count -eq 0) { Write-Verbose "No Conditional Access policies found" return } $report = foreach ($policy in $allPolicies) { # Flatten included users $includeUsers = if ($policy.Conditions.Users.IncludeUsers) { ($policy.Conditions.Users.IncludeUsers | Sort-Object) -join '; ' } else { '' } # Flatten excluded users $excludeUsers = if ($policy.Conditions.Users.ExcludeUsers) { ($policy.Conditions.Users.ExcludeUsers | Sort-Object) -join '; ' } else { '' } # Flatten included applications $includeApps = if ($policy.Conditions.Applications.IncludeApplications) { ($policy.Conditions.Applications.IncludeApplications | Sort-Object) -join '; ' } else { '' } # Flatten grant controls $grantControls = if ($policy.GrantControls.BuiltInControls) { $controlsList = @($policy.GrantControls.BuiltInControls) $operator = $policy.GrantControls.Operator if ($controlsList.Count -gt 1 -and $operator) { ($controlsList -join " $operator ") } else { $controlsList -join '; ' } } else { '' } # Flatten session controls $sessionControlsList = @() if ($policy.SessionControls.SignInFrequency.IsEnabled) { $freq = $policy.SessionControls.SignInFrequency $sessionControlsList += "SignInFrequency: $($freq.Value) $($freq.Type)" } if ($policy.SessionControls.PersistentBrowser.IsEnabled) { $sessionControlsList += "PersistentBrowser: $($policy.SessionControls.PersistentBrowser.Mode)" } if ($policy.SessionControls.CloudAppSecurity.IsEnabled) { $sessionControlsList += "CloudAppSecurity: $($policy.SessionControls.CloudAppSecurity.CloudAppSecurityType)" } if ($policy.SessionControls.ApplicationEnforcedRestrictions.IsEnabled) { $sessionControlsList += "AppEnforcedRestrictions" } $sessionControls = $sessionControlsList -join '; ' [PSCustomObject]@{ DisplayName = $policy.DisplayName State = $policy.State CreatedDateTime = $policy.CreatedDateTime ModifiedDateTime = $policy.ModifiedDateTime IncludeUsers = $includeUsers ExcludeUsers = $excludeUsers IncludeApplications = $includeApps GrantControls = $grantControls SessionControls = $sessionControls } } $report = @($report) | Sort-Object -Property DisplayName Write-Verbose "Found $($report.Count) Conditional Access policies" if ($OutputPath) { $report | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Output "Exported Conditional Access report ($($report.Count) policies) to $OutputPath" } else { Write-Output $report } |