Audit Newly Created Conditional Access Policies Using Graph PowerShell

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:

  • When was the policy created?
  • Who created it?

The Script: Query “Add policy” Events in Azure AD

# 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
}
                                

How the Script Works

  1. Graph Authentication
    • The script starts by connecting to Microsoft Graph using the Connect-MgGraph cmdlet and requests the AuditLog.Read.All permission to access audit log data.
  2. Time Range Definition
    • You can define how far back the report should go by modifying the $daysToLookBack variable (e.g., 7, 14, or 30 days).
  3. OData Filtering
  4. The $filter targets audit entries with:

    • category eq 'Policy'
    • activityDisplayName eq 'Add policy'
    • activityDateTime within the defined range
  5. Output Formatting
  6. The script collects key properties:

    • Added Time – When the policy was created
    • Added Policy – Display name of the Conditional Access policy
    • Added By (Admin UPN) – Who created it
    • Result Status – Success or failure of the operation

    The results are formatted neatly using Format-Table.


Further Enhancements

  • Export to CSV
  • Export the report to a file:

    $output | Export-Csv -Path "CA-Policy-Creation-Audit.csv" -NoTypeInformation

  • Filter by Admin
  • Focus on specific admins:

    $output | Where-Object { $_."Added By (Admin UPN)" -like "*securityadmin*" }

  • Include Additional Fields
  • You can expand the script to include more details like id, correlationId, or the full audit JSON if needed.

  • Scheduled Reporting Automate this script weekly via Task Scheduler or Azure Automation for continuous compliance.

Possible Errors & Solutions

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

Use Cases

  • Security Audits: Confirm all newly created CA policies were authorized and documented.
  • Change Management: Track changes as part of IT governance practices.
  • Onboarding Review: Ensure security admins follow proper review protocols during rollout.
  • Delegation Monitoring: Check if junior admins or delegated groups are creating policies beyond their scope.

Conclusion

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.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex