Private/Invoke-AACResourceGraphQuery.ps1

function Invoke-AACResourceGraphQuery {
    <#
    .SYNOPSIS
        Runs a Kusto query against Azure Resource Graph for one or more
        subscriptions (or every subscription the signed-in account can see),
        following $skipToken pagination, and returns every result row.
    .DESCRIPTION
        Wraps POST https://management.azure.com/providers/Microsoft.ResourceGraph/resources
        (api-version 2022-10-01). Resource Graph pages differently to a plain
        ARM list endpoint: instead of a nextLink URL, a response can carry a
        "$skipToken" that has to be echoed back inside the *next* request's
        "options" object (together with the same query and subscription) to
        get the next page; its absence means there is no more data.
 
        Resource Graph is used here (rather than one REST call per resource)
        because it can answer "every virtual network / NSG / route table in
        this subscription" in a single call each, no matter how many exist -
        the alternative is a REST call per resource, which does not scale.
 
        Leave -SubscriptionId out to query every subscription the signed-in
        account can see, in one request.
    #>

    [CmdletBinding()]
    [OutputType([object[]])]
    param(
        [string[]] $SubscriptionId,

        [Parameter(Mandatory)]
        [string] $Query,

        [Parameter(Mandatory)]
        [hashtable] $Headers
    )

    # No web-request progress bar or per-call verbose line: callers show their
    # own Spectre progress.
    $ProgressPreference = 'SilentlyContinue'
    $collected = [System.Collections.Generic.List[object]]::new()
    $skipToken = $null

    do {
        $requestBody = @{
            query = $Query
        }
        if ($SubscriptionId) {
            $requestBody.subscriptions = @($SubscriptionId)
        }
        if ($skipToken) {
            $requestBody.options = @{ '$skipToken' = $skipToken }
        }

        $response = Invoke-RestMethod -Uri 'https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2022-10-01' `
            -Method Post -Headers $Headers -ContentType 'application/json' `
            -Body ($requestBody | ConvertTo-Json -Depth 10) -ErrorAction Stop -Verbose:$false

        foreach ($item in $response.data) {
            $collected.Add($item)
        }

        $skipToken = Get-AACPropertyValue -InputObject $response -Name '$skipToken'
    } while ($skipToken)

    return $collected.ToArray()
}