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)"
    }
}