Private/Invoke-IntuneAccessGraphRequest.ps1
|
function Invoke-IntuneAccessGraphRequest { [CmdletBinding()] param( [Parameter(Mandatory)] [string] $Uri, [ValidateSet('v1.0', 'beta')] [string] $ApiVersion = 'v1.0', [ValidateRange(0, 10)] [int] $MaxRetryCount = 4, [switch] $SingleObject ) $null = Assert-IntuneAccessConnection if (-not (Get-Command -Name Invoke-MgGraphRequest -ErrorAction SilentlyContinue)) { throw 'Invoke-MgGraphRequest is unavailable. Import Microsoft.Graph.Authentication and reconnect.' } $nextUri = if ($Uri -match '^https://graph\.microsoft\.com/') { $Uri } else { "https://graph.microsoft.com/$ApiVersion/$($Uri.TrimStart('/'))" } $items = [System.Collections.Generic.List[object]]::new() do { $attempt = 0 while ($true) { try { Write-Verbose "GET $nextUri" $response = Invoke-MgGraphRequest -Method GET -Uri $nextUri -OutputType PSObject break } catch { $statusCode = 0 $responseProperty = $_.Exception.PSObject.Properties['Response'] $errorResponse = if ($null -ne $responseProperty) { $responseProperty.Value } else { $null } $statusProperty = if ($null -ne $errorResponse) { $errorResponse.PSObject.Properties['StatusCode'] } else { $null } if ($null -ne $statusProperty -and $null -ne $statusProperty.Value) { $statusCode = [int] $statusProperty.Value } elseif ($_.Exception.Message -match '\b(401|403|429|5\d\d)\b') { $statusCode = [int] $Matches[1] } if ($statusCode -eq 401) { throw 'Microsoft Graph rejected the session (HTTP 401). The token may have expired. Run Connect-IntuneAccess again.' } if ($statusCode -eq 403) { throw "Microsoft Graph denied this read request (HTTP 403): $nextUri. Check Graph consent and the signed-in administrator's Intune permissions." } $retryable = $statusCode -eq 429 -or ($statusCode -ge 500 -and $statusCode -lt 600) if (-not $retryable -or $attempt -ge $MaxRetryCount) { throw "Microsoft Graph read failed for $nextUri. $($_.Exception.Message)" } $retryAfter = 0 $headersProperty = if ($null -ne $errorResponse) { $errorResponse.PSObject.Properties['Headers'] } else { $null } if ($null -ne $headersProperty -and $null -ne $headersProperty.Value) { $retryAfterProperty = $headersProperty.Value.PSObject.Properties['RetryAfter'] $header = if ($null -ne $retryAfterProperty) { $retryAfterProperty.Value } else { $null } $deltaProperty = if ($null -ne $header) { $header.PSObject.Properties['Delta'] } else { $null } if ($null -ne $deltaProperty -and $null -ne $deltaProperty.Value) { $retryAfter = [int] [Math]::Ceiling($deltaProperty.Value.TotalSeconds) } } if ($retryAfter -le 0) { $retryAfter = [Math]::Min(2 * [Math]::Pow(2, $attempt), 30) } $attempt++ Write-Verbose "Graph returned HTTP $statusCode. Retrying in $retryAfter second(s), attempt $attempt of $MaxRetryCount." Start-Sleep -Seconds $retryAfter } } $valuePropertyExists = if ($response -is [System.Collections.IDictionary]) { $response.Contains('value') } else { $null -ne $response.PSObject.Properties['value'] } $value = Get-IntuneAccessProperty -InputObject $response -Name 'value' if ($valuePropertyExists -and -not $SingleObject) { foreach ($item in @($value)) { $items.Add($item) } } else { $items.Add($response) } $nextLink = Get-IntuneAccessProperty -InputObject $response -Name '@odata.nextLink' if ($SingleObject) { $nextLink = $null } $nextUri = [string] $nextLink } while (-not [string]::IsNullOrWhiteSpace($nextUri)) return $items.ToArray() } |