Skip to content

Instantly share code, notes, and snippets.

@kosuka-EMS
Last active May 29, 2024 02:48
Show Gist options
  • Save kosuka-EMS/b9b6c9cb7a5bbe6d740477da70c03dcc to your computer and use it in GitHub Desktop.
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.
# 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