Conditional Access Policy Impact Analysis
Professional Summary
This script analyzes Microsoft Entra ID Conditional Access policies and produces an impact assessment report before policy modifications are implemented. It identifies enabled policies, targeted users and groups, included applications, grant controls, session controls, and potential administrative lockout risks.
The report helps administrators validate Conditional Access changes, understand policy scope, and reduce the likelihood of tenant-wide authentication disruptions during security hardening initiatives.
Why it matters
Conditional Access is one of the most critical security controls in Microsoft 365. A misconfigured policy can unintentionally block administrators, service accounts, executives, remote users, or entire business units from accessing Microsoft 365 services.
Before enabling, modifying, or consolidating policies, organizations should perform an impact assessment to understand:
- Which users and groups are affected
- Which cloud applications are targeted
- Whether emergency access accounts are excluded
- Potential administrator lockout scenarios
- Overlapping or conflicting policy assignments
Benefits
- Prevents accidental administrator lockouts
- Identifies high-risk policy configurations
- Improves Conditional Access governance
- Supports CAB and change review processes
- Accelerates security assessments
- Creates an exportable report for documentation and auditing
- Scales efficiently across large Microsoft 365 tenants
Usage
- Register an Azure AD App
- Assign Exchange.ManageAsApp application permissions
- Upload a certificate and note:
- Client ID
- Tenant ID
- Certificate Thumbprint
- Run the script from a secure automation host
- Review or export the $Report object
Import-Module Microsoft.Graph.Identity.SignIns
$ReportPath = ".\ConditionalAccessImpactAnalysis.csv"
Connect-MgGraph -Scopes `
"Policy.Read.All",
"Directory.Read.All",
"Group.Read.All"
$policies = Get-MgIdentityConditionalAccessPolicy -All
$directoryRoles = Get-MgDirectoryRole -All
$adminGroupIds = @()
foreach ($role in $directoryRoles) {
$members = Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id -All -ErrorAction SilentlyContinue
foreach ($member in $members) {
if ($member.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.group') {
$adminGroupIds += $member.Id
}
}
}
$results = foreach ($policy in $policies) {
$conditions = $policy.Conditions
$users = $conditions.Users
$includedUsers = ($users.IncludeUsers -join '; ')
$excludedUsers = ($users.ExcludeUsers -join '; ')
$includedGroups = ($users.IncludeGroups -join '; ')
$excludedGroups = ($users.ExcludeGroups -join '; ')
$targetsAdmins = $false
if ($users.IncludeUsers -contains "All") {
$targetsAdmins = $true
}
if ($users.IncludeGroups) {
foreach ($groupId in $users.IncludeGroups) {
if ($groupId -in $adminGroupIds) {
$targetsAdmins = $true
break
}
}
}
$emergencyAccessExcluded = $false
if (
$users.ExcludeUsers.Count -gt 0 -or
$users.ExcludeGroups.Count -gt 0
) {
$emergencyAccessExcluded = $true
}
$applications = if ($conditions.Applications.IncludeApplications) {
$conditions.Applications.IncludeApplications -join '; '
}
else {
"Not Specified"
}
$grantControls = if ($policy.GrantControls.BuiltInControls) {
$policy.GrantControls.BuiltInControls -join '; '
}
else {
"None"
}
$sessionControls = @()
if ($policy.SessionControls.SignInFrequency) {
$sessionControls += "SignInFrequency"
}
if ($policy.SessionControls.PersistentBrowser) {
$sessionControls += "PersistentBrowser"
}
if ($policy.SessionControls.ApplicationEnforcedRestrictions) {
$sessionControls += "ApplicationRestrictions"
}
if ($policy.SessionControls.CloudAppSecurity) {
$sessionControls += "CloudAppSecurity"
}
[PSCustomObject]@{
PolicyName = $policy.DisplayName
State = $policy.State
IncludedUsers = $includedUsers
ExcludedUsers = $excludedUsers
IncludedGroups = $includedGroups
ExcludedGroups = $excludedGroups
Applications = $applications
GrantControls = $grantControls
SessionControls = ($sessionControls -join '; ')
TargetsAdministrators = $targetsAdmins
EmergencyAccessExcluded = $emergencyAccessExcluded
CreatedDateTime = $policy.CreatedDateTime
ModifiedDateTime = $policy.ModifiedDateTime
}
}
$results |
Sort-Object PolicyName |
Export-Csv -Path $ReportPath -NoTypeInformation -Encoding UTF8
Write-Host ""
Write-Host "Conditional Access Impact Analysis Complete" -ForegroundColor Green
Write-Host "Report: $ReportPath"
Write-Host "Policies Analyzed: $($results.Count)"
Required Microsoft Graph permissions:
- Policy.Read.All
- Directory.Read.All
- Group.Read.All
Output
CSV report containing:
| Column | Description |
|---|---|
| PolicyName | Conditional Access policy name |
| State | Enabled, Disabled, Report-Only |
| IncludedUsers | Targeted users |
| ExcludedUsers | Excluded users |
| IncludedGroups | Targeted groups |
| ExcludedGroups | Excluded groups |
| Applications | Targeted cloud applications |
| GrantControls | MFA, Compliant Device, Hybrid Join, etc. |
| SessionControls | Session restrictions configured |
| TargetsAdministrators | Indicates potential admin impact |
| EmergencyAccessExcluded | Indicates whether exclusions exist |
| CreatedDateTime | Policy creation date |
| ModifiedDateTime | Last modification date |
Notes
- Designed for Microsoft Entra ID Conditional Access.
- Uses Microsoft Graph PowerShell SDK.
- Suitable for pre-change reviews, CAB approvals, security audits, and governance assessments.
- Review emergency access account exclusions before enabling any policy targeting all users or privileged administrators.
- Consider scheduling periodic exports to establish a historical baseline of Conditional Access configurations.
Contributors
| Author(s) |
|---|
| Josiah Opiyo |
Built with a focus on automation, governance, least privilege, and clean Microsoft 365 tenants-helping M365 admins gain visibility and reduce operational risk.
Version history
| Version | Date | Comments |
|---|---|---|
| 1.0 | June 02, 2026 | Initial release |
Disclaimer
THESE SAMPLES ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.