Private/Resolve-SCAError.ps1
|
function Resolve-SCAError { <# .SYNOPSIS Translates a failed CyberArk API call into a structured PowerShell error record. .DESCRIPTION Extracts the HTTP status, any CyberArk error body (message/code/requestId), and the endpoint that was called, then builds a single-line error message plus a detailed multi-line message carried on the ErrorRecord. Never includes header values, since those may carry the bearer token; only the parsed response body and status metadata are used. .PARAMETER ErrorRecord The ErrorRecord caught from Invoke-WebRequest / Invoke-RestMethod. .PARAMETER Service The CyberArk service that was called, for error context. .PARAMETER Operation The psSCA cmdlet or logical operation name, for error context. .PARAMETER Uri The request URI that failed. Query string is retained; no header/auth data is present in it. .OUTPUTS System.Management.Automation.ErrorRecord #> [CmdletBinding()] [OutputType([System.Management.Automation.ErrorRecord])] param( [Parameter(Mandatory)] [System.Management.Automation.ErrorRecord]$ErrorRecord, [Parameter(Mandatory)] [string]$Service, [Parameter(Mandatory)] [string]$Operation, [Parameter(Mandatory)] [string]$Uri ) $statusCode = $null $responseBody = $null if ($ErrorRecord.Exception -is [Microsoft.PowerShell.Commands.HttpResponseException]) { $statusCode = [int]$ErrorRecord.Exception.Response.StatusCode if ($ErrorRecord.ErrorDetails -and $ErrorRecord.ErrorDetails.Message) { $responseBody = $ErrorRecord.ErrorDetails.Message } } elseif ($ErrorRecord.Exception.Response) { try { $statusCode = [int]$ErrorRecord.Exception.Response.StatusCode } catch { $statusCode = $null } } $serviceMessage = $null $errorCode = $null $requestId = $null if ($responseBody) { try { $parsed = $responseBody | ConvertFrom-Json -ErrorAction Stop $serviceMessage = $parsed.message ?? $parsed.error_description ?? $parsed.error ?? $parsed.Message $errorCode = $parsed.code ?? $parsed.errorCode ?? $parsed.error_code $requestId = $parsed.requestId ?? $parsed.request_id ?? $parsed.correlationId ?? $parsed.correlation_id } catch { $serviceMessage = Protect-SCASecret -InputObject $responseBody } } if (-not $serviceMessage) { $serviceMessage = $ErrorRecord.Exception.Message } $lines = [System.Collections.Generic.List[string]]::new() $lines.Add('Secure Cloud Access API request failed.') $lines.Add('') if ($statusCode) { $lines.Add("HTTP Status : $statusCode") } $lines.Add("Operation : $Operation") $lines.Add("Service : $Service") $lines.Add("Endpoint : $Uri") $lines.Add("Message : $serviceMessage") if ($errorCode) { $lines.Add("Error Code : $errorCode") } if ($requestId) { $lines.Add("Request ID : $requestId") } $message = $lines -join [Environment]::NewLine $category = switch ($statusCode) { 401 { [System.Management.Automation.ErrorCategory]::AuthenticationError } 403 { [System.Management.Automation.ErrorCategory]::PermissionDenied } 404 { [System.Management.Automation.ErrorCategory]::ObjectNotFound } 429 { [System.Management.Automation.ErrorCategory]::LimitsExceeded } default { [System.Management.Automation.ErrorCategory]::InvalidOperation } } $newException = [System.Exception]::new($message, $ErrorRecord.Exception) $errorId = "psSCA.$Service.$Operation" + $(if ($statusCode) { ".$statusCode" } else { '' }) return [System.Management.Automation.ErrorRecord]::new($newException, $errorId, $category, $Uri) } |