Site icon Office 365 for IT Pros

Using Graph Delta Queries with Entra ID Groups

Delta Queries for Entra ID Groups.
Advertisements

Delta Queries are Useful for Synchronization, Not for Reporting

The article about tracking changes in Microsoft 365 groups resulted in a comment that using a delta query against the Groups Graph endpoint might be a solution to track changes made by groups. The assertion is correct, but it doesn’t work in the scenario where we want to report group changes over the last month. Let me explain why.

A delta query (also called change tracking) enables applications to find added, changes, or deleted objects without performing a full read of every object from a Graph resource. Microsoft Graph supports delta queries for several resources, including Entra ID objects like users and groups, Outlook resources like messages and calendar events, and SharePoint/OneDrive objects like drives and drive items. It’s important to check the documentation for resources to understand if a resource supports delta queries and if so, if any limitations or special conditions exist. For example, delta queries don’t typically support the expand, top, or orderby (sort) query parameters.

The problem posed by the scenario of monitoring group changes over an extended period is that delta queries rely on a specific pattern by first establishing a baseline and then monitoring changes that occur subsequently. The script that I wrote is designed to be run on an ad hoc basis. Because the maximum lifetime of a directory delta token is seven days, the script cannot establish a baseline of the state groups were in 30 days ago, meaning that a delta query cannot work. In a nutshell, delta queries are useful for applications that need to synchronize a local store with something like Entra ID, but they are not the basis for reporting.

Delta Query Basics

Delta queries depend on delta links. A delta link is a special form of URI to instruct Graph to provide a list of changes since the creation of the baseline. The classic way to create a delta link is to paginate through the resource to fetch information about objects that we might later want to check against. Instead of a regular query against the resource, the delta query adds /delta and specifies the properties that we’re interested in monitoring. It’s important that any query parameters required by the request are included in the initial request. The Graph includes the query parameters when it generates the delta link to avoid the need to restate the parameters when fetching delta changes.

The last page returned by the Graph contains the delta link, a URI that looks similar to the next page link used to navigate pages during pagination. For convenience, the code saves the delta link to a temporary file.

the delta link to a temporary file.
Connect-MgGraph -Scopes Group.Read.All
$Uri = 'https://graph.microsoft.com/v1.0/groups/delta?$select=id,DisplayName,MailNickName
[array]$Baseline = $null

do {
    $Data = Invoke-MgGraphRequest -Method Get-Uri $Uri

    If ($Data.value) {
        $Baseline += $Data.value
    }

    If ($Data.'@odata.deltaLink') {
        $deltaLink = $Data.'@odata.deltaLink'
        $Uri = $null
    }
    Else {
        $Uri = $Data.'@odata.nextLink'
    }
}
While ($Uri)

$DeltaLink | Out-File .\groupsdeltaLink.txt

After a time, to discover what’s changed in the monitored resource, we use the delta link.

[array]$Data = Invoke-MgGraphRequest -Uri $DeltaLink -Method Get -OutputType PsObject

Changes are returned in the value property of the variable used for the request.

$Data.Value

displayName                 id
-----------                 --
Banking Investigations Team 0f1e8efe-a8e3-442e-ac84-066b4104f647

We now know that the display name of the Banking Investigations Team changed since the creation of the baseline. However, we don’t know who updated the display name, which is another reason why audit records are usually a better source for report data.

Note that multiple references to an object can be returned by a delta query. This happens when multiple changes are made to a baseline object.

Delta Query From Now

Some resources, including users and groups, support the concept of synchronization from now, meaning that we don’t care about retrieving the properties of the resource objects as they now are. Instead, we want the Graph to provide a delta link immediately that can be used to check for modifications from this point forward. To request the token, add $deltatoken=latest to the query:

$Uri = "https://graph.microsoft.com/v1.0/groups/delta?`$deltatoken=latest"
$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get -OutputType PsObject
$DeltaLink = $Data.'@odata.deltaLink'

Delta Query for Specific Groups

A scoping filter allows a delta query to track changes to specific groups (or users). To create a scoped filter, the identifiers of the groups to monitor are included in the query. A maximum of 50 identifiers can be included in the filter.

For example, let’s assume that we want to keep an eye on the membership of two security groups used to control certain functions. To do this, fetch the group identifiers, create the URI with the filter, and use the URI to create a baseline:

$Group1 = Get-MgGroup -Filter "displayName eq 'Account Recovery Enabled Users'"
$Group2 = Get-MgGroup -Filter "displayName eq 'Users Allowed to Create M365 Groups'"
$Uri = ("https://graph.microsoft.com/beta/groups/delta/?`$filter=id eq '{0}' or id eq '{1}'" -f $Group1.Id, $Group2.Id)
# Get baseline
[array]$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get -OutputType PsObject

Over the next seven days, the baseline will report a change in these groups if an update happens for any group property. Note that in this case, the code uses the next link URI instead of the delta link URI. The documentation says that a delta query can respond with either a delta link or next link. My experience is that the next link only appears with a filtered query:

# Check for changes
[array]$Changes = Invoke-MgGraphRequest -Uri $data.'@odata.nextLink' -Method Get
If ($Changes.Value) {
  Write-Output ("Changes detected for the following groups: {0} " -f ($Changes.Value.displayName -join ", "))
}

If a change is detected in a group, it can be reversed with Entra ID Backup and Recovery, providing that the change is noticed within five days.

No Graph SDK Option

Despite the presence of a Get-MgGroupDelta cmdlet, Graph SDK cmdlets do not expose delta links and cannot perform delta queries. This is a known problem that’s been around for years.

Something to Try, But Not for Group Reporting

In summary, delta queries are a useful option in specific circumstances that didn’t include long-term reporting for changes made to Microsoft 365 groups. The option is certainly one to consider for applications that need to keep a close eye on Entra ID users and groups. Or the other innovative ideas that people come up with.


Need help to write and manage PowerShell scripts for Microsoft 365, including Azure Automation runbooks? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Office 365 for IT Pros eBook bundle.

Exit mobile version