Last active
May 29, 2024 02:48
-
-
Save kosuka-EMS/b9b6c9cb7a5bbe6d740477da70c03dcc to your computer and use it in GitHub Desktop.
This script retrieves sign-in logs from Entra ID that were blocked in report-only mode using the Get-MgAuditLogSignIn cmdlet from the Microsoft Graph PowerShell SDK. It outputs the logs into CSV files, grouped by conditional access policy names.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Move to the directory for CSV output (replace the path as needed) | |
cd C:\work | |
# Connect to Microsoft Graph | |
### Sign in using a global administrator account | |
### The consent page for accessing Entra ID will be displayed | |
Connect-MgGraph -Scope "AuditLog.Read.All", "Directory.Read.All", "Policy.Read.All" | |
# Get the date and time for the past 24 hours | |
$last24Hours = (Get-Date).AddHours(-24).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") | |
# Retrieve sign-in logs (within the past 24 hours) | |
### By default, the Graph API returns a maximum of 1,000 records, but specifying -All:$true retrieves all records | |
### Be aware that using -All:$true might consume significant memory depending on the number of records in your organization | |
### Consider replacing -All:$true with -Top 1000 as an alternative approach | |
$signInLogs = Get-MgAuditLogSignIn -All:$true -Filter "createdDateTime ge $last24Hours" | |
# Extract entries with "reportOnlyFailure" | |
### This process is designed to output only the records judged as failed in report-only mode to a CSV file | |
$filteredLogs = $signInLogs | Where-Object { | |
$_.appliedConditionalAccessPolicies -ne $null -and | |
$_.appliedConditionalAccessPolicies.result -eq "reportOnlyFailure" | |
} | |
# Separate logs by policy and output to CSV | |
$policyGroups = $filteredLogs | Group-Object -Property { $_.appliedConditionalAccessPolicies.displayName } | |
foreach ($policyGroup in $policyGroups) { | |
$policyName = $policyGroup.Name | |
$sanitizedPolicyName = $policyName -replace '[\\\/:*?"<>|]', '' | |
$logFileName = "./{0}_filteredLogs.csv" -f $sanitizedPolicyName.Replace(' ', '_') | |
# Append logs for each policy | |
$policyGroup.Group | Export-Csv -Path $logFileName -NoTypeInformation -Append | |
} | |
# Retrieve next page data as long as the next page link exists | |
### Even with -All:$true or -Top N specified, more than 1,000 records could be retrieved, making this unnecessary | |
### Still included to adhere to Graph API's standard behavior | |
while ($signInLogs.'@odata.nextLink') { | |
$signInLogs = Get-MgAuditLogSignIn -All:$true -Filter "createdDateTime ge $last24Hours" -NextLink $signInLogs.'@odata.nextLink' | |
$filteredLogs = $signInLogs | Where-Object { | |
$_.appliedConditionalAccessPolicies -ne $null -and | |
$_.appliedConditionalAccessPolicies.result -eq "reportOnlyFailure" | |
} | |
# Separate logs by policy and output to CSV | |
$policyGroups = $filteredLogs | Group-Object -Property { $_.appliedConditionalAccessPolicies.displayName } | |
foreach ($policyGroup in $policyGroups) { | |
$policyName = $policyGroup.Name | |
$sanitizedPolicyName = $policyName -replace '[\\\/:*?"<>|]', '' | |
$logFileName = "./{0}_filteredLogs.csv" -f $sanitizedPolicyName.Replace(' ', '_') | |
# Append logs for each policy | |
$policyGroup.Group | Export-Csv -Path $logFileName -NoTypeInformation -Append | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment