Conditional Access (CA) policies are a foundational security control in Microsoft 365. They allow organizations to enforce access rules based on identity, device compliance, location, and risk. However, untracked or unauthorized creation of CA policies can introduce unintended security consequences.
Fortunately, Azure AD logs all Conditional Access policy creation activities under the “Policy” category with an event labeled “Add policy.”
This article walks you through a Graph PowerShell script that fetches all newly added Conditional Access policies over a defined time window and helps you answer two key questions:
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "AuditLog.Read.All"
# Set how many days to look back (change as needed)
$daysToLookBack = 14
$startTime = (Get-Date).AddDays(-$daysToLookBack).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
# Build OData filter to target "Add policy" event under "Policy" category
$filter = "category eq 'Policy' and activityDisplayName eq 'Add policy' and activityDateTime ge $startTime"
# Fetch the audit logs
$logs = Get-MgAuditLogDirectoryAudit -Filter $filter -All
# Parse and output the results
$output = foreach ($log in $logs) {
$policyName = ($log.targetResources | Select-Object -First 1).displayName
$adminUser = $log.initiatedBy.user.userPrincipalName
[PSCustomObject]@{
"Added Time" = $log.activityDateTime
"Added Policy" = $policyName
"Added By (Admin UPN)" = $adminUser
"Result Status" = $log.result
}
}
# Display the results
if ($output) {
$output | Format-Table -AutoSize
} else {
Write-Host "No 'Add policy' events found in the last $daysToLookBack days." -ForegroundColor Yellow
}
The $filter targets audit entries with:
The script collects key properties:
The results are formatted neatly using Format-Table.
Export the report to a file:
$output | Export-Csv -Path "CA-Policy-Creation-Audit.csv" -NoTypeInformation
Focus on specific admins:
$output | Where-Object { $_."Added By (Admin UPN)" -like "*securityadmin*" }
You can expand the script to include more details like id, correlationId, or the full audit JSON if needed.
Error Message | Cause | Solution |
Invalid filter clause | DateTime not in correct format | Ensure the $startTime is in "yyyy-MM-ddTHH:mm:ssZ" (UTC ISO 8601) format |
Access denied | Insufficient permissions | Use AuditLog.Read.All and ensure the account has proper admin roles |
No parameter found | Using unsupported cmdlet options | Avoid -Property, -ConsistencyLevel, or -AdditionalHeaders with Get-MgAuditLogDirectoryAudit |
Conditional Access policies are powerful — and potentially risky — if misconfigured or created without oversight. This Graph PowerShell script helps you track all new policy creations in real time and hold administrators accountable for changes that affect organizational access and compliance.
With just a few lines of code, you gain full visibility into policy creation events across your tenant, ensuring a more secure and transparent environment.
© m365corner.com. All Rights Reserved. Design by HTML Codex