The Microsoft 365 Unified Audit Logs (aka. Office 365 Audit Logs) serve as a valuable resource for organizations using Microsoft 365. These logs consolidate data from multiple services within the Microsoft 365 suite, providing a unified view of activities and events.
Accessing and analyzing the Microsoft 365 audit logs can be done through various methods, including the Microsoft 365 Security & Compliance Center and PowerShell cmdlets. PowerShell, in particular, offers a powerful and efficient way to query these logs, making it easier to extract and analyze specific audit log data.
In this blog post, we will explore how PowerShell can query the Office 365 Audit Logs effectively. Join us as we dive into the world of Microsoft 365 audit logs and discover how PowerShell can be a game-changer in managing and querying this valuable data.
Table of Contents
What Data Do Office 365 Audit Logs Include?
Office 365 Audit Logs record various types of events, including:
- User and administrator activities: This includes actions such as file access, document sharing, email activities, user sign-in events, changes to user roles and permissions, and other user-related activities.
- Exchange Online events: These cover activities related to Exchange Online, such as email sends and receives, mailbox access, message deletions, and changes to mailbox configurations.
- SharePoint Online and OneDrive for Business events: It tracks activities within SharePoint Online and OneDrive for Business, including file uploads, downloads, sharing, and modifications.
- Azure Active Directory events: This includes events related to user and group management, password resets, user sign-in events, and other activities within the Azure Active Directory service.
- Azure Information Protection events: It logs activities related to data protection and classification, including document labeling, encryption, and other security-related actions.
But first, turn on auditing…
Before going further, you must confirm that auditing is turned on in your tenant. Without it, there are no logs to search.
To do so, connect to the Exchange Online PowerShell session. This requires installing the Exchange Online PowerShell V3 module on your computer.
Connect-ExchangeOnline -Organization tenant.onmicrosoft.com
Next, run the following command to confirm the UnifiedAuditLogIngestionEnabled property.
Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabled
If the UnifiedAuditLogIngestionEnabled says True, then you’re all set.
If not, run the following command to turn on auditing. Note that you must be an Organization Management role group member for this command to work.
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
Search Office 365 Audit Logs with Search-UnifiedAuditLog
A powerful cmdlet in PowerShell that enables you to search and retrieve information from the Microsoft 365 Unified Audit Logs is “Search-UnifiedAuditLog.”
This cmdlet allows you to specify various search criteria, such as date ranges, specific activities, users, or even IP addresses, to narrow your search and retrieve the relevant audit log entries.
Syntax, RecordType, and Operations
Below is the syntax for the Search-UnifiedAuditLog cmdlet. As you can see, only the StartDate and EndDate are required. But in most cases, narrowing down your search by filtering the RecordType and Operations is recommended.
Search-UnifiedAuditLog -EndDate <ExDateTime> -StartDate <ExDateTime> [-Formatted] [-FreeText <String>] [-IPAddresses <String[]>] [-ObjectIds <String[]>] [-Operations <String[]>] [-RecordType <AuditRecordType>] [-ResultSize <Int32>] [-SessionCommand <UnifiedAuditSessionCommand>] [-SessionId <String>] [-SiteIds <String[]>] [-UserIds <String[]>] [<CommonParameters>]
RecordType — This is the service-specific record type that you wish to filter. For example, ExchangeAdmin is the record type containing the admin-related operations performed in Exchange Online. Another example is the SharePointFileOperation record type, which consists of file-related operations or events in SharePoint Online.
Operations — The events or actions that happened. One example operation is FileAccessed for the SharePointFileOperation record, an entry for when a file was accessed from a SharePoint Online library. Under the ExchangeAdmin record type, you will see the cmdlet name executed, like Set-TransportConfig, Set-Mailbox, and Set-UnifiedGroup.
Refer to the Office 365 Management Activity API schema to see the valid record types and operations list.
The following sections demonstrate examples of using the Search-UnifiedAuditLog cmdlet. Let’s dive in.
Suppose you need to report how many SharePoint Online sites were created in the last 90 days. To do that, we’ll use the SharePoint record type.
Copy the code below and run it in your Exchange Online PowerShell session.
$startDate = (Get-Date).AddDays(-90) $endDate = (Get-Date) $result = Search-UnifiedAuditLog ` -StartDate $startDate ` -EndDate $endDate ` -RecordType SharePoint ` -Operations SiteCollectionCreated ` -Formatted $result | Group-Object -Property Operations
Note that the -Formatted switch ensures that the RecordType and Operations attributes in the results are returned as names, not integers.
According to the result, there have been three SiteCollectionCreated events in the last 90 days.
The details of each audit log are in the AuditData property in JSON format. Now let’s inspect one of the results.
$result[0].AuditData | ConvertFrom-Json
Search Exchange Online Audit Logs
One area in Exchange Online that admins tend to monitor is the actions executed by administrators. In this example, we can run the Search-UnifiedAuditLog and specify the ExchangeAdmin record type.
For example, the below command returns all Exchange-cmdlets executed in the last 90 days.
$startDate = (Get-Date).AddDays(-90) $endDate = (Get-Date) $result = Search-UnifiedAuditLog ` -StartDate $startDate ` -EndDate $endDate ` -RecordType ExchangeAdmin ` -Formatted $result | Group-Object -Property Operations | Select-Object Count, Name
But how do we know who did what? Let’s inspect one log entry.
$result[0].AuditData | ConvertFrom-Json
The result shows that the Set-AdminAuditLogConfig command was executed by the NT AUTHORITY\SYSTEM (Microsoft.Exchange.ServiceHost) account.
How about listing all events? For that, we can apply an iteration like the foreach statement.
foreach ($item in $result) { $audit = $item.AuditData | ConvertFrom-Json New-Object psobject -Property $([ordered]@{ TimeStamp = $audit.CreationTime UserId = $audit.UserId Operation = $audit.Operation # Parameters = $audit.Parameters Parameters = [string]$( $audit.Parameters | ForEach-Object { "$($_.Name):$($_.Value);" } ) } ) }
There can be irrelevant log entries. Perhaps you’d want to ignore the events created by the NT AUTHORITY\SYSTEM (Microsoft.Exchange.ServiceHost) and NT AUTHORITY\SYSTEM (w3wp) accounts? We can add an array of user Ids to ignore.
# List of UserIds to ignore $ignoreEventsBy = @( 'NT AUTHORITY\SYSTEM (Microsoft.Exchange.ServiceHost)', 'NT AUTHORITY\SYSTEM (w3wp)' )
And insert an if statement that checks if the UserId is listed in the $ignoreEventsBy array. If so, the foreach loop will skip this event.
foreach ($item in $result) { $audit = $item.AuditData | ConvertFrom-Json if ($ignoreEventsBy -contains $audit.UserId) { # skip this event continue } New-Object psobject -Property $([ordered]@{ TimeStamp = $audit.CreationTime UserId = $audit.UserId Operation = $audit.Operation Parameters = [string]$( $audit.Parameters | ForEach-Object { "$($_.Name):$($_.Value);" } ) } ) }
This time, only the events from actual users are included in the report.
Handling Large Office 365 Audit Log Results
The Search-UnifiedAuditLog command returns 100 items by default, which is not a lot. When you run the below command, it returns 100 audit logs entries.
$startDate = (Get-Date).AddDays(-10) $endDate = (Get-Date) $result = Search-UnifiedAuditLog ` -StartDate $startDate ` -EndDate $endDate ` -RecordType SharePoint ` -Formatted $result.Count
You can increase the result size to a maximum of 5000 by adding the -ResultSize 5000 and -SessionCommand ReturnLargeSet parameters.
$result = Search-UnifiedAuditLog ` -StartDate $startDate ` -EndDate $endDate ` -RecordType SharePoint ` -SessionCommand ReturnLargeSet ` -ResultSize 5000 ` -Formatted $result.Count
What if there are more than 5,000 Office 365 audit log items? Don’t worry; the maximum you can retrieve is up to 50,000 using paging. Each page result can be a maximum of 5,000 items. You can achieve this by specifying the -SessionId parameter.
First, create a unique session ID, this can be any value, but I prefer using a GUID. Next, we’ll enclose the Search-UnifiedAuditLog command in a do-while loop. The command will run until there are no more results. Each iteration will use the same SessionId value.
$sessionID = (New-Guid).Guid $startDate = (Get-Date).AddDays(-4) $endDate = (Get-Date) $result = [System.Collections.ArrayList]@() do { $temp = Search-UnifiedAuditLog ` -StartDate $startDate ` -EndDate $endDate ` -RecordType SharePoint ` -SessionId $sessionId ` -SessionCommand ReturnLargeSet ` -ResultSize 5000 ` -Formatted foreach ($item in $temp) { $audit = $item.AuditData | ConvertFrom-Json $null = $result.Add($( New-Object psobject -Property $([ordered]@{ TimeStamp = $audit.CreationTime UserId = $audit.UserId Operation = $audit.Operation ObjectID = $audit.ObjectId } ) ) ) } } while ($temp.count -gt 0) $result.count
In this example, the total result is over 41,000 log items.
You can export the result to a CSV file using the Export-Csv cmdlet if needed.
$result | Export-Csv -NoTypeInformation .\auditlog.csv
Conclusion
Querying Microsoft 365 audit logs using PowerShell is a powerful and efficient way to gain valuable insights into your organization’s activities, security, and compliance. By leveraging the capabilities of PowerShell and the Search-UnifiedAuditLog, you can easily retrieve and analyze the information stored in your audit logs.