-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update Get-HawkUserMailBoxAuditing to migrate from deprecated Search-…
…AuditLog and to use Search-UnifiedAuditLog
- Loading branch information
1 parent
0fe454e
commit 44b9aeb
Showing
1 changed file
with
151 additions
and
87 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,110 +2,174 @@ | |
<# | ||
.SYNOPSIS | ||
Gathers Mailbox Audit data if enabled for the user. | ||
.DESCRIPTION | ||
Check if mailbox auditing is enabled for the user. | ||
If it is pulls the mailbox audit logs from the time period specified for the investigation. | ||
Retrieves mailbox audit logs from Microsoft 365 Unified Audit Log, focusing on mailbox | ||
content access and operations. This function replaces the deprecated Search-MailboxAuditLog | ||
cmdlet with modern UAL-based auditing. | ||
Migration Changes: | ||
- Old: Used Search-MailboxAuditLog for direct mailbox audit log access | ||
- New: Uses Search-UnifiedAuditLog with separate collection of: | ||
* ExchangeItem records (item-level operations) | ||
* ExchangeItemGroup records (access patterns) | ||
The new implementation provides: | ||
- Improved visibility into mailbox item access patterns | ||
- More consistent data collection across Exchange Online | ||
- Automatic pagination for large result sets | ||
- Integration with Microsoft 365 compliance center | ||
- Separated output files for better data analysis | ||
Note: Administrative actions on mailboxes (like granting permissions) are tracked by | ||
Get-HawkUserAdminAudit instead of this function. | ||
Will pull from the Unified Audit Log and the Mailbox Audit Log | ||
.PARAMETER UserPrincipalName | ||
Single UPN of a user, commans seperated list of UPNs, or array of objects that contain UPNs. | ||
.OUTPUTS | ||
Single UPN of a user, comma-separated list of UPNs, or array of objects that contain UPNs. | ||
File: Exchange_UAL_Audit.csv | ||
.OUTPUTS | ||
ExchangeItem Records: | ||
File: ExchangeItem_Simple_{User}.csv/.json | ||
Path: \<User> | ||
Description: All Exchange related audit events found in the Unified Audit Log. | ||
Description: Flattened item-level operations data in CSV and JSON formats | ||
File: Exchange_Mailbox_Audit.csv | ||
File: ExchangeItem_Logs_{User}.csv/.json | ||
Path: \<User> | ||
Description: All Exchange related audit events found in the Mailbox Audit Log. | ||
.EXAMPLE | ||
Get-HawkUserMailboxAuditing -UserPrincipalName [email protected] | ||
Search for all Mailbox Audit logs from [email protected] | ||
.EXAMPLE | ||
Get-HawkUserMailboxAuditing -UserPrincipalName (get-mailbox -Filter {Customattribute1 -eq "C-level"}) | ||
Search for all Mailbox Audit logs for all users who have "C-Level" set in CustomAttribute1 | ||
#> | ||
|
||
param | ||
( | ||
[Parameter(Mandatory = $true)] | ||
[array]$UserPrincipalName | ||
) | ||
|
||
Function Get-MailboxAuditLogsFiveDaysAtATime { | ||
param( | ||
[Parameter(Mandatory = $true)] | ||
[datetime]$StartDate, | ||
[Parameter(Mandatory = $true)] | ||
[datetime]$EndDate, | ||
[Parameter(Mandatory = $true)] | ||
$User | ||
) | ||
|
||
|
||
# Setup the initial start date | ||
[datetime]$RangeStart = $StartDate | ||
|
||
do { | ||
# Get the end of the Range we are going to gather data for | ||
[datetime] $RangeEnd = ($RangeStart.AddDays(5)) | ||
# Do the actual search | ||
Out-LogFile ("Searching Range " + [string]$RangeStart + " To " + [string]$RangeEnd) | ||
[array]$Results += Search-MailboxAuditLog -StartDate $RangeStart -EndDate $RangeEnd -identity $User -ShowDetails -ResultSize 250000 | ||
|
||
# Set the RangeStart = to the RangeEnd so we do the next range | ||
$RangeStart = $RangeEnd | ||
} | ||
# While the start range is less than the end date we need to keep pulling in 5 day increments | ||
while ($RangeStart -le $EndDate) | ||
Description: Raw item-level operations data in CSV and JSON formats | ||
# Return the results object | ||
Return $Results | ||
|
||
} | ||
|
||
### MAIN ### | ||
Test-EXOConnection | ||
Send-AIEvent -Event "CmdRun" | ||
|
||
# Verify our UPN input | ||
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName | ||
File: ExchangeItem_Raw.json | ||
Path: \<User> | ||
Description: Raw JSON dump of item operations audit data | ||
foreach ($Object in $UserArray) { | ||
[string]$User = $Object.UserPrincipalName | ||
ExchangeItemGroup Records: | ||
File: ExchangeItemGroup_Simple_{User}.csv/.json | ||
Path: \<User> | ||
Description: Flattened access pattern data in CSV and JSON formats | ||
Out-LogFile ("Attempting to Gather Mailbox Audit logs " + $User) -action | ||
File: ExchangeItemGroup_Logs_{User}.csv/.json | ||
Path: \<User> | ||
Description: Raw access pattern data in CSV and JSON formats | ||
# Test if mailbox auditing is enabled | ||
$mbx = Get-Mailbox -identity $User | ||
if ($mbx.AuditEnabled -eq $true) { | ||
# if enabled pull the mailbox auditing from the unified audit logs | ||
Out-LogFile "Mailbox Auditing is enabled." | ||
Out-LogFile "Searching Unified Audit Log for Exchange Related Events" | ||
File: ExchangeItemGroup_Raw.json | ||
Path: \<User> | ||
Description: Raw JSON dump of access pattern audit data | ||
$UnifiedAuditLogs = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -UserIDs " + $User + " -RecordType ExchangeItem") | select-object -Expandproperty AuditData | convertfrom-json | ||
Out-LogFile ("Found " + $UnifiedAuditLogs.Count + " Exchange audit records.") | ||
.EXAMPLE | ||
Get-HawkUserMailboxAuditing -UserPrincipalName [email protected] | ||
# Output the data we found | ||
$UnifiedAuditLogs | Out-MultipleFileType -FilePrefix "Exchange_UAL_Audit" -User $User -csv -json | ||
Search for all Mailbox Audit logs from [email protected], creating separate files for | ||
item operations and access patterns, each with both raw and processed formats. | ||
# Search the MailboxAuditLogs as well since they may have different/more information | ||
Out-LogFile "Searching Exchange Mailbox Audit Logs (this can take some time)" | ||
.EXAMPLE | ||
Get-HawkUserMailboxAuditing -UserPrincipalName (Get-Mailbox -Filter {CustomAttribute1 -eq "C-level"}) | ||
$MailboxAuditLogs = Get-MailboxAuditLogsFiveDaysAtATime -StartDate $Hawk.StartDate -EndDate $Hawk.EndDate -User $User | ||
Out-LogFile ("Found " + $MailboxAuditLogs.Count + " Exchange Mailbox audit records.") | ||
Search for all Mailbox Audit logs for all users who have "C-Level" set in CustomAttribute1, | ||
creating separate output files for each user's item operations and access patterns. | ||
# Output the data we found | ||
$MailboxAuditLogs | Out-MultipleFileType -FilePrefix "Exchange_Mailbox_Audit" -User $User -csv -json | ||
.NOTES | ||
In older versions of Exchange Online, Search-MailboxAuditLog provided direct access to | ||
mailbox audit data. This has been replaced by the Unified Audit Log which provides a | ||
more comprehensive and consistent view of mailbox activities through separate record types: | ||
- ExchangeItem: Tracks specific operations on items | ||
- ExchangeItemGroup: Tracks access patterns and aggregated activity | ||
Each record type is processed separately and output in multiple formats to support | ||
different analysis needs: | ||
- Simple (flattened) formats for easy analysis | ||
- Raw formats for detailed investigation | ||
- JSON dumps for programmatic processing | ||
#> | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[array]$UserPrincipalName | ||
) | ||
|
||
Test-EXOConnection | ||
Send-AIEvent -Event "CmdRun" | ||
|
||
# Verify our UPN input | ||
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName | ||
|
||
foreach ($Object in $UserArray) { | ||
[string]$User = $Object.UserPrincipalName | ||
|
||
Out-LogFile ("Attempting to Gather Mailbox Audit logs for: " + $User) -action | ||
|
||
# Test if mailbox auditing is enabled | ||
$mbx = Get-Mailbox -Identity $User | ||
if ($mbx.AuditEnabled -eq $true) { | ||
Out-LogFile "Mailbox Auditing is enabled." | ||
|
||
try { | ||
# Get the user's folder path | ||
$UserFolder = Join-Path -Path $Hawk.FilePath -ChildPath $User | ||
if (-not (Test-Path -Path $UserFolder)) { | ||
New-Item -Path $UserFolder -ItemType Directory -Force | Out-Null | ||
} | ||
|
||
# Process ExchangeItem records | ||
Out-LogFile "Searching Unified Audit Log for ExchangeItem events..." | ||
$searchCommand = "Search-UnifiedAuditLog -UserIds $User -RecordType ExchangeItem" | ||
$itemLogs = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand | ||
|
||
if ($itemLogs.Count -gt 0) { | ||
Out-LogFile ("Found " + $itemLogs.Count + " ExchangeItem events.") | ||
|
||
# Write raw JSON dump | ||
$RawJsonPath = Join-Path -Path $UserFolder -ChildPath "ExchangeItem_Raw.json" | ||
$itemLogs | Select-Object -ExpandProperty AuditData | Out-File -FilePath $RawJsonPath | ||
|
||
# Process and output flattened data | ||
$ParsedItemLogs = $itemLogs | Get-SimpleUnifiedAuditLog | ||
if ($ParsedItemLogs) { | ||
$ParsedItemLogs | Out-MultipleFileType -FilePrefix "ExchangeItem_Simple" -csv -json -User $User | ||
} | ||
|
||
# Output raw data | ||
$itemLogs | Out-MultipleFileType -FilePrefix "ExchangeItem_Logs" -csv -json -User $User | ||
} | ||
else { | ||
Out-LogFile "No ExchangeItem events found." | ||
} | ||
|
||
# Process ExchangeItemGroup records | ||
Out-LogFile "Searching Unified Audit Log for ExchangeItemGroup events..." | ||
$searchCommand = "Search-UnifiedAuditLog -UserIds $User -RecordType ExchangeItemGroup" | ||
$groupLogs = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand | ||
|
||
if ($groupLogs.Count -gt 0) { | ||
Out-LogFile ("Found " + $groupLogs.Count + " ExchangeItemGroup events.") | ||
|
||
# Write raw JSON dump | ||
$RawJsonPath = Join-Path -Path $UserFolder -ChildPath "ExchangeItemGroup_Raw.json" | ||
$groupLogs | Select-Object -ExpandProperty AuditData | Out-File -FilePath $RawJsonPath | ||
|
||
# Process and output flattened data | ||
$ParsedGroupLogs = $groupLogs | Get-SimpleUnifiedAuditLog | ||
if ($ParsedGroupLogs) { | ||
$ParsedGroupLogs | Out-MultipleFileType -FilePrefix "ExchangeItemGroup_Simple" -csv -json -User $User | ||
} | ||
|
||
# Output raw data | ||
$groupLogs | Out-MultipleFileType -FilePrefix "ExchangeItemGroup_Logs" -csv -json -User $User | ||
} | ||
else { | ||
Out-LogFile "No ExchangeItemGroup events found." | ||
} | ||
|
||
# Summary logging | ||
$totalEvents = ($itemLogs.Count + $groupLogs.Count) | ||
Out-LogFile "Completed processing $totalEvents total events." | ||
} | ||
# If auditing is not enabled log it and move on | ||
else { | ||
Out-LogFile ("Auditing not enabled for " + $User) | ||
catch { | ||
Out-LogFile "Error retrieving audit logs: $($_.Exception.Message)" -Notice | ||
Write-Error -ErrorRecord $_ -ErrorAction Continue | ||
} | ||
} | ||
} | ||
else { | ||
Out-LogFile ("Auditing not enabled for " + $User) -Notice | ||
Out-LogFile "Enable auditing to track mailbox access patterns." -Notice | ||
} | ||
} | ||
} |