public/psf-sensors.ps1
function Add-FalconSensorTag { <# .SYNOPSIS Use Real-time Response to add FalconSensorTags to hosts .DESCRIPTION Provided FalconSensorTag values will be appended to any existing tags. Requires 'Hosts: Read', 'Sensor update policies: Write' and 'Real time response (admin): Write'. .PARAMETER Tag FalconSensorTag value ['FalconSensorTags/<string>'] .PARAMETER QueueOffline Add command request to the offline queue .PARAMETER Id Host identifier .LINK https://github.com/crowdstrike/psfalcon/wiki/Add-FalconSensorTag #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory,Position=1)] [ValidateScript({ @($_).foreach{ if ((Test-RegexValue $_) -eq 'tag') { $true } else { throw "Valid values include letters numbers, hyphens, unscores and forward slashes. ['$_']" } } })] [Alias('Tags')] [string[]]$Tag, [Parameter(Position=2)] [boolean]$QueueOffline, [Parameter(Mandatory,ValueFromPipelineByPropertyName,ValueFromPipeline,Position=3)] [ValidatePattern('^[a-fA-F0-9]{32}$')] [Alias('Ids','device_id','host_ids','aid')] [string[]]$Id ) begin { [string]$ScriptPath = Join-Path (Show-FalconModule).ModulePath 'script' [System.Collections.Generic.List[string]]$List = @() } process { if ($Id) { @($Id).foreach{ $List.Add($_) }}} end { if ($List) { [string[]]$Id = @($List | Select-Object -Unique) [string[]]$Tag = $Tag -replace 'SensorGroupingTags/',$null [string]$UserAgent = (Show-FalconModule).UserAgent try { # Get device info to determine script and begin session $HostList = Get-FalconHost -Id $Id | Select-Object cid,device_id,platform_name,device_policies,tags foreach ($Platform in (($HostList.platform_name | Group-Object).Name | Where-Object { @('Linux','Mac', 'Windows') -contains $_ })) { # Start sessions for each 'platform' type if ($Platform -eq 'Windows') { foreach ($i in ($HostList | Where-Object { $_.platform_name -eq $Platform })) { # Check 'tags' for existing values [boolean]$TagMatch = $false [string[]]$Existing = ($i.tags | Where-Object { $_ -match 'SensorGroupingTags/' }) -replace 'SensorGroupingTags/',$null @($Tag).foreach{ if ($TagMatch -eq $false -and $Existing -notcontains $_) { $TagMatch = $true } } if ($TagMatch -eq $true) { [string]$Script = Get-Content (Join-Path $ScriptPath 'add_sensortag.ps1') -Raw [string]$TagString = (@($Existing + $Tag) | Select-Object -Unique) -join ',' [string]$CmdLine = if ($i.device_policies.sensor_update.uninstall_protection -eq 'ENABLED') { '-Tag',$TagString,'-Token',($i.device_id | Get-FalconUninstallToken -AuditMessage ( 'Add-FalconSensorTag',"[$UserAgent]" -join ' ')).uninstall_token -join ' ' } else { '-Tag',$TagString -join ' ' } $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}``` -CommandLine=```{1}```' -f $Script,$CmdLine HostId = $i.device_id QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } Invoke-FalconRtr @Param | Select-Object aid,stdout,stderr,errors | ForEach-Object { # Output device properties and 'tags' value after script [PSCustomObject]@{ cid = $i.cid device_id = $_.aid tags = if ($_.stdout) { $Result = ($_.stdout).Trim() if ($Result -match 'Maintenance Token>') { $TagString } else { $Result } } elseif ($_.stderr) { $_.stderr } else { $_.errors } } } } else { # Output device properties and 'tags' value when no changes required [PSCustomObject]@{ cid = $i.cid device_id = $i.device_id tags = $Existing -join ',' } } } } else { [string]$Filename = if ($Platform -eq 'Linux') { 'add_sensortag.sh' } else { 'add_sensortag.zsh' } [string]$Script = Get-Content (Join-Path $ScriptPath $Filename) -Raw $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}``` -CommandLine=```{1}```' -f $Script,($Tag -join ',') HostId = ($HostList | Where-Object { $_.platform_name -eq $Platform }).device_id QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } Invoke-FalconRtr @Param | Select-Object aid,stdout,stderr,errors | ForEach-Object { # Output device properties and 'tags' value [PSCustomObject]@{ cid = ($HostList | Where-Object device_id -eq $_.aid).cid device_id = $_.aid tags = if ($_.stdout) { ($_.stdout).Trim() } elseif ($_.stderr) { $_.stderr } else { $_.errors } } } } } } catch { throw $_ } } } } function Get-FalconSensorTag { <# .SYNOPSIS Use Real-time Response to display FalconSensorTags assigned to hosts .DESCRIPTION Requires 'Hosts: Read' and 'Real time response (admin): Write'. .PARAMETER QueueOffline Add command request to the offline queue .PARAMETER Id Host identifier .LINK https://github.com/crowdstrike/psfalcon/wiki/Get-FalconSensorTag #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position=1)] [boolean]$QueueOffline, [Parameter(Mandatory,ValueFromPipelineByPropertyName,ValueFromPipeline,Position=2)] [ValidatePattern('^[a-fA-F0-9]{32}$')] [Alias('Ids','device_id','host_ids','aid')] [string[]]$Id ) begin { [string]$ScriptPath = Join-Path (Show-FalconModule).ModulePath 'script' [System.Collections.Generic.List[string]]$List = @() } process { if ($Id) { @($Id).foreach{ $List.Add($_) }}} end { if ($List) { [string[]]$Id = @($List | Select-Object -Unique) try { # Get device info to determine script and begin session $HostList = Get-FalconHost -Id $Id | Select-Object cid,device_id,platform_name,tags foreach ($Platform in (($HostList.platform_name | Group-Object).Name | Where-Object { @('Linux','Mac', 'Windows') -contains $_ })) { # Start sessions for each 'platform' type if ($Platform -eq 'Windows') { foreach ($i in ($HostList | Where-Object { $_.platform_name -eq $Platform })) { # Use devices API to return tag values [PSCustomObject]@{ cid = $i.cid device_id = $i.device_id tags = ($i.tags | Where-Object { $_ -match 'SensorGroupingTags/' }) -replace 'SensorGroupingTags/',$null -join ',' } } } else { [string]$Filename = if ($Platform -eq 'Linux') { 'get_sensortag.sh' } else { 'get_sensortag.zsh' } [string]$Script = Get-Content (Join-Path $ScriptPath $Filename) -Raw $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}```' -f $Script HostId = ($HostList | Where-Object { $_.platform_name -eq $Platform }).device_id QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } Invoke-FalconRtr @Param | Select-Object aid,stdout,stderr,errors | ForEach-Object { # Output device properties and 'tags' value [PSCustomObject]@{ cid = ($HostList | Where-Object device_id -eq $_.aid).cid device_id = $_.aid tags = if ($_.stdout) { ($_.stdout).Trim() } elseif ($_.stderr) { $_.stderr } else { $_.errors } } } } } } catch { throw $_ } } } } function Remove-FalconSensorTag { <# .SYNOPSIS Use Real-time Response to remove FalconSensorTags from hosts .DESCRIPTION Provided FalconSensorTag values will be removed from existing tags and others will be left unmodified. Requires 'Hosts: Read', 'Sensor update policies: Write' and 'Real time response (admin): Write'. .PARAMETER Tag FalconSensorTag value ['FalconSensorTags/<string>'] .PARAMETER Id Host identifier .PARAMETER QueueOffline Add command request to the offline queue .LINK https://github.com/crowdstrike/psfalcon/wiki/Remove-FalconSensorTag #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory,Position=1)] [ValidateScript({ @($_).foreach{ if ((Test-RegexValue $_) -eq 'tag') { $true } else { throw "Valid values include letters, numbers, hyphens, unscores and forward slashes. ['$_']" } } })] [Alias('Tags')] [string[]]$Tag, [Parameter(Position=2)] [boolean]$QueueOffline, [Parameter(Mandatory,ValueFromPipelineByPropertyName,ValueFromPipeline,Position=3)] [ValidatePattern('^[a-fA-F0-9]{32}$')] [Alias('Ids','device_id','host_ids','aid')] [string[]]$Id ) begin { [string]$ScriptPath = Join-Path (Show-FalconModule).ModulePath 'script' [System.Collections.Generic.List[string]]$List = @() } process { if ($Id) { @($Id).foreach{ $List.Add($_) }}} end { if ($List) { [string[]]$Id = @($List | Select-Object -Unique) [string[]]$Tag = $Tag -replace 'SensorGroupingTags/',$null [string]$UserAgent = (Show-FalconModule).UserAgent try { # Get device info to determine script and begin session $HostList = Get-FalconHost -Id $Id | Select-Object cid,device_id,platform_name,device_policies,tags foreach ($Platform in (($HostList.platform_name | Group-Object).Name | Where-Object { @('Linux','Mac', 'Windows') -contains $_ })) { # Start sessions for each 'platform' type if ($Platform -eq 'Windows') { foreach ($i in ($HostList | Where-Object { $_.platform_name -eq $Platform })) { [boolean]$TagMatch = $false [string[]]$Existing = ($i.tags | Where-Object { $_ -match 'SensorGroupingTags/' }) -replace 'SensorGroupingTags/',$null @($Tag).foreach{ if ($TagMatch -eq $false -and $Existing -contains $_) { $TagMatch = $true }} if ($TagMatch -eq $true) { [string]$Script = Get-Content (Join-Path $ScriptPath 'remove_sensortag.ps1') -Raw [string]$TagString = (@($Existing + $Tag) | Select-Object -Unique) -join ',' [string]$CmdLine = if ($i.device_policies.sensor_update.uninstall_protection -eq 'ENABLED') { '-Tag',$TagString,'-Token',($i.device_id | Get-FalconUninstallToken -AuditMessage ( 'Remove-FalconSensorTag',"[$UserAgent]" -join ' ')).uninstall_token -join ' ' } else { '-Tag',$TagString -join ' ' } $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}``` -CommandLine=```{1}```' -f $Script,$CmdLine HostId = $i.device_id QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } Invoke-FalconRtr @Param | Select-Object aid,stdout,stderr,errors | ForEach-Object { # Output device properties and 'tags' value after script [PSCustomObject]@{ cid = $i.cid device_id = $_.aid tags = if ($_.stdout) { $Result = ($_.stdout).Trim() if ($Result -eq 'Maintenance Token>') { $TagString } else { $Result } } elseif ($_.stderr) { $_.stderr } else { $_.errors } } } } else { # Output device properties and 'tags' value when no changes required [PSCustomObject]@{ cid = $i.cid device_id = $i.device_id tags = $Existing -join ',' } } } } else { [string]$Filename = if ($Platform -eq 'Linux') { 'remove_sensortag.sh' } else { 'remove_sensortag.zsh' } [string]$Script = Get-Content (Join-Path $ScriptPath $Filename) -Raw $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}``` -CommandLine=```{1}```' -f $Script,($Tag -join ',') HostId = ($HostList | Where-Object { $_.platform_name -eq $Platform }).device_id QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } Invoke-FalconRtr @Param | Select-Object aid,stdout,stderr,errors | ForEach-Object { # Output device properties and 'tags' value [PSCustomObject]@{ cid = ($HostList | Where-Object device_id -eq $_.aid).cid device_id = $_.aid tags = if ($_.stdout) { ($_.stdout).Trim() } elseif ($_.stderr) { $_.stderr } else { $_.errors } } } } } } catch { throw $_ } } } } function Uninstall-FalconSensor { <# .SYNOPSIS Use Real-time Response to uninstall the Falcon sensor from a host .DESCRIPTION This command uses information from the registry and/or relevant Falcon command line utilities of the target host to uninstall the Falcon sensor. If the sensor is damaged or malfunctioning, Real-time Response may not work properly and/or the uninstallation may not succeed. Requires 'Hosts: Read', 'Sensor update policies: Write', 'Real time response: Read', and 'Real Time Response (Admin): Write'. .PARAMETER QueueOffline Add command request to the offline queue .PARAMETER Include Include additional properties .PARAMETER Id Host identifier .LINK https://github.com/crowdstrike/psfalcon/wiki/Uninstall-FalconSensor #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position=1)] [boolean]$QueueOffline, [Parameter(Position=2)] [ValidateSet('agent_version','cid','external_ip','first_seen','hostname','last_seen','local_ip', 'mac_address','os_build','os_version','platform_name','product_type','product_type_desc', 'serial_number','system_manufacturer','system_product_name','tags',IgnoreCase=$false)] [string[]]$Include, [Parameter(Mandatory,ValueFromPipelineByPropertyName,ValueFromPipeline,Position=3)] [ValidatePattern('^[a-fA-F0-9]{32}$')] [Alias('HostId','device_id','host_ids','aid')] [string]$Id ) process { try { [string[]]$Select = 'cid','device_id','platform_name','device_policies' if ($Include) { $Select += $Include } $HostList = Get-FalconHost -Id $Id | Select-Object $Select if ($HostList.platform_name -notmatch '^(Windows|Linux)$') { throw 'Only Windows and Linux hosts are currently supported for uninstallation using PSFalcon.' } [string]$Filename = if ($Platform -eq 'Linux') { 'uninstall_sensor.sh' } else { 'uninstall_sensor.ps1' } [string]$Script = Get-Content (Join-Path (Join-Path (Show-FalconModule).ModulePath 'script') $Filename) -Raw $Param = @{ Command = 'runscript' Argument = '-Raw=```{0}```' -f $Script Timeout = 120 QueueOffline = if ($QueueOffline) { $QueueOffline } else { $false } } [string]$IdValue = switch ($HostList.device_policies.sensor_update.uninstall_protection) { 'ENABLED' { $HostList.device_id } 'MAINTENANCE_MODE' { 'MAINTENANCE' } } if ($IdValue) { [string]$Token = ($IdValue | Get-FalconUninstallToken -AuditMessage ("Uninstall-FalconSensor [$( (Show-FalconModule).UserAgent)]")).uninstall_token if ($Token) { $Param.Argument += (' -CommandLine=```{0}```' -f $Token) } } $Request = $HostList | Invoke-FalconRtr @Param if ($Request) { [string[]]$Select = 'cid','device_id' if ($Include) { $Select += $Include } @($HostList | Select-Object $Select).foreach{ $Status = if ($Request.stdout) { ($Request.stdout).Trim() } elseif (!$Request.stdout -and $QueueOffline -eq $true) { 'Uninstall request queued' } else { $Request.stderr } Set-Property $_ 'status' $Status $_ } } } catch { throw $_ } } } |