Private/Invoke-IntuneGraphRequest.ps1
|
<#
.SYNOPSIS Invokes Microsoft Graph REST API for Intune/DeviceManagement. .DESCRIPTION Ensures Connect-MgGraph (or equivalent) is used, then calls Graph API. #> function Invoke-IntuneGraphRequest { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Method, [Parameter(Mandatory = $true)] [string]$Uri, [object]$Body = $null ) if ($Uri -notmatch '^https://') { $Uri = "https://graph.microsoft.com/v1.0/$($Uri.TrimStart('/'))" } try { if (Get-Command -Name 'Invoke-MgGraphRequest' -ErrorAction SilentlyContinue) { $params = @{ Method = $Method Uri = $Uri ErrorAction = 'Stop' } if ($Body) { $params["Body"] = $Body } return Invoke-MgGraphRequest @params } $ctx = $null if (Get-Command -Name 'Get-MgContext' -ErrorAction SilentlyContinue) { $ctx = Get-MgContext } if (-not $ctx -or -not $ctx.TenantId) { throw "Not connected to Microsoft Graph. Run Connect-MgGraph or ensure Import-NLBaselineConfig + Connect-Intune first." } $token = $null if (Get-Command -Name 'Get-MgAccessToken' -ErrorAction SilentlyContinue) { $token = Get-MgAccessToken } if (-not $token) { throw "Could not obtain Graph access token. Connect via Connect-MgGraph." } $headers = @{ "Authorization" = "Bearer $token" "Content-Type" = "application/json" } $irmParams = @{ Method = $Method Uri = $Uri Headers = $headers } if ($Body) { $irmParams["Body"] = if ($Body -is [string]) { $Body } else { $Body | ConvertTo-Json -Depth 20 } } return Invoke-RestMethod @irmParams } catch { $err = $_.Exception.Message $responseBody = "" $httpErr = $_.Exception if ($httpErr -is [System.Net.Http.HttpRequestException] -and $httpErr.Data.Contains('Response')) { try { $response = $httpErr.Data['Response'] if ($response -and $response.Content) { $responseBody = $response.Content.ReadAsStringAsync().Result } } catch { $null = 0 # Ignore response-body parse; primary error is preserved } } elseif ($_.Exception.Response) { try { $resp = $_.Exception.Response if ($resp.GetType().Name -eq 'HttpResponseMessage') { $responseBody = $resp.Content.ReadAsStringAsync().Result } else { $stream = $resp.GetResponseStream() $reader = New-Object System.IO.StreamReader($stream) $responseBody = $reader.ReadToEnd() $reader.Close() $stream.Close() } } catch { $null = 0 # Ignore response-body parse; primary error is preserved } } if ($err -match '401|Unauthorized') { Write-Error "Graph request failed (401 Unauthorized). Check: (1) Client secret expired – create a new one in Azure App Registration > Certificates & secrets and update config.json; (2) ClientId, TenantId, or ClientSecret incorrect in config.json; (3) App Registration disabled or deleted. See WIKI.md Troubleshooting." } elseif ($err -match '403|Forbidden|DeviceManagementConfiguration') { Write-Error "Graph request failed (403). Ensure the App Registration has Application permission 'DeviceManagementConfiguration.ReadWrite.All' and admin consent is granted. See API-PERMISSIONS.md." } elseif ($err -match '400|BadRequest') { $detailedErr = $err if ($responseBody) { try { $errJson = $responseBody | ConvertFrom-Json -ErrorAction SilentlyContinue if ($errJson.error.message) { $detailedErr = $errJson.error.message } elseif ($errJson.error.innerError) { $detailedErr = $errJson.error.innerError | ConvertTo-Json -Depth 5 } } catch { $null = 0 # Ignore JSON parse; use generic error } } Write-Error "Graph request failed (400 BadRequest). $detailedErr" } else { Write-Error "Graph request failed: $err" } throw } } |