PSMDATP.psm1
function Add-MDATPDeviceTag{ <# .Synopsis Add-MDATPDeviceTag .DESCRIPTION Add-MDATPDeviceTag adds the specified Tag to the MDATP device .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Tag The value of the tag to be added .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Add-MDATPDeviceTag -DeviceName computer02 -Tag 'Testing' -verbose This command adds the tag 'testing' to the device 'computer02' .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 16.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Tag to be added to the device [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [String]$Tag, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path "$PoshMTPconfigFilePath" -PathType Leaf ){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = "$ClientID" client_secret = "$ClientSecret" grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" # change the devicename to lowercase $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Adding tag: $Tag")){ Try{ # Tag machine $AddTag = @{"Value" = "$Tag"; "Action"= "Add"} | ConvertTo-Json $Taguri = "$MachineAPI/$MDATPDeviceID/tags" $response =Invoke-WebRequest -Uri $Taguri -Headers $Headers -Method Post -Body $AddTag # end tag machine If ($response.StatusCode -eq 200){ Write-Verbose "Tag: $Tag was successfully added to device $DeviceName" $True } Else{ Write-Warning "Adding tag $Tag to device $DeviceName failed!" Write-Error "StatusCode: $($response.StatusCode)" $False } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Added tag: $Tag" Write-Verbose "StatusCode: $($response.statuscode)" Write-Verbose "StatusDescription: $($response.StatusDescription)" } } function Get-MDATPAlert{ <# .Synopsis Get-MDATPAlert .Description Get-MDATPAlert retrieves Microsoft Defender Advanced Threat Protection alerts exposed through the Microsoft Defender Advanced Threat Protection Alerts Rest API. .PARAMETER Severity Provides an option to filter the output by Severity. Low, Medium, High. .PARAMETER PastHours Provides an option to filter the results by past hours when the alert was created. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-WDATPAlert This command retrieves all alerts .EXAMPLE Get-MDATPAlert -PastHours 168 -Severity Informational This command retrieves all alerts from the past 7 days with severity level Informational .NOTES Version: 1.1 Author: Alex Verboon Creation Date: 10.04.2020 Purpose/Change: update config.json #> [CmdletBinding()] Param( # Alert Severity level [Parameter(Mandatory=$false)] [ValidateSet('High', 'Medium', 'Low','Informational')] [String]$Severity, # Show alerts from past n hours [Parameter(Mandatory=$false)] [ValidateSet('12', '24', '48','72','168','720')] [String]$PastHours, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information #WDATP Alerts - Europe $uri = "https://wdatp-alertexporter-eu.windows.com/api/alerts" <# Other regions For EU: https://wdatp-alertexporter-eu.windows.com/api/alerts For US: https://wdatp-alertexporter-us.windows.com/api/alerts For UK: https://wdatp-alertexporter-uk.windows.com/api/alerts #> # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://graph.windows.net" client_id = "$ClientID" client_secret = "$ClientSecret" grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $Headers = @{ Authorization = "Bearer $($Response.access_token)"} } Process{ # Define the time range If ($null -eq $PastHours){ $PastHours = 24 } Else{ $dateTime = (Get-Date).ToUniversalTime().AddHours(-$PastHours).ToString("o") $body = @{sinceTimeUtc = $dateTime} } # Retrieve MDATP alert data Try{ $output = @(Invoke-RestMethod -Uri $uri -Headers $Headers -Body $Body -Method Get -Verbose -ContentType application/json) } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error retrieving MDATP alert data [$errorMessage]" } # Handle the output If ([string]::IsNullOrEmpty($Severity)){ $output } Else{ $output | Where-Object {$_.Severity -eq "$Severity"} } } End{ } } function Get-MDATPCollectionPackageUri{ <# .Synopsis Get-MDATPCollectionPackageUri .DESCRIPTION Get-MDATPCollectionPackageUri retrieves the Investigation Collection Package download URI and optionally download the package Use the Get-MDATPDeviceActions cmdlet to retrieve the ActionID of the investigation package collection request. .PARAMETER ActionID The Action ID of the investigation package collection request. .PARAMETER Download Downloads the investigation pacakge ZIP file into the users Downloads folder .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE $lastcollectionrequestid = Get-MDATPDeviceActions -DeviceName testclient6 -ActionType CollectInvestigationPackage | Select-Object -First 1 Get-MDATPCollectionPackageUri -ActionID $lastcollectionrequestid.id This comand first retrieves the last collection package request ID and then retrieves the download URI .EXAMPLE $lastcollectionrequestid = Get-MDATPDeviceActions -DeviceName testclient6 -ActionType CollectInvestigationPackage | Select-Object -First 1 Get-MDATPCollectionPackageUri -ActionID $lastcollectionrequestid.id -Download This comand first retrieves the last collection package request ID and stores the investigation package into the users download folder .COMPONENT <%=$PLASTER_PARAM_ModuleName%> .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param( # ActionID [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$ActionID, # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile, # Download switch [switch]$Download ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # Define the request URI $MachineActionAPI = "$MDATP_API_URI/machineactions" $getPackageUri = "getPackageUri" $RequestURI = "$MachineActionAPI/$ActionID/$getPackageUri" Write-Verbose "Request URI: $($RequestURI)" # Let's get the Investigation Collection Package download URL Try{ $URIresponse = @(Invoke-RestMethod -Uri "$RequestURI" -Headers $Headers -Method Get -Verbose -ContentType application/json) $URIresponse.value } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" } If($Download){ $fileuri = $URIresponse.value $OutPutFile = "$ENV:USERPROFILE\Downloads\MDATP_InvestigationPackage_$($ActionID).zip" Try{ Invoke-WebRequest -UseBasicParsing -Uri $fileuri -OutFile "$OutPutFile" } Catch{ Write-Error "Investigation Package download failed" } } } End{} } function Get-MDATPDevice{ <# .SYNOPSIS Get-MDATPDevice .DESCRIPTION Get-MDATPDevice retrieves MDATP device information .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER All Lists machine actions for all managed devices .PARAMETER HealthStatus Filters the results by device heatlh. .PARAMETER RiskScore Filters the results by device risk score .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPDevice -all This command retrieves all MDATP devices .EXAMPLE Get-MDATPDevice -All -HealthStatus Inactive This command lists all inactive devices .EXAMPLE Get-MDATPDevice -All -RiskScore Medium This command lists all devices with a medium risk score .EXAMPLE Get-MDATPDevice -DeviceName Computer01 This command retrieves device information for Computer01 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 14.04.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Switch to retrieve actions from all devices [Parameter(Mandatory=$true, ParameterSetName='All')] [switch]$All, # The HealthStatus of the device [Parameter(Mandatory=$false, ParameterSetName='All')] [ValidateNotNullOrEmpty()] [ValidateSet('Inactive','Active')] [String]$HealthStatus, # The device Risk Score [Parameter(Mandatory=$false, ParameterSetName='All')] [ValidateSet('None','Low','Medium','High')] [String]$RiskScore, # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $DeviceUri = "https://api.securitycenter.windows.com/api/machines" If($PSBoundParameters.ContainsKey("HealthStatus")){ $HealthFilter = "healthStatus eq '$Healthstatus'" } If($PSBoundParameters.ContainsKey("RiskScore")){ $RiskFilter = "riskscore eq '$RiskScore'" } If ($HealthFilter -and $RiskFilter){ $DeviceUri = $DeviceUri + "?`$filter=" + $HealthFilter + " and " + $RiskFilter } Elseif($HealthFilter){ $DeviceUri = $DeviceUri + "?`$filter=" + $HealthFilter } ElseIf ($RiskFilter){ $DeviceUri = $DeviceUri + "?`$filter="+$RiskFilter } If ($PSBoundParameters.ContainsKey("DeviceName")){ $DeviceUri = $DeviceUri + "?`$filter=" + "ComputerDNSName eq '$DeviceName'" } If ($PSBoundParameters.ContainsKey("DeviceID")){ $DeviceUri = $DeviceUri + "?`$filter=" + "id eq '$DeviceID'" } Write-Verbose "API Request: $DeviceUri" Try{ $DeviceList = @(Invoke-RestMethod -Uri "$DeviceUri" -Headers $Headers -Method Get -Verbose -ContentType application/json) $Devicelist.value } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error retrieving MDATP device data [$errorMessage]" } } End{ } } function Get-MDATPDeviceAction{ <# .Synopsis Get-MDATPDeviceAction .DESCRIPTION Get-MDATPDeviceAction retrieves machine MDATP actions .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER All Lists machine actions for all managed devices .PARAMETER Action Type Filters the results by the specified Action type. Possible values are: RunAntiVirusScan, Offboard,UnrestrictCodeExecution,RestrictCodeExecution,Unisolate,Isolate,CollectInvestigationPackage,RequestSample,StopAndQuarantineFile .PARAMETER id The machine action id .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPDeviceAction -DeviceName computer02 This command retrieves the actions for device 'computer02' .EXAMPLE Get-MDATPDeviceAction -DeviceID 70077ccc272ab3baeb991c09442c5657d22bfc5c This command retrieves the actions for the device with the specified device id .EXAMPLE Get-MDATPDeviceAction -ActionType CollectInvestigationPackage This command retreives all machine actions with the specified action type .EXAMPLE Get-MDATPDeviceAction -All This command retrieves machine actions for all devices .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Switch to retrieve actions from all devices [Parameter(Mandatory=$true, ParameterSetName='All')] [switch]$All, # MDATP Action id [Parameter(Mandatory=$false, ParameterSetName='id')] [ValidateNotNullOrEmpty()] [String]$Id, # Action Type [Parameter(Mandatory=$false)] [ValidateSet('RunAntiVirusScan','Offboard','UnrestrictCodeExecution','RestrictCodeExecution','Unisolate','Isolate','CollectInvestigationPackage','RequestSample','StopAndQuarantineFile')] [String]$ActionType, # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ If ($DeviceName){ $Machines = @() $DeviceName = $DeviceName.ToLower() $MachineAPI = "https://api.securitycenter.windows.com/api/machines" + "?`$filter=" + "ComputerDNSName eq '$DeviceName'" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) | Select-Object -ExpandProperty Value $ActionDevice = @($Machines) If($ActionDevice.count -gt 1){ Write-Error "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id } Elseif($ActionDevice.count -eq 0){ Write-Error "No device records found that match DeviceName $DeviceName" } Elseif ($ActionDevice.count -eq 1){ Write-Verbose "$($ActionDevice.CompueterDnsName) found with id $($ActionDevice.id)" $DeviceID = $ActionDevice.id } Else{ Write-Error "Something went wrong" } } if($DeviceID){ $MachineAPI = "https://api.securitycenter.windows.com/api/machines/$DeviceID" $Machine = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If($Machine.Count -eq 1){ $DeviceName = $Machine.ComputerDnsName } Else{ Write-Error "No device records found that match DeviceID $DeviceID" } } # Get Machine Actions data $MachineActionsUri= "https://api-us.securitycenter.windows.com/api/machineactions/" if($PSBoundParameters.ContainsKey("All")){ $MachineActionsUri= "https://api-us.securitycenter.windows.com/api/machineactions/" } Else{ If($DeviceName){ $MachineActionsUri = $MachineActionsUri + "?`$filter=" $MachineActionsUri = $MachineActionsUri + "machineId+eq+'$DeviceID'" } If($ActionType){ If($DeviceName){ $MachineActionsUri = $MachineActionsUri + "and type+eq+'$ActionType'" } Else{ $MachineActionsUri = $MachineActionsUri + "?`$filter=" $MachineActionsUri = $MachineActionsUri + "type+eq+'$ActionType'" } } # Search by action ID if($id){ $MachineActionsUri = $MachineActionsUri + "$id" } } # Retrieve MDATP machine actions data Try{ $output = @(Invoke-RestMethod -Uri $MachineActionsUri -Headers $Headers -Method Get -Verbose -ContentType application/json) } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error retrieving MDATP machine actions data [$errorMessage]" } # Handle the output If($id){ $output } Else{ $output.value } } End{} } function Get-MDATPDeviceTag{ <# .Synopsis Get-MDATPDeviceTag .Description Get-MDATPDeviceTag retrieves tags assigned on the specified device .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPDeviceTag -DeviceName computer02 This command reads all the tags assigned to the device 'computer02' .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 16.03.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Switch to retrieve tags from all devices [Parameter(Mandatory=$true, ParameterSetName='All')] [switch]$All, # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $MDATP_API_URI = "https://api.securitycenter.windows.com/api" # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ # change the devicename to lowercase $DeviceName = $DeviceName.ToLower() $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } Elseif($All){ $ActionDevice = @($machines.value) } If($ActionDevice.Count -gt 0 -and $All -eq $true){ $Result = ForEach($device in $ActionDevice){ [PSCustomObject]@{ DeviceName = $device.ComputerDnsName id = $device.id machineTags = $device.machineTags } } $Result } ElseIf($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $Result = [PSCustomObject]@{ DeviceName = $ActionDevice.ComputerDnsName id = $ActionDevice.id machineTags = $ActionDevice.machineTags } $Result } } End{} } function Get-MDATPIndicator{ <# .Synopsis Get-MDATPIndicator .DESCRIPTION Get-MDATPIndicator retrieves Microsoft Defender Advanced Threat Protection custom indicators exposed through the Microsoft Defender Advanced Threat Protection indicators Rest API. .PARAMETER IndicatorType Filters the indicator by the specified IndicatorType. Possible values are: DomainName, Url, FileSha256,IpAddress,WebCategory .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPIndicator This command retrieves all TI indicators .EXAMPLE Get-MDATPIndicator -IndicatorType DomainName This command retrieves all DomainName TI indicators .EXAMPLE $indicators = Get-MDATPIndicator -MTPConfigFile "C:\Dev\Private\MSSecurityPowerShell\Config\PoshMTPconfigBaseVISION.json" $indicators | Where-Object {$_.Source -like "WindowsDefenderATPThreatIntelAPI"} This sample shows how to filter results by TI source .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 20.03.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param( # Indicator type [Parameter(Mandatory=$false)] [ValidateSet('DomainName','Url','FileSha256','IpAddress','WebCategory')] [String]$IndicatorType, # MDATP configfile [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ Try{ $indicatorsuri = "https://api.securitycenter.windows.com/api/indicators" $indicators = @(Invoke-RestMethod -Uri $indicatorsuri -Headers $Headers -Body $Body -Method Get -Verbose -ContentType application/json) } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error retrieving MDATP TI indicators data [$errorMessage]" } If ($IndicatorType){ $indicators.value | Where-Object {$_.IndicatorType -eq "$IndicatorType"} } Else{ $indicators.value } } End{} } function Get-MDATPInvestigation{ <# .Synopsis Get-MDATPInvestigation .DESCRIPTION Get-MDATPInvestigation retrieves Microsoft Defender ATP automated investigation information .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER id The investigation id .PARAMETER State The current state of the investigation. Possible values are: Unknown, Terminated, SuccessfullyRemediated, Benign, Failed, PartiallyRemediated, Running, PendingApproval, PendingResource, PartiallyInvestigated, TerminatedByUser, TerminatedBySystem, Queued, InnerFailure, PreexistingAlert, UnsupportedOs, UnsupportedAlertType, SuppressedAlert .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPInvestigation This command retrieves all investigations .EXAMPLE Get-MDATPInvestigation -DeviceName Computer01 This command retrieves all investigations for Computer01 .EXAMPLE Get-MDATPInvestigation -DeviceID 70077ccc272ab3baeb991c09442c5657d22bfc5c This command retrieves all investigations for the device with the specified device id. .EXAMPLE Get-MDATPInvestigation -State Running This command retireves all investigations with the state Running .EXAMPLE Get-MDATPInvestigation -Id 12 This command retrieves investigation details for the investigation with id 12 .EXAMPLE Get-MDATPInvestigation -DeviceName computer01 -State SuccessfullyRemediated This command retrieves all SuccessfullyRemediated investigations for device computer01 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding(DefaultParametersetname="All")] Param( # Switch to list all devices [Parameter(Mandatory=$false, ParameterSetName='All')] [ValidateNotNullOrEmpty()] [switch]$All, # Computername of the MDATP managed device [Parameter(Mandatory=$false, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$false, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # MDATP investigation id [Parameter(Mandatory=$false, ParameterSetName='id')] [ValidateNotNullOrEmpty()] [String]$Id, # Investigation state [Parameter(Mandatory=$false)] [ValidateSet( 'Unknown','Terminated','SuccessfullyRemediated','Benign','Failed','PartiallyRemediated','Running','PendingApproval','PendingResource','PartiallyInvestigated','TerminatedByUser','TerminatedBySystem','Queued','InnerFailure','PreexistingAlert','UnsupportedOs','UnsupportedAlertType','SuppressedAlert')] [String]$State, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API access configuration If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ If ($DeviceName){ $MachineAPI = "https://api.securitycenter.windows.com/api/machines" $DeviceName = $DeviceName.ToLower() $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) $ActionDevice = @($machines.value | Select-Object -Property * | Where-Object {$_.computerDnsName -like "$DeviceName"}) If($ActionDevice.count -gt 1){ Write-Error "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id } Elseif($ActionDevice.count -eq 0){ Write-Error "No device records found that match DeviceName $DeviceName" } Elseif ($ActionDevice.count -eq 1){ Write-Verbose "$($ActionDevice.CompueterDnsName) found with id $($ActionDevice.id)" $DeviceID = $ActionDevice.id } } if($DeviceID){ $MachineAPI = "https://api.securitycenter.windows.com/api/machines/$DeviceID" $Machine = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If($Machine.Count -eq 1){ $DeviceName = $Machine.ComputerDnsName } Else{ Write-Error "No device records found that match DeviceID $DeviceID" } } # Get Investigation data $InvestigationUri= "https://api-us.securitycenter.windows.com/api/investigations/" if($PSBoundParameters.ContainsKey("All")){ $InvestigationUri= "https://api-us.securitycenter.windows.com/api/investigations/" } Else{ If($DeviceName){ $InvestigationUri = $InvestigationUri + "?`$filter=" $InvestigationUri = $InvestigationUri + "machineId+eq+'$DeviceID'" } If($State){ If($DeviceName){ $InvestigationUri = $InvestigationUri + "and state+eq+'$State'" } Else{ $InvestigationUri = $InvestigationUri + "?`$filter=" $InvestigationUri = $InvestigationUri + "state+eq+'$State'" } } # Search by Investigation ID if($id){ $InvestigationUri = $InvestigationUri + "$id" } } # Retrieve MDATP Investigations data Try{ $output = @(Invoke-RestMethod -Uri $InvestigationUri -Headers $Headers -Method Get -Verbose -ContentType application/json) } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error retrieving MDATP inestigation data [$errorMessage]" } # Handle the output If($id){ $output } Else{ $output.value } } End{} } function Get-MDATPQuery{ <# .Synopsis Get-MDATPQuery .DESCRIPTION Get-MDATPQuery executes MDATP advanced hunting queries through the Microsoft Defender Advanced Threat Protection Alerts Rest API. Limitations 1. You can only run a query on data from the last 30 days. 2. The results will include a maximum of 100,000 rows. 3. The number of executions is limited per tenant: up to 15 calls per minute, 15 minutes of running time every hour and 4 hours of running time a day. 4. The maximal execution time of a single request is 10 minutes. .PARAMETER Schema The Schema to use for the query .PARAMETER DeviceName Computername of the device.If no DeviceName is provided all devices are querried .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Get-MDATPQuery -Schema DeviceLogonEvents -DeviceName TestClient4 The above query retrieves all logon events for the specified device .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 17.02.2020 Purpose/Change: Initial script development #> [CmdletBinding()] Param ( # The MDATP Schema to search for [Parameter(Mandatory=$true)] [ValidateSet('DeviceAlertEvents','DeviceInfo','DeviceNetworkInfo','DeviceProcessEvents','DeviceFileEvents','DeviceRegistryEvents','DeviceLogonEvents','DeviceImageLoadEvents','DeviceEvents')] [String]$Schema, # Computername of the MDATP managed device [Parameter(Mandatory=$false)] [String]$DeviceName, # The Time Range [Parameter(Mandatory=$false)] [ValidateSet('1h', '12h', '1d','7d','30d')] [String]$TimeRange, # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ #WDATP API $uri = "https://api.securitycenter.windows.com/api/advancedqueries/run" # Define devices to include in query if ($DeviceName){ $DeviceName = $DeviceName.ToLower() $ExecQuery = "$Schema | where DeviceName == '$DeviceName'" } Else{ $ExecQuery = "$Schema" } $DeviceTarget = if([string]::IsNullOrEmpty($DeviceName)) {"All Devices"}Else {"$DeviceName"} If ($TimeRange){ $ExecQuery = $ExecQuery + "|where Timestamp > ago($($TimeRange))" } Try{ $body = ConvertTo-Json -InputObject @{ 'Query' = $ExecQuery} $webResponse = @(Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body) $response = $webResponse | ConvertFrom-Json $results = $response.Results $results } Catch{ $errorMessage = $_.Exception.Message Write-Error "Error running advanced hunting query [$errorMessage]" } } End{ Write-Verbose "Schema: $Schema" Write-Verbose "Device: $DeviceTarget" Write-Verbose "Query: $ExecQuery" Write-Verbose "Retrieved $($results.count) records" } } function Remove-MDATPDevice{ <# .Synopsis Remove-MDATPDevice .DESCRIPTION Remove-MDATPDevice offboards a device from MDATP and adds a tag 'Offboarded' to the device. .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER OffboardReason Comment to be added to the offboard action, when no value is specified a default comment 'Offobard machine by automation' is added .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Remove-MDATPDevice -DeviceName Computer02 This command offboards device Computer02 from MDATP .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 14.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Offboard reason [Parameter(Mandatory=$false)] [String]$OffboardReason = "Offobard machine by automation", # API Configuration [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" $OffboardingStatus = $false # change the devicename to lowercase $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id # set offboarding comment $OffboardReasonInput = @{"Comment" = "$OffboardReason"} | ConvertTo-Json if ($pscmdlet.ShouldProcess("$DeviceName", "offobarding device from MDATP")){ $Offboarduri = "$MachineAPI/$MDATPDeviceID/offboard" Try{ $OffboardAction =Invoke-WebRequest -Uri $Offboarduri -Headers $Headers -Method Post -Body $OffboardReasonInput If ($OffboardAction.StatusCode -eq 201){ Write-Verbose "Offboarding device $DeviceName completed successfully" # Tag machine $offboardTag = @{"Value" = "Offboarded"; "Action"= "Add"} | ConvertTo-Json $Taguri = "$MachineAPI/$MDATPDeviceID/tags" Invoke-WebRequest -Uri $Taguri -Headers $Headers -Method Post -Body $offboardTag $OffboardingStatus = $true # end tag machine $True } Else{ Write-Warning "Offboarding device $DeviceName failed!" Write-Error "StatusCode: $($OffboardAction.StatusCode)" $OffboardingStatus = $false } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Reason: $OffboardReason" Write-Verbose "Offboardingstatus: $OffboardingStatus" Write-Verbose "StatusCode: $($response.statuscode)" Write-Verbose "StatusDescription: $($response.StatusDescription)" } } function Remove-MDATPDeviceTag{ <# .Synopsis Remove-MDATPDeviceTag .Description Remove-MDATPDeviceTag removes the specified Tag to the MDATP device. .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Tag The value of the tag to be removed .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Remove-MDATPDeviceTag -DeviceName computer02 -Tag 'Testing' -verbose This command removes the tag 'testing' from device 'computer02' .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 16.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Tag to be removed from the device [Parameter(Mandatory=$true)] [String]$Tag, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" # change the devicename to lowercase $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Remvoing tag: $Tag")){ Try{ # Tag machine $AddTag = @{"Value" = "$Tag"; "Action"= "Remove"} | ConvertTo-Json $Taguri = "$MachineAPI/$MDATPDeviceID/tags" $response =Invoke-WebRequest -Uri $Taguri -Headers $Headers -Method Post -Body $AddTag # end tag machine If ($response.StatusCode -eq 200){ Write-Verbose "Tag: $Tag was successfully removed from device $DeviceName" $True } Else{ Write-Warning "Removing tag $Tag from device $DeviceName failed!" Write-Error "StatusCode: $($response.StatusCode)" $false } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Removed tag: $Tag" Write-Verbose "StatusCode: $($response.statuscode)" Write-Verbose "StatusDescription: $($response.StatusDescription)" } } function Start-MDATPAppRestriction{ <# .Synopsis Start-MDATPAppRestriction .DESCRIPTION Start-MDATPAppRestriction restricts execution of all applications on the machine. .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Start-MDATPAppRestriction -DeviceName computer02 -Comment "incident1973" This command restricts application execution on device computer02 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } # change the devicename to lowercase $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start Isolation: $IsolationType")){ Try{ $AppRestrictionInput = @{"Comment" = "$Comment"} | ConvertTo-Json $AppRestrictionUri = "$MachineAPI/$MDATPDeviceID/restrictCodeExecution " $AppRestrictionResponse =Invoke-WebRequest -Uri $AppRestrictionUri -Headers $Headers -Method Post -Body $AppRestrictionInput If ($AppRestrictionResponse.StatusCode -eq 201){ $ActionID = $AppRestrictionResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "App restriction was successfully initiated for device $DeviceName -ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating app restriction for device $DeviceName failed!" Write-Error "StatusCode: $($AppRestrictionResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($IsolateResponse.statuscode)" Write-Verbose "StatusDescription: $($IsolateResponse.StatusDescription)" } } function Start-MDATPAVScan{ <# .Synopsis Start-MDATPAVScan .DESCRIPTION Start-MDATPAVScan initiates an Antivirus scan on the specified device .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Scantype The type of scan to perform, Full or Quick .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Start-MDATPAVScan -DeviceName testclient6 -ScanType Quick -Comment "better check" This command starts a quck AV scan on device testclient6 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 17.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # ScanType controls the type of scan to perform [Parameter(Mandatory=$true)] [ValidateSet('Quick','Full')] [String]$ScanType, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start AV Scan: $ScanType")){ Try{ # DefineScanType $ScanTypeInput = @{"ScanType" = "$ScanType"; "Comment"= "$Comment"} | ConvertTo-Json $ScanUri = "$MachineAPI/$MDATPDeviceID/runAntiVirusScan" $ScanResponse =Invoke-WebRequest -Uri $ScanUri -Headers $Headers -Method Post -Body $ScanTypeInput # end tag machine If ($ScanResponse.StatusCode -eq 201){ $ActionID = $ScanResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "$ScanType scan was successfully initiated for device $DeviceName" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating $ScanType scan for device $DeviceName failed!" Write-Error "StatusCode: $($ScanResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "ScanType: $ScanType" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($ScanResponse.statuscode)" Write-Verbose "StatusDescription: $($ScanResponse.StatusDescription)" } } function Start-MDATPInvestigation{ <# .Synopsis Start-MDATPInvestigation .DESCRIPTION Start-MDATPInvestigation initiates an automated investigation on the targeted device .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. Comment to associate with the action .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Start-MDATPInvestigation -DeviceName computer02 -Comment "incident1973" This command starts an automated investigation on device computer02 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 17.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ # MDATP API URI $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start automated investigation")){ Try{ $InvestigationInput = @{"Comment" = "$Comment"} | ConvertTo-Json $InvestigationUri = "$MachineAPI/$MDATPDeviceID/startInvestigation" $InvestigationResponse = Invoke-WebRequest -Uri $InvestigationUri -Headers $Headers -Method Post -Body $InvestigationInput If ($InvestigationResponse.StatusCode -eq 201){ $ActionID = $InvestigationResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "An automated investigation was successfully initiated for device $DeviceName -ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating automated investigation for device $DeviceName failed!" Write-Error "StatusCode: $($InvestigationResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($InvestigationResponse.statuscode)" Write-Verbose "StatusDescription: $($InvestigationResponse.StatusDescription)" } } function Start-MDATPInvestigationPackageCollection{ <# .Synopsis Start-MDATPInvestigationPackageCollection .Description Start-MDATPInvestigationPackageCollection initiates the collection of an investigation package .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Start-MDATPInvestigationPackageCollection -DeviceName computer02 This command starts the collection of the investigation package on device computer02 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 17.03.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start investigation package collection")){ Try{ Write-Verbose "Device: $DeviceName Id:$MDATPDeviceID" $CollectInput = @{"Comment" = "$Comment"} | ConvertTo-Json $CollectUri = "$MachineAPI/$MDATPDeviceID/collectInvestigationPackage" $CollectResponse =Invoke-WebRequest -Uri $CollectUri -Headers $Headers -Method Post -Body $CollectInput # end tag machine If ($CollectResponse.StatusCode -eq 201){ $ActionID = $CollectResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "Investigation package collection was successfully initiated for device $DeviceName - ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating investigation pacakge collection for device $DeviceName failed!" Write-Error "StatusCode: $($CollectResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Action: Collection Investigation Package" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($response.statuscode)" Write-Verbose "StatusDescription: $($CollectResponse.StatusDescription)" } } function Start-MDATPIsolation{ <# .Synopsis Start-MDATPIsolation .DESCRIPTION Start-MDATPIsolation initiates the isolation of the specified device from the network .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER IsolationType Type of the isolation. Allowed values are: 'Full' or 'Selective'. .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Start-MDATPIsolation -DeviceName computer02 -IsolationType Full -Comment "incident1973" This command isolates device computer02 from the network .EXAMPLE Start-MDATPIsolation -DeviceName computer02 -IsolationType Selective -Comment "incident1973" This command isolates device computer02 from the network but allows communication through Outlook and Skype .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # IsolationType controls the type of isolation to perform [Parameter(Mandatory=$true)] [ValidateSet('Full','Selective')] [String]$IsolationType, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start Isolation: $IsolationType")){ Try{ $IsolationTypeInput = @{"IsolationType" = "$IsolationType"; "Comment"= "$Comment"} | ConvertTo-Json $IsolateUri = "$MachineAPI/$MDATPDeviceID/isolate" $IsolateResponse =Invoke-WebRequest -Uri $IsolateUri -Headers $Headers -Method Post -Body $IsolationTypeInput If ($IsolateResponse.StatusCode -eq 201){ $ActionID = $IsolateResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "$IsolationType isolation was successfully initiated for device $DeviceName -ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating $IsolationType isolation for device $DeviceName failed!" Write-Error "StatusCode: $($IsolateResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "IsolationType: $IsolationType" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($IsolateResponse.statuscode)" Write-Verbose "StatusDescription: $($IsolateResponse.StatusDescription)" } } function Stop-MDATPAppRestriction{ <# .Synopsis Stop-MDATPAppRestriction .DESCRIPTION Stop-MDATPAppRestriction removes app execution restrictions on the machine. .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Stop-MDATPAppRestriction -DeviceName computer02 -Comment "incident1973" This command removes app execution restrictions from device computer02 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Start Isolation: $IsolationType")){ Try{ $UnAppRestrictionInput = @{"Comment" = "$Comment"} | ConvertTo-Json $UnAppRestrictionUri = "$MachineAPI/$MDATPDeviceID/unrestrictCodeExecution " $UnAppRestrictionResponse =Invoke-WebRequest -Uri $UnAppRestrictionUri -Headers $Headers -Method Post -Body $UnAppRestrictionInput If ($UnAppRestrictionResponse.StatusCode -eq 201){ $ActionID = $UnAppRestrictionResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "Remove App restriction was successfully initiated for device $DeviceName -ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Initiating app restriction for device $DeviceName failed!" Write-Error "StatusCode: $($UnAppRestrictionResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($IsolateResponse.statuscode)" Write-Verbose "StatusDescription: $($IsolateResponse.StatusDescription)" } } function Stop-MDATPIsolation{ <# .Synopsis Stop-MDATPIsolation .DESCRIPTION Stop-MDATPIsolation removes network isolation for the specified device .PARAMETER DeviceName Computername of the device .PARAMETER DeviceID The unique device ID of the device .PARAMETER Comment Comment that is added to the request, if no comment is provided the default commment 'submitted by automation' is used. .PARAMETER MTPConfigFile The MTPConfigFile contains the API connection information, if not specified a default PoshMTPconfig.json is used that must be located in the module folder .EXAMPLE Stop-MDATPIsolation -DeviceName computer02 -Comment "incident1973" This command removes network isolation for device computer02 .NOTES Version: 1.0 Author: Alex Verboon Creation Date: 12.04.2020 Purpose/Change: Initial script development #> [CmdletBinding(SupportsShouldProcess)] Param( # Computername of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceName')] [ValidateNotNullOrEmpty()] [String]$DeviceName, # Unique device id of the MDATP managed device [Parameter(Mandatory=$true, ParameterSetName='DeviceID')] [ValidateNotNullOrEmpty()] [String]$DeviceID, # Comment for the request [Parameter(Mandatory=$false)] [String]$Comment, # API Configuration file [Parameter(Mandatory=$false)] [String]$MTPConfigFile ) Begin{ # Begin Get API Information If ($MTPConfigFile){ $PoshMTPconfigFilePath = $MTPConfigFile Write-Verbose "MTP ConfigFile parameter: $PoshMTPconfigFilePath" } Else{ # If no configfile is defined we use a defined lcoation .\Config\PoshMTPconfig.json $ConfigFileDir = [IO.Directory]::GetParent($PSScriptRoot) $PoshMTPconfigFilePath = "$ConfigFileDir\" + "PoshMTPconfig.json" Write-Verbose "MTP ConfigFile static: $PoshMTPconfigFilePath" } Write-Verbose "Checking for $PoshMTPconfigFilePath" If (Test-Path -Path $PoshMTPconfigFilePath -PathType Leaf){ $ConfigSettings = @(Get-Content -Path "$PoshMTPconfigFilePath" | ConvertFrom-Json) $OAuthUri = $ConfigSettings.API_MDATP.OAuthUri $ClientID = $ConfigSettings.API_MDATP.ClientID $ClientSecret = $ConfigSettings.API_MDATP.ClientSecret } Else{ Write-Error "$PoshMTPconfigFilePath not found" Break } # End Get API Information # Connect with MDATP API [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $Body = @{ resource = "https://api.securitycenter.windows.com" client_id = $ClientID client_secret = $ClientSecret grant_type = 'client_credentials' redirectUri = "https://localhost:8000" } $Response = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body #$Authorization = Invoke-RestMethod -Method Post -Uri $OAuthUri -Body $Body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing #$access_token = $Authorization.access_token $headers = @{ 'Content-Type' = 'application/json' Accept = 'application/json' Authorization = "Bearer $($Response.access_token)" } } Process{ $MDATP_API_URI = "https://api.securitycenter.windows.com/api" If([string]::IsNullOrEmpty($Comment)){ $Comment = "submitted by automation" } $DeviceName = $DeviceName.ToLower() # Get the MDATP devices $MachineAPI = "$MDATP_API_URI/machines" $Machines = @(Invoke-RestMethod -Uri "$MachineAPI" -Headers $Headers -Method Get -Verbose -ContentType application/json) If ($DeviceName){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.computerDnsName -like "$DeviceName"}) } Elseif ($DeviceID){ $ActionDevice = @($machines.value | Select-Object * | Where-Object {$_.id -like "$DeviceID"}) } If($ActionDevice.count -gt 1){ Write-Warning "There are multiple device records with this computername, please specify the MDATP device id" $ActionDevice | Select-Object computerDnsName, id Break } Elseif($ActionDevice.count -eq 0){ Write-Warning "No device records found that match DeviceName $DeviceName" Break } Elseif($ActionDevice.count -eq 1){ $MDATPDeviceID = $ActionDevice.id if ($pscmdlet.ShouldProcess("$DeviceName", "Stop Isolation")){ Try{ $UnIsolationInput = @{"Comment" = "$Comment"} | ConvertTo-Json $UnIsolateUri = "$MachineAPI/$MDATPDeviceID/unisolate " $UnIsolateResponse =Invoke-WebRequest -Uri $UnIsolateUri -Headers $Headers -Method Post -Body $UnIsolationInput If ($UnIsolateResponse.StatusCode -eq 201){ $ActionID = $UnIsolateResponse.content | ConvertFrom-Json | Select-Object -ExpandProperty id Write-Verbose "Remove isolation was successfully initiated for device $DeviceName -ActionID: $ActionID" $ActionID } Else{ $ActionID = "0000000-0000-0000-0000-000000000000" Write-Warning "Removing isolation for device $DeviceName failed!" Write-Error "StatusCode: $($UnIsolateResponse.StatusCode)" $ActionID } } Catch{ $ex = $_.Exception $errorResponse = $ex.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($errorResponse) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); Write-Verbose "Response content:`n$responseBody" Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" $ActionID = "0000000-0000-0000-0000-000000000000" $ActionID } } } } End{ Write-Verbose "Device: $DeviceName" Write-Verbose "DeviceID: $MDATPDeviceID" Write-Verbose "Comment: $Comment" Write-Verbose "ActionID: $($ActionID)" Write-Verbose "StatusCode: $($UnIsolateResponse.statuscode)" Write-Verbose "StatusDescription: $($UnIsolateResponse.StatusDescription)" } } |