Public/policy-ioa-exclusions.ps1

function ConvertTo-FalconIoaExclusion {
<#
.SYNOPSIS
Output required fields to create an Indicator of Attack exclusion from a Falcon detection
.DESCRIPTION
Uses the 'behaviors' and 'device' properties of a detection to generate the necessary fields to create a new
Indicator of Attack exclusion. Specfically, it maps the following properties these fields:
 
behaviors.behavior_id > pattern_id
behaviors.display_name > pattern_name
behaviors.cmdline > cl_regex
behaviors.filepath > ifn_regex
device.groups > groups
 
The 'cl_regex' and 'ifn_regex' fields are escaped using the [regex]::Escape() PowerShell accelerator. The
'ifn_regex' output also replaces the NT device path ('Device/HarddiskVolume') with a wildcard.
 
If the detection involves a device that is not in any groups, it uses 'all' to target all host groups.
 
The resulting output can be passed to 'New-FalconIoaExclusion' to create an exclusion.
.PARAMETER Detection
Falcon detection content, including 'behaviors' and 'device'
.LINK
https://github.com/crowdstrike/psfalcon/wiki/ConvertTo-FalconIoaExclusion
#>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory,ValueFromPipeline,Position=1)]
        [object]$Detection
    )
    begin { [System.Collections.Generic.List[PSCustomObject]]$Output = @() }
    process {
        if ($Detection.behaviors -and $Detection.device) {
            @($Detection.behaviors).Where({ $_.tactic -notmatch '^(Machine Learning|Malware)$' }).foreach{
                $Output.Add(([PSCustomObject]@{
                    pattern_id = $_.behavior_id
                    pattern_name = $_.display_name
                    cl_regex = [regex]::Escape($_.cmdline) -replace '(\\ {1,})+','\s+'
                    ifn_regex = [regex]::Escape($_.filepath) -replace '\\\\Device\\\\HarddiskVolume\d+','.*'
                    groups = if ($Detection.device.groups) { $Detection.device.groups } else { 'all' }
                    comment = "Created from $($Detection.detection_id) by $((Show-FalconModule).UserAgent)."
                }))
            }
        } else {
            foreach ($Property in @('behaviors','device')) {
                if (!$Detection.$Property) {
                    throw "[ConvertTo-FalconMlExclusion] Missing required '$Property' property."
                }
            }
        }
    }
    end { if ($Output) { @($Output | Group-Object pattern_id).foreach{ $_.Group | Select-Object -First 1 }}}
}
function Edit-FalconIoaExclusion {
<#
.SYNOPSIS
Modify an Indicator of Attack exclusion
.DESCRIPTION
Requires 'IOA Exclusions: Write'.
.PARAMETER Name
Exclusion name
.PARAMETER ClRegex
Command line RegEx
.PARAMETER IfnRegex
Image Filename RegEx
.PARAMETER GroupId
Host group identifier or 'all' to apply to all hosts
.PARAMETER Description
Exclusion description
.PARAMETER Comment
Audit log comment
.PARAMETER PatternId
Indicator of Attack pattern identifier
.PARAMETER PatternName
Indicator of Attack pattern name
.PARAMETER Id
Exclusion identifier
.LINK
https://github.com/crowdstrike/psfalcon/wiki/Edit-FalconIoaExclusion
#>

    [CmdletBinding(DefaultParameterSetName='/policy/entities/ioa-exclusions/v1:patch',SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=1)]
        [string]$Name,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=2)]
        [Alias('cl_regex')]
        [string]$ClRegex,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=3)]
        [Alias('ifn_regex')]
        [string]$IfnRegex,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=4)]
        [Alias('groups','GroupIds')]
        [object[]]$GroupId,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=5)]
        [string]$Description,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=6)]
        [string]$Comment,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=7)]
        [Alias('pattern_id')]
        [string]$PatternId,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',ValueFromPipelineByPropertyName,
            Position=8)]
        [Alias('pattern_name')]
        [string]$PatternName,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:patch',Mandatory,
            ValueFromPipelineByPropertyName,ValueFromPipeline)]
        [ValidatePattern('^([a-fA-F0-9]{32}|all)$')]
        [string]$Id
    )
    begin {
        $Param = @{
            Command = $MyInvocation.MyCommand.Name
            Endpoint = $PSCmdlet.ParameterSetName
            Format = @{
                Body = @{
                    root = @('cl_regex','ifn_regex','groups','name','id','description','comment','pattern_id',
                        'pattern_name')
                }
            }
        }
    }
    process {
        if ($PSCmdlet.ShouldProcess('Edit-FalconIoaExclusion','Test-GroupId')) {
            if ($PSBoundParameters.GroupId) {
                if ($PSBoundParameters.GroupId.id) {
                    # Filter to 'id' if supplied with 'detailed' objects
                    [string[]]$PSBoundParameters.GroupId = $PSBoundParameters.GroupId.id
                }
                @($PSBoundParameters.GroupId).foreach{
                    if ($_ -notmatch '^([a-fA-F0-9]{32}|all)$') {
                        throw "'$_' is not a valid Host Group identifier."
                    }
                }
            }
        }
        Invoke-Falcon @Param -Inputs $PSBoundParameters
    }
}
function Get-FalconIoaExclusion {
<#
.SYNOPSIS
Search for Indicator of Attack exclusions
.DESCRIPTION
Requires 'IOA Exclusions: Read'.
.PARAMETER Id
Exclusion identifier
.PARAMETER Filter
Falcon Query Language expression to limit results
.PARAMETER Sort
Property and direction to sort results
.PARAMETER Limit
Maximum number of results per request
.PARAMETER Offset
Position to begin retrieving results
.PARAMETER Detailed
Retrieve detailed information
.PARAMETER All
Repeat requests until all available results are retrieved
.PARAMETER Total
Display total result count instead of results
.LINK
https://github.com/crowdstrike/psfalcon/wiki/Get-FalconIoaExclusion
#>

    [CmdletBinding(DefaultParameterSetName='/policy/queries/ioa-exclusions/v1:get',SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:get',Mandatory,
            ValueFromPipelineByPropertyName,ValueFromPipeline)]
        [ValidatePattern('^[a-fA-F0-9]{32}$')]
        [Alias('Ids')]
        [string[]]$Id,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get',Position=1)]
        [ValidateScript({ Test-FqlStatement $_ })]
        [string]$Filter,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get',Position=2)]
        [ValidateSet('applied_globally.asc','applied_globally.desc','created_by.asc','created_by.desc',
            'created_on.asc','created_on.desc','last_modified.asc','last_modified.desc','modified_by.asc',
            'modified_by.desc','name.asc','name.desc','pattern_id.asc','pattern_id.desc','pattern_name.asc',
            'pattern_name.desc',IgnoreCase=$false)]
        [string]$Sort,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get',Position=3)]
        [ValidateRange(1,500)]
        [int32]$Limit,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get')]
        [int32]$Offset,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get')]
        [switch]$Detailed,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get')]
        [switch]$All,
        [Parameter(ParameterSetName='/policy/queries/ioa-exclusions/v1:get')]
        [switch]$Total
    )
    begin {
        $Param = @{
            Command = $MyInvocation.MyCommand.Name
            Endpoint = $PSCmdlet.ParameterSetName
            Format = @{ Query = @('sort','ids','offset','filter','limit') }
        }
        [System.Collections.Generic.List[string]]$List = @()
    }
    process { if ($Id) { @($Id).foreach{ $List.Add($_) }}}
    end {
        if ($List) { $PSBoundParameters['Id'] = @($List | Select-Object -Unique) }
        Invoke-Falcon @Param -Inputs $PSBoundParameters
    }
}
function New-FalconIoaExclusion {
<#
.SYNOPSIS
Create an Indicator of Attack exclusion
.DESCRIPTION
'ConvertTo-FalconIoaExclusion' can be used to generate the required Indicator of Attack exclusion properties
using an existing detection.
 
Requires 'IOA Exclusions: Write'.
.PARAMETER Name
Exclusion name
.PARAMETER PatternId
Indicator of Attack pattern identifier
.PARAMETER PatternName
Indicator of Attack pattern name
.PARAMETER ClRegex
Command line RegEx
.PARAMETER IfnRegex
Image Filename RegEx
.PARAMETER GroupId
Host group identifier, or leave undefined to apply to all hosts
.PARAMETER Description
Exclusion description
.PARAMETER Comment
Audit log comment
.LINK
https://github.com/crowdstrike/psfalcon/wiki/New-FalconIoaExclusion
#>

    [CmdletBinding(DefaultParameterSetName='/policy/entities/ioa-exclusions/v1:post',SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',Mandatory,
            ValueFromPipelineByPropertyName,Position=1)]
        [string]$Name,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',Mandatory,
            ValueFromPipelineByPropertyName,Position=2)]
        [ValidatePattern('^\d+$')]
        [Alias('pattern_id')]
        [string]$PatternId,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',Mandatory,
            ValueFromPipelineByPropertyName,Position=3)]
        [Alias('pattern_name')]
        [string]$PatternName,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',Mandatory,
            ValueFromPipelineByPropertyName,Position=4)]
        [Alias('cl_regex')]
        [string]$ClRegex,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',Mandatory,
            ValueFromPipelineByPropertyName,Position=5)]
        [Alias('ifn_regex')]
        [string]$IfnRegex,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',ValueFromPipelineByPropertyName,
            Position=7)]
        [Alias('groups','GroupIds')]
        [object[]]$GroupId,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',ValueFromPipelineByPropertyName,
            Position=8)]
        [string]$Description,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:post',ValueFromPipelineByPropertyName,
            Position=9)]
        [string]$Comment
    )
    begin {
        $Param = @{
            Command = $MyInvocation.MyCommand.Name
            Endpoint = $PSCmdlet.ParameterSetName
            Format = @{
                Body = @{
                    root = @('cl_regex','ifn_regex','groups','name','pattern_id','pattern_name',
                        'description','comment')
                }
            }
        }
    }
    process {
        if ($PSBoundParameters.GroupId.id) {
            # Filter to 'id' if supplied with 'detailed' objects
            [string[]]$PSBoundParameters.GroupId = $PSBoundParameters.GroupId.id
        }
        if ($PSBoundParameters.GroupId -eq 'all') {
            # Remove 'all' from 'GroupId', and remove 'GroupId' if 'all' was the only value
            $PSBoundParameters.GroupId = @($PSBoundParameters.GroupId).Where({ $_ -ne 'all' })
            if ([string]::IsNullOrEmpty($PSBoundParameters.GroupId)) { [void]$PSBoundParameters.Remove('GroupId') }
        }
        if ($PSBoundParameters.GroupId) {
            @($PSBoundParameters.GroupId).foreach{
                if ($_ -notmatch '^[a-fA-F0-9]{32}$') { throw "'$_' is not a valid Host Group identifier." }
            }
        }
        Invoke-Falcon @Param -Inputs $PSBoundParameters
    }
}
function Remove-FalconIoaExclusion {
<#
.SYNOPSIS
Remove Indicator of Attack exclusions
.DESCRIPTION
Requires 'IOA Exclusions: Write'.
.PARAMETER Comment
Audit log comment
.PARAMETER Id
Exclusion identifier
.LINK
https://github.com/crowdstrike/psfalcon/wiki/Remove-FalconIoaExclusion
#>

    [CmdletBinding(DefaultParameterSetName='/policy/entities/ioa-exclusions/v1:delete',SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:delete',Position=1)]
        [string]$Comment,
        [Parameter(ParameterSetName='/policy/entities/ioa-exclusions/v1:delete',Mandatory,
            ValueFromPipelineByPropertyName,ValueFromPipeline,Position=2)]
        [ValidatePattern('^[a-fA-F0-9]{32}$')]
        [Alias('Ids')]
        [string[]]$Id
    )
    begin {
        $Param = @{
            Command = $MyInvocation.MyCommand.Name
            Endpoint = $PSCmdlet.ParameterSetName
            Format = @{ Query = @('ids','comment') }
        }
        [System.Collections.Generic.List[string]]$List = @()
    }
    process { if ($Id) { @($Id).foreach{ $List.Add($_) }}}
    end {
        if ($List) {
            $PSBoundParameters['Id'] = @($List | Select-Object -Unique)
            Invoke-Falcon @Param -Inputs $PSBoundParameters
        }
    }
}