functions/Get-XdrEndpointDeviceActionResult.ps1
|
function Get-XdrEndpointDeviceActionResult { <# .SYNOPSIS Gets device action results and download URIs from Microsoft Defender XDR. .DESCRIPTION Retrieves the latest device action results for a device, or downloads completed investigation package or support log collection results. When called with just -DeviceId, returns the latest action results for each action type including status, requestor, timestamps, and request GUIDs. When called with -DownloadInvestigationPackage or -DownloadSupportLogs, retrieves the download URI for completed collection results. You can provide either a DeviceId (which auto-resolves the latest RequestGuid from machine state) or a RequestGuid directly. .PARAMETER DeviceId The device identifier (SenseMachineId) to query action results for. Accepts pipeline input by property name and supports MachineId/SenseMachineId aliases. .PARAMETER DownloadInvestigationPackage Retrieve the download URI for the latest investigation package (forensics) collection. .PARAMETER DownloadSupportLogs Retrieve the download URI for the latest support logs collection. .PARAMETER RequestGuid The GUID of a specific request. When used with -DeviceId (List mode), filters the results to the matching request. When used with -DownloadInvestigationPackage or -DownloadSupportLogs, specifies the completed request to download results for. .EXAMPLE Get-XdrEndpointDeviceActionResult -DeviceId "55a5db7b474470725e0131dec38c07b2f54bf2ad" Gets the latest action results for the specified device. .EXAMPLE Get-XdrEndpointDeviceActionResult -DeviceId "55a5db7b474470725e0131dec38c07b2f54bf2ad" -RequestGuid "1b2010b8-143e-441b-b5e9-c0b56c090a24" Gets the action result for a specific request on the device. .EXAMPLE Get-XdrEndpointDevice -DeviceId $deviceId | Get-XdrEndpointDeviceActionResult Gets action results for a device using pipeline input. .EXAMPLE Get-XdrEndpointDeviceActionResult -DownloadInvestigationPackage -DeviceId "55a5db7b474470725e0131dec38c07b2f54bf2ad" Auto-resolves the latest investigation package request and returns its download URI. .EXAMPLE Get-XdrEndpointDevice -DeviceId $deviceId | Get-XdrEndpointDeviceActionResult -DownloadSupportLogs Gets the download URI for the latest support logs collection using pipeline input. .EXAMPLE Get-XdrEndpointDeviceActionResult -DownloadInvestigationPackage -RequestGuid "b28b630c-d1a1-4b1d-9676-680c15366a52" Downloads the investigation package for a specific request to the current working directory. .EXAMPLE Get-XdrEndpointDeviceActionResult -DownloadSupportLogs -RequestGuid "abc12345-6789-0123-4567-890abcdef012" Downloads the support logs for a specific request to the current working directory. .OUTPUTS PSCustomObject[] When listing: Returns an array of action result objects with Type, RequestStatus, Requestor, timestamps, etc. System.IO.FileInfo When downloading: Returns a FileInfo object for the downloaded file in the current working directory. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter defines parameter set')] [CmdletBinding(DefaultParameterSetName = 'List')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'List')] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DownloadInvestigationPackageByDevice')] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DownloadSupportLogsByDevice')] [Alias('MachineId', 'SenseMachineId')] [ValidateLength(40, 40)] [ValidatePattern('^[0-9a-fA-F]{40}$')] [string]$DeviceId, [Parameter(Mandatory = $true, ParameterSetName = 'DownloadInvestigationPackageByDevice')] [Parameter(Mandatory = $true, ParameterSetName = 'DownloadInvestigationPackageByRequest')] [switch]$DownloadInvestigationPackage, [Parameter(Mandatory = $true, ParameterSetName = 'DownloadSupportLogsByDevice')] [Parameter(Mandatory = $true, ParameterSetName = 'DownloadSupportLogsByRequest')] [switch]$DownloadSupportLogs, [Parameter(ParameterSetName = 'List')] [Parameter(Mandatory = $true, ParameterSetName = 'DownloadInvestigationPackageByRequest')] [Parameter(Mandatory = $true, ParameterSetName = 'DownloadSupportLogsByRequest')] [string]$RequestGuid ) begin { Update-XdrConnectionSettings } process { try { switch -Wildcard ($PSCmdlet.ParameterSetName) { 'List' { $Uri = "https://security.microsoft.com/apiproxy/mtp/responseApiPortal/requests/latest?machineId=$DeviceId&tenantIds=" Write-Verbose "Retrieving latest action results for device $DeviceId" $result = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers if ($RequestGuid) { Write-Verbose "Filtering results for RequestGuid: $RequestGuid" $result = $result | Where-Object { $_.RequestGuid -eq $RequestGuid } } return $result } 'DownloadInvestigationPackageBy*' { if ($PSCmdlet.ParameterSetName -eq 'DownloadInvestigationPackageByDevice') { $stateUri = "https://security.microsoft.com/apiproxy/mtp/responseApiPortal/requests/machinestate?machineId=$DeviceId&overrideCache=false" Write-Verbose "Looking up latest investigation package request for device $DeviceId" $state = Invoke-RestMethod -Uri $stateUri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers $RequestGuid = $state.RequestsIds.ForensicsRequest if (-not $RequestGuid) { Write-Error "No investigation package request found for device $DeviceId" return } Write-Verbose "Resolved ForensicsRequest GUID: $RequestGuid (State: $($state.States.ForensicsRequest))" } $Uri = "https://security.microsoft.com/apiproxy/mtp/responseApiPortal/requests/forensics/downloaduribyguid/V2?requestGuid=$RequestGuid&packageIdentity=null" Write-Verbose "Retrieving investigation package download URI for request $RequestGuid" $downloadUri = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers $fileName = [System.IO.Path]::GetFileName(([System.Uri]$downloadUri).LocalPath) if (-not $fileName) { $fileName = "InvestigationPackage-$RequestGuid.zip" } $outFile = Join-Path $PWD $fileName Write-Verbose "Downloading from:`n`n$downloadUri" Invoke-WebRequest -Uri $downloadUri -OutFile $outFile return Get-Item $outFile } 'DownloadSupportLogsBy*' { if ($PSCmdlet.ParameterSetName -eq 'DownloadSupportLogsByDevice') { $stateUri = "https://security.microsoft.com/apiproxy/mtp/responseApiPortal/requests/machinestate?machineId=$DeviceId&overrideCache=false" Write-Verbose "Looking up latest support logs request for device $DeviceId" $state = Invoke-RestMethod -Uri $stateUri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers $RequestGuid = $state.RequestsIds.LogsCollectionRequest if (-not $RequestGuid) { Write-Error "No support logs request found for device $DeviceId" return } Write-Verbose "Resolved LogsCollectionRequest GUID: $RequestGuid (State: $($state.States.LogsCollectionRequest))" } $Uri = "https://security.microsoft.com/apiproxy/mtp/responseApiPortal/requests/logscollection/downloaduribyguid/V2?LogCollectionV2Migration=true&requestGuid=$RequestGuid" Write-Verbose "Retrieving support logs download URI for request $RequestGuid" $downloadUri = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers $fileName = [System.IO.Path]::GetFileName(([System.Uri]$downloadUri).LocalPath) if (-not $fileName) { $fileName = "SupportLogs-$RequestGuid.zip" } $outFile = Join-Path $PWD $fileName Write-Verbose "Downloading from:`n`n$downloadUri" Invoke-WebRequest -Uri $downloadUri -OutFile $outFile return Get-Item $outFile } } } catch { Write-Error "Failed to retrieve action result: $_" } } end { } } |