The Microsoft Graph for Unified Audit Log acquisitions is here!

March 26, 2024
Interested in all the secrets of the UAL? Join our OnDemand or live training.

Introduction

Great news for those who frequently acquire the Unified Audit Log (UAL): it's officially integrated with the Graph API! In a previous blog post, we touched upon its initial implementation within the Graph API Beta module. At that time, it was only available to a special group that Microsoft gives early access to. It’s now up and running for everyone (as far as we know). We've run a series of tests, the details of which we'll share below. As this has only recently been launched, be aware that you might encounter some bugs. In addition, the documentation is incomplete in some areas as well.

We also updated the Microsoft-Extractor-Suite to include the new functionality, you can test it by installing:

Install-Module -Name Microsoft-Extractor-Suite

Test the new module by running:

Get-UALGraph -searchName "Invictus blog"

Graph API

To get the UAL data through the Graph API the auditLogQuery API (docs) is leveraged, it's currently still in beta. To get the data it's a two step process:

  1. Create auditLogQuery, create a query to retrieve data that you want to acquire
  2. Get auditLogQuery, to return the data from the log query

The procedure closely mirrors what you typically do when searching and downloading results through the audit logs in the Purview portal. When you start a search via the Graph API it will also shows up in the portal.

We've integrated this functionality into the Microsoft-Extractor-Suite, automating the entire process for you. Simply provide the necessary options, and our tool takes care of everything else, from crafting the query to waiting for its completion. Once done, it automatically retrieves the logs and stores them in the designated output directory.

How it works

Instead of making manual Microsoft Graph calls, the Microsoft-Extractor-Suite utilizes the Microsoft.Graph.Security.Beta (docs) module which contains cmdlets that will allow for acquisition of the data.

Specifically the following steps are performed for the audit log retrieval:

  1. Initiate Search Query: Launch a new audit log search by invoking New-MgBetaSecurityAuditLogQuery.
  2. Monitor Query Progress: The tool checks the progress of your search query using Get-MgBetaSecurityAuditLogQuery -AuditLogQueryId {id}. If the query is ongoing, the system will pause for 10 seconds before rechecking.
  3. Retrieve and Save Results: Once the search is complete, the suite automatically downloads the findings and saves them directly to the output directory via Get-MgBetaSecurityAuditLogQueryRecord -AuditLogQueryId {id}.

Acquisition options

As indicated in the documentation for the Create Audit Log query, when you make a request, you can provide a considerable number of parameters. This enables you to filter the logging for relevant data such as:

  • Start date
  • End date
  • Record types
  • Keywords
  • Operations
  • User principal names
  • IP addresses

Example

The various filtering options are available into the Microsoft Extractor Suite. For example let's acquire some data witht the following query:


Get-UALGraph -SearchName BlogTest -startDate "2024-03-10T09:28:56Z" -endDate "2024-03-20T09:28:56Z" -Service Exchange -UserIds bob@invictus-ir.com

This would retrieve specific audit log records from the Exchange service within the specified time period for the actions performed by user bob.

Testing

We conducted several tests comparing the acquisition of the Unified Audit Log using the Graph API versus the old school search-unifiedauditlog cmdlet. We believe that the Graph API's performance will improve as the volume of records increases. This is because of its ability to fetch data more efficiently without requiring extensive looping like the search-unifiedauditlog cmdlet, as it is restricted to extracting only 5000 records at a time. When performing tests with a small time window, the search-unifiedauditlog was faster.

In our test environment, the search-unifiedauditlog extracted the 8500 events within 2 minutes, while the Graph API module typically took around 13 minutes for the same task. However, as the volume of logs increases, the search-unifiedauditlog cmdlet's execution time also increases due to the need for more iterations.

For instance, when utilizing the Microsoft Extractor Suite with the default interval of 720 minutes (equivalent to half a day) over a 90-day period, it would need to run the search-unifiedauditlog cmdlet 180 times. On average, this process would take around 14 minutes to extract the 8500 events. Since the maximum number of events that can be returned in a single search-unifiedauditlog cmdlet is 5000, the duration of the cmdlet increases as the dataset grows.

In some cases, we've encountered millions of events, which sometimes necessitated multiple days to acquire using the Microsoft Extractor Suite. We anticipate that the Graph API might expedite this process, but we have yet to conduct extensive testing in larger environments to confirm its efficiency.

What stands out as an advantage when using the Graph API is the consistency in the returned data volume. In our experimentation, where we extracted data for a period of 90 days (our limited dataset contains only 8700~ events), the search-unifiedauditlog method yielded varying event counts. The Graph API consistently provided the same results.

Below is an overview of the testing results for both acquisition methods for events between 2023-12-21 09:28:56 and 2024-03-20 09:28:56:

Future work

However, further testing in larger environments is required to comprehensively assess whether it outperforms the traditional method of utilizing the search-unifiedauditlog cmdlet. Additionally, it remains unclear if there exists a maximum limit on the number of events that can be returned in a single search query via the Graph API.

Want to learn even more about the Graph the Unified Audit Log or incident response in the cloud? Join our OnDemand or live training.