SophosFirewall.ActiveThreatResponse.psm1
|
#requires -Version 5.1 #requires -Modules SophosFirewall.Core <# SophosFirewall.ActiveThreatResponse ==================================== PowerShell module for the Sophos Firewall (SFOS) PROTECT > Active threat response area via the XML API: the device-wide ATP (Sophos X-Ops threat feeds) singleton, including its HostException and ThreatException lists, and ThirdPartyFeed objects. Total Functions: 10 - see README.md for the full cmdlet table. Requires SophosFirewall.Core (>= 1.3.0) for transport, session state and status evaluation. All XML building and entity parsing happens here; all HTTP(S) happens in Core. API reference: https://docs.sophos.com/nsg/sophos-firewall/22.0/api/ #> #region ATP <# .SYNOPSIS Retrieves the ATP (Sophos X-Ops threat feeds) settings from the Sophos Firewall. .DESCRIPTION Queries the Sophos Firewall XML API for the ATP singleton (PROTECT > Active threat response > Sophos X-Ops threat feeds - the wire element and API documentation folder are still named ATP, a naming leftover from the feature's former name "Advanced Threat Protection"). There is exactly one instance of this element per firewall. By default the cmdlet returns a PowerShell-friendly object. Use -AsXml to return the raw XML node. The cmdlet only reads; nothing on the firewall is changed. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .PARAMETER AsXml Optional. Returns the raw XML node sent by the firewall instead of a PowerShell object. .INPUTS None. This cmdlet does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject. One object with the properties ThreatProtectionStatus, InspectContent, Policy, HostExceptionList and ThreatExceptionList. Returns System.Xml.XmlElement when -AsXml is used. The exception lists are always an array, empty when no exception is configured. .EXAMPLE Get-SfosATPSettings Reads the device-wide ATP configuration. .EXAMPLE Get-SfosATPSettings -AsXml Returns the raw XML node, for example to check a field that the standard output does not contain. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Set-SfosATPSettings #> function Get-SfosATPSettings { # PSUseSingularNouns is suppressed on purpose: <ATP> settings form one singleton # configuration object (Sophos X-Ops threat feeds), not a plural container - the same # reasoning as the WebFilterSettings precedent. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [CmdletBinding()] param( [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session, [switch]$AsXml ) $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters $inner = '<Get><ATP></ATP></Get>' try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to retrieve ATP settings: $($_.Exception.Message)" } $XmlResponse = [xml]$response.Content Assert-SfosApiReturnSuccess -Xml $XmlResponse -ObjectName 'ATP' -Action 'get' $node = $XmlResponse.SelectSingleNode('/Response/ATP') if (-not $node) { throw 'ATP settings could not be retrieved from the firewall.' } if ($AsXml) { return $node } $hostNodes = @($node.SelectNodes('HostException/Host')) $threatNodes = @($node.SelectNodes('ThreatException/Threat')) return [PSCustomObject]@{ ThreatProtectionStatus = [string]$node.ThreatProtectionStatus InspectContent = [string]$node.InspectContent Policy = [string]$node.Policy HostExceptionList = @($hostNodes | ForEach-Object -Process { [string]$_.InnerText }) ThreatExceptionList = @($threatNodes | ForEach-Object -Process { [string]$_.InnerText }) } } <# .SYNOPSIS Updates the ATP (Sophos X-Ops threat feeds) settings on the Sophos Firewall. .DESCRIPTION Updates the device-wide ATP singleton using the Sophos Firewall XML API. Reads the current object first and resends every field, overriding only what the caller explicitly passed. Fields left out keep their current value on the firewall. This is a device-wide security switch that controls threat feed enforcement for the whole appliance. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly, and an account with administrative permission. .PARAMETER ThreatProtectionStatus Optional. 'Enable' or 'Disable'. If omitted, the existing value is kept. .PARAMETER InspectContent Optional. 'all' or 'untrusted'. If omitted, the existing value is kept. .PARAMETER Policy Optional. 'Log Only' or 'Log and Drop'. If omitted, the existing value is kept. .PARAMETER HostException Optional. Complete replacement list of HostException entries. Each entry must be the name of an existing IPHost object on the firewall. If omitted, the existing list is kept. Pass an empty array to clear the list. .PARAMETER ThreatException Optional. Complete replacement list of ThreatException entries. Each entry is free text. If omitted, the existing list is kept. Pass an empty array to clear the list. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. The account needs administrative permission. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS None. This cmdlet does not accept pipeline input. .OUTPUTS None. The cmdlet writes no output and raises an error if the firewall rejects the update. .EXAMPLE Set-SfosATPSettings -InspectContent all -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Set-SfosATPSettings -InspectContent all Switches content inspection from untrusted-only to all traffic. Every other field keeps its current value. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Get-SfosATPSettings #> function Set-SfosATPSettings { # PSUseSingularNouns is suppressed on purpose: see Get-SfosATPSettings. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [CmdletBinding(SupportsShouldProcess)] param( [ValidateSet('Enable', 'Disable')] [string]$ThreatProtectionStatus, [ValidateSet('all', 'untrusted')] [string]$InspectContent, [ValidateSet('Log Only', 'Log and Drop')] [string]$Policy, [string[]]$HostException, [string[]]$ThreatException, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters $bp = $PSBoundParameters $current = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck $targetThreatProtectionStatus = if ($bp.ContainsKey('ThreatProtectionStatus')) { $ThreatProtectionStatus } else { $current.ThreatProtectionStatus } $targetInspectContent = if ($bp.ContainsKey('InspectContent')) { $InspectContent } else { $current.InspectContent } $targetPolicy = if ($bp.ContainsKey('Policy')) { $Policy } else { $current.Policy } # @() wraps the whole if/else: a one-element array from a branch unrolls to a scalar # on assignment. $targetHostException = @(if ($bp.ContainsKey('HostException')) { $HostException } else { $current.HostExceptionList }) $targetThreatException = @(if ($bp.ContainsKey('ThreatException')) { $ThreatException } else { $current.ThreatExceptionList }) if (-not $PSCmdlet.ShouldProcess("ATP settings on $($params.Firewall)", 'Update')) { return } $policyEsc = ConvertTo-SfosXmlEscaped -Text $targetPolicy $hostXml = '' if ($targetHostException.Count -gt 0) { $hostItems = foreach ($item in $targetHostException) { $itemEsc = ConvertTo-SfosXmlEscaped -Text $item "<Host>$itemEsc</Host>" } $hostXml = "<HostException>$($hostItems -join '')</HostException>" } $threatXml = '' if ($targetThreatException.Count -gt 0) { $threatItems = foreach ($item in $targetThreatException) { $itemEsc = ConvertTo-SfosXmlEscaped -Text $item "<Threat>$itemEsc</Threat>" } $threatXml = "<ThreatException>$($threatItems -join '')</ThreatException>" } $inner = @" <Set operation="update"> <ATP> <ThreatProtectionStatus>$targetThreatProtectionStatus</ThreatProtectionStatus> <InspectContent>$targetInspectContent</InspectContent> <Policy>$policyEsc</Policy> $hostXml $threatXml </ATP> </Set> "@ try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to update ATP settings: $($_.Exception.Message)" } $XmlResponse = [xml]$response.Content Assert-SfosApiReturnSuccess -Xml $XmlResponse -ObjectName 'ATP' -Action 'update' } <# .SYNOPSIS Adds an IPHost exception to the ATP settings on the Sophos Firewall. .DESCRIPTION Adds an entry to the ATP HostException list using the Sophos Firewall XML API. Reads the current ATP object first and resends it complete with the new host appended. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. HostException expects the name of an already existing IPHost object, while ThreatException accepts free text. .PARAMETER HostName Required. Name of an existing IPHost object on the firewall to except from ATP inspection. Accepts pipeline input by value or by property name, aliased 'Host' so Get-SfosIPHost | Add-SfosATPHostException binds. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.String. HostName can be supplied by value or by property name, for example from Get-SfosIPHost. .OUTPUTS None. The cmdlet writes no output and raises an error if the firewall rejects the update. .EXAMPLE Add-SfosATPHostException -HostName 'WebServer01' -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Add-SfosATPHostException -HostName 'WebServer01' Adds the IPHost object 'WebServer01' to the ATP HostException list. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Get-SfosATPSettings .LINK Remove-SfosATPHostException #> function Add-SfosATPHostException { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('Host')] [string]$HostName, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $current = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (-not $PSCmdlet.ShouldProcess("ATP HostException '$HostName' on $($params.Firewall)", 'Add')) { return } $newList = @($current.HostExceptionList) + $HostName Set-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck ` -HostException $newList ` -Confirm:$false } } <# .SYNOPSIS Removes an IPHost exception from the ATP settings on the Sophos Firewall. .DESCRIPTION Removes an entry from the ATP HostException list using the Sophos Firewall XML API. Reads the current ATP object first, throws if the host is not currently listed, and otherwise resends the ATP object complete with the host filtered out. Reads the object back afterwards and throws if the host is still present. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. .PARAMETER HostName Required. Name of the IPHost object to remove from the HostException list. Accepts pipeline input by value or by property name, aliased 'Host'. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.String. HostName can be supplied by value or by property name. .OUTPUTS None. The cmdlet writes no output and raises an error if the update fails or the host is still present afterwards. .EXAMPLE Remove-SfosATPHostException -HostName 'WebServer01' -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Remove-SfosATPHostException -HostName 'WebServer01' Removes the IPHost object 'WebServer01' from the ATP HostException list. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Get-SfosATPSettings .LINK Add-SfosATPHostException #> function Remove-SfosATPHostException { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('Host')] [string]$HostName, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $current = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (@($current.HostExceptionList) -notcontains $HostName) { throw "The ATP HostException '$HostName' was not found." } if (-not $PSCmdlet.ShouldProcess("ATP HostException '$HostName' on $($params.Firewall)", 'Remove')) { return } $newList = @($current.HostExceptionList | Where-Object -FilterScript { $_ -ne $HostName }) Set-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck ` -HostException $newList ` -Confirm:$false $after = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (@($after.HostExceptionList) -contains $HostName) { throw "Failed to remove ATP HostException '$HostName': the firewall reported success but the host is still present." } } } <# .SYNOPSIS Adds a threat exception to the ATP settings on the Sophos Firewall. .DESCRIPTION Adds an entry to the ATP ThreatException list using the Sophos Firewall XML API. Reads the current ATP object first and resends it complete with the new threat identifier appended. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. HostException expects the name of an already existing IPHost object, while ThreatException accepts free text. .PARAMETER Threat Required. Threat identifier text to except from ATP enforcement. Accepts pipeline input by value or by property name. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.String. Threat can be supplied by value or by property name. .OUTPUTS None. The cmdlet writes no output and raises an error if the firewall rejects the update. .EXAMPLE Add-SfosATPThreatException -Threat 'C2/Generic-A' -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Add-SfosATPThreatException -Threat 'C2/Generic-A' Adds the threat identifier 'C2/Generic-A' to the ATP ThreatException list. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Get-SfosATPSettings .LINK Remove-SfosATPThreatException #> function Add-SfosATPThreatException { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string]$Threat, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $current = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (-not $PSCmdlet.ShouldProcess("ATP ThreatException '$Threat' on $($params.Firewall)", 'Add')) { return } $newList = @($current.ThreatExceptionList) + $Threat Set-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck ` -ThreatException $newList ` -Confirm:$false } } <# .SYNOPSIS Removes a threat exception from the ATP settings on the Sophos Firewall. .DESCRIPTION Removes an entry from the ATP ThreatException list using the Sophos Firewall XML API. Reads the current ATP object first, throws if the threat is not currently listed, and otherwise resends the ATP object complete with the threat filtered out. Reads the object back afterwards and throws if the threat is still present. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. .PARAMETER Threat Required. Threat identifier text to remove from the ThreatException list. Accepts pipeline input by value or by property name. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.String. Threat can be supplied by value or by property name. .OUTPUTS None. The cmdlet writes no output and raises an error if the update fails or the threat is still present afterwards. .EXAMPLE Remove-SfosATPThreatException -Threat 'C2/Generic-A' -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Remove-SfosATPThreatException -Threat 'C2/Generic-A' Removes the threat identifier 'C2/Generic-A' from the ATP ThreatException list. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/ATP/operations/SophosX-Opsthreatfeeds.html .LINK Get-SfosATPSettings .LINK Add-SfosATPThreatException #> function Remove-SfosATPThreatException { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string]$Threat, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $current = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (@($current.ThreatExceptionList) -notcontains $Threat) { throw "The ATP ThreatException '$Threat' was not found." } if (-not $PSCmdlet.ShouldProcess("ATP ThreatException '$Threat' on $($params.Firewall)", 'Remove')) { return } $newList = @($current.ThreatExceptionList | Where-Object -FilterScript { $_ -ne $Threat }) Set-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck ` -ThreatException $newList ` -Confirm:$false $after = Get-SfosATPSettings -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -SkipCertificateCheck:$params.SkipCertificateCheck if (@($after.ThreatExceptionList) -contains $Threat) { throw "Failed to remove ATP ThreatException '$Threat': the firewall reported success but the threat is still present." } } } #endregion #region ThirdPartyFeed <# .SYNOPSIS Retrieves ThirdPartyFeed objects from the Sophos Firewall. .DESCRIPTION Queries the Sophos Firewall XML API for ThirdPartyFeed objects (PROTECT > Active threat response > Third party threat feed). A ThirdPartyFeed polls an external URL for threat indicators and feeds them into the firewall's own enforcement. By default the cmdlet returns PowerShell-friendly objects. Use -AsXml to return the raw XML nodes. The cmdlet only reads; nothing on the firewall is changed. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly. You can combine several filters. The firewall itself evaluates at most one of them, so every filter you supply is applied again on the client. The result therefore always matches all filters you gave. Position is a write-only field and Get-SfosThirdPartyFeed never returns it, so Set-SfosThirdPartyFeed has no -Position parameter. .PARAMETER NameLike Optional. Returns only objects whose name contains the given text anywhere. This is a substring match, not a wildcard pattern. If omitted, the name is not used to filter. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .PARAMETER AsXml Optional. Returns the raw XML nodes sent by the firewall instead of PowerShell objects. .INPUTS None. This cmdlet does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject. One object per feed, with the properties Id, Name, Description, Action, IndicatorType, ExternalURL, Authorization, Username, PasswordHash, Key, ValueHash, AddTo, ValidateServerCertificate, PollingInterval and Enabled. PasswordHash and ValueHash carry the firewall's hashed secret for troubleshooting only; they are never usable as a credential. Returns System.Xml.XmlElement when -AsXml is used, and an empty array when no object matches. .EXAMPLE Get-SfosThirdPartyFeed Lists every configured third-party threat feed. .EXAMPLE Get-SfosThirdPartyFeed -NameLike 'Feed' Lists all feeds whose name contains 'Feed'. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/thirdpartyfeeds/thirdpartyfeeds.html .LINK New-SfosThirdPartyFeed #> function Get-SfosThirdPartyFeed { [CmdletBinding()] param( [string]$NameLike, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session, [switch]$AsXml ) $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters $filterXml = '' if ($NameLike) { $nameLikeEsc = ConvertTo-SfosXmlEscaped -Text $NameLike $filterXml = ('<Filter><key name="Name" criteria="like">{0}</key></Filter>' -f $nameLikeEsc) } $inner = @" <Get> <ThirdPartyFeed> $filterXml </ThirdPartyFeed> </Get> "@ try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to retrieve ThirdPartyFeed objects: $($_.Exception.Message)" } $XmlResponse = [xml]$response.Content Assert-SfosApiReturnSuccess -Xml $XmlResponse -ObjectName 'ThirdPartyFeed' -Action 'get' $nodes = Select-Xml -Xml $XmlResponse -XPath '/Response/ThirdPartyFeed[Name]' | ForEach-Object -Process { $_.Node } $objects = foreach ($node in @($nodes)) { $passwordNode = $node.SelectSingleNode('Password') $valueNode = $node.SelectSingleNode('Value') [PSCustomObject]@{ Id = [string]$node.Id Name = [string]$node.Name Description = [string]$node.Description Action = [string]$node.Action IndicatorType = [string]$node.IndicatorType ExternalURL = [string]$node.ExternalURL Authorization = [string]$node.Authorization Username = [string]$node.Username PasswordHash = if ($passwordNode) { [string]$passwordNode.InnerText } else { '' } Key = [string]$node.Key ValueHash = if ($valueNode) { [string]$valueNode.InnerText } else { '' } AddTo = [string]$node.AddTo ValidateServerCertificate = [string]$node.ValidateServerCertificate PollingInterval = [string]$node.PollingInterval Enabled = [string]$node.Enabled } } $objects = @($objects) if ($NameLike) { $objects = @($objects | Where-Object -FilterScript { $_.Name -like "*$NameLike*" }) } if ($AsXml) { $keptNames = @($objects | ForEach-Object -Process { $_.Name }) return @($nodes | Where-Object -FilterScript { $keptNames -contains $_.Name }) } return $objects } <# .SYNOPSIS Creates a new ThirdPartyFeed object on the Sophos Firewall. .DESCRIPTION Creates a ThirdPartyFeed (PROTECT > Active threat response > Third party threat feed) using the Sophos Firewall XML API. Use this cmdlet to add an external threat indicator feed for the firewall to poll. It needs an open connection from Connect-SfosFirewall, or the connection parameters supplied directly, and an account with administrative permission. .PARAMETER Name Required. Name of the feed. Maximum 63 characters, letters, digits, underscore and hyphen only. .PARAMETER Description Optional. Free-text description. Maximum 255 characters. If omitted, an empty description is stored. .PARAMETER Action Optional. 'block' or 'monitor'. Default 'monitor'. .PARAMETER Position Optional. 'top' or 'bottom'. Default 'top'. This field is write-only; Get-* never returns it, so it can only be set here at creation, not changed afterwards. .PARAMETER IndicatorType Optional. 'ip', 'domain' or 'url'. Default 'ip'. .PARAMETER ExternalURL Required. URL the firewall polls for indicator data. Maximum 1024 characters. .PARAMETER Authorization Optional. 'noAuthentication', 'basicAuthentication' or 'apiKey'. Default 'noAuthentication'. Determines which of -FeedUsername/-FeedPassword or -ApiKeyName/-ApiKeyValue/-AddTo are required; see those parameters. .PARAMETER FeedUsername Optional. Username for -Authorization basicAuthentication. Named differently from the connection parameter -Username because that name is reserved for the API login identity. Ignored for other -Authorization values. .PARAMETER FeedPassword Optional. Password for -Authorization basicAuthentication, as a SecureString. Named differently from the connection parameter -Password because that name is reserved for the API login secret. Required when -Authorization is basicAuthentication. .PARAMETER ApiKeyName Optional. The API key field or header name for -Authorization apiKey. Required when -Authorization is apiKey. .PARAMETER ApiKeyValue Optional. The API key secret value for -Authorization apiKey, as a SecureString. Required when -Authorization is apiKey. .PARAMETER AddTo Optional. 'header' or 'queryParam' for -Authorization apiKey. Required when -Authorization is apiKey. .PARAMETER ValidateServerCertificate Required. '1' or '0'. Whether the firewall validates the TLS certificate of -ExternalURL when polling. .PARAMETER PollingInterval Required. One of '5m','15m','30m','1h','6h','24h','7d','30d'. .PARAMETER Enabled Optional. '1' or '0'. Default '1'. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. The account needs administrative permission. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS None. This cmdlet does not accept pipeline input. .OUTPUTS None. The cmdlet writes no output and raises an error if creation fails. .EXAMPLE New-SfosThirdPartyFeed -Name 'AbuseChIPFeed' -Action monitor -IndicatorType ip -ExternalURL 'https://feeds.example.com/blocklist.txt' -Authorization noAuthentication -ValidateServerCertificate 1 -PollingInterval 1h -Enabled 1 -WhatIf Shows what the call would create without sending it to the firewall. .EXAMPLE New-SfosThirdPartyFeed -Name 'AbuseChIPFeed' -Action monitor -IndicatorType ip -ExternalURL 'https://feeds.example.com/blocklist.txt' -Authorization noAuthentication -ValidateServerCertificate 1 -PollingInterval 1h -Enabled 1 Creates a feed with no authentication. .EXAMPLE $pw = ConvertTo-SecureString 'FeedSecret1!' -AsPlainText -Force New-SfosThirdPartyFeed -Name 'VendorIPFeed' -Action monitor -IndicatorType ip -ExternalURL 'https://feeds.example.com/blocklist.txt' -Authorization basicAuthentication -FeedUsername 'feedreader' -FeedPassword $pw -ValidateServerCertificate 1 -PollingInterval 1h -Enabled 1 Creates a feed that authenticates with a username and password. .EXAMPLE $key = ConvertTo-SecureString 'MyApiKeyValue123' -AsPlainText -Force New-SfosThirdPartyFeed -Name 'PartnerIPFeed' -Action monitor -IndicatorType ip -ExternalURL 'https://feeds.example.com/blocklist.txt' -Authorization apiKey -ApiKeyName 'X-Api-Key' -ApiKeyValue $key -AddTo header -ValidateServerCertificate 1 -PollingInterval 1h -Enabled 1 Creates a feed that authenticates with an API key. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/thirdpartyfeeds/operations/AddThird-partythreatfeed%26EditThird-partythreatfeed.html .LINK Get-SfosThirdPartyFeed #> function New-SfosThirdPartyFeed { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [ValidateLength(1, 63)] [ValidatePattern('^[A-Za-z0-9_-]+$')] [string]$Name, [ValidateLength(0, 255)] [string]$Description = '', [ValidateSet('block', 'monitor')] [string]$Action = 'monitor', [ValidateSet('top', 'bottom')] [string]$Position = 'top', [ValidateSet('ip', 'domain', 'url')] [string]$IndicatorType = 'ip', [Parameter(Mandatory)] [ValidateLength(1, 1024)] [string]$ExternalURL, [ValidateSet('noAuthentication', 'basicAuthentication', 'apiKey')] [string]$Authorization = 'noAuthentication', [string]$FeedUsername, [SecureString]$FeedPassword, [string]$ApiKeyName, [SecureString]$ApiKeyValue, [ValidateSet('header', 'queryParam')] [string]$AddTo, [Parameter(Mandatory)] [ValidateSet('1', '0')] [string]$ValidateServerCertificate, [Parameter(Mandatory)] [ValidateSet('5m', '15m', '30m', '1h', '6h', '24h', '7d', '30d')] [string]$PollingInterval, [ValidateSet('1', '0')] [string]$Enabled = '1', [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters if ($Authorization -eq 'basicAuthentication' -and -not $FeedPassword) { throw "ThirdPartyFeed '$Name': -Authorization basicAuthentication requires -FeedPassword." } if ($Authorization -eq 'apiKey' -and (-not $ApiKeyName -or -not $ApiKeyValue -or -not $AddTo)) { throw "ThirdPartyFeed '$Name': -Authorization apiKey requires -ApiKeyName, -ApiKeyValue and -AddTo." } if (-not $PSCmdlet.ShouldProcess("ThirdPartyFeed '$Name' on $($params.Firewall)", 'Create')) { return } $nameEsc = ConvertTo-SfosXmlEscaped -Text $Name $descriptionEsc = ConvertTo-SfosXmlEscaped -Text $Description $externalUrlEsc = ConvertTo-SfosXmlEscaped -Text $ExternalURL $authXml = '' if ($Authorization -eq 'basicAuthentication') { $usernameEsc = ConvertTo-SfosXmlEscaped -Text $FeedUsername $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($FeedPassword) try { $plainPassword = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) } $passwordEsc = ConvertTo-SfosXmlEscaped -Text $plainPassword $authXml = "<Username>$usernameEsc</Username><Password>$passwordEsc</Password>" } elseif ($Authorization -eq 'apiKey') { $keyEsc = ConvertTo-SfosXmlEscaped -Text $ApiKeyName $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($ApiKeyValue) try { $plainValue = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) } $valueEsc = ConvertTo-SfosXmlEscaped -Text $plainValue $authXml = "<Key>$keyEsc</Key><Value>$valueEsc</Value><AddTo>$AddTo</AddTo>" } $inner = @" <Set operation="add"> <ThirdPartyFeed> <Name>$nameEsc</Name> <Description>$descriptionEsc</Description> <Action>$Action</Action> <Position>$Position</Position> <IndicatorType>$IndicatorType</IndicatorType> <ExternalURL>$externalUrlEsc</ExternalURL> <Authorization>$Authorization</Authorization> $authXml <ValidateServerCertificate>$ValidateServerCertificate</ValidateServerCertificate> <PollingInterval>$PollingInterval</PollingInterval> <Enabled>$Enabled</Enabled> </ThirdPartyFeed> </Set> "@ try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to create ThirdPartyFeed object '$Name': $($_.Exception.Message)" } $XmlResponse = [xml]$response.Content Assert-SfosApiReturnSuccess -Xml $XmlResponse -ObjectName 'ThirdPartyFeed' -Action 'create' -Target $Name } <# .SYNOPSIS Updates an existing ThirdPartyFeed object on the Sophos Firewall. .DESCRIPTION Updates a ThirdPartyFeed using the Sophos Firewall XML API. Reads the current object first and resends every field, overriding only what the caller explicitly passed. Fields left out keep their current value on the firewall. Resending a password or API key value that was read back from Get-SfosThirdPartyFeed makes the whole update fail; leaving the secret parameter out keeps the stored secret unchanged. This cmdlet never resends the value Get-SfosThirdPartyFeed returns, so pass -FeedPassword or -ApiKeyValue only when you want to set a new secret. .PARAMETER Name Required. Name of the target feed. Accepts pipeline input by property name. .PARAMETER Description Optional. Free-text description. If omitted, the existing value is kept. .PARAMETER Action Optional. 'block' or 'monitor'. If omitted, the existing value is kept. .PARAMETER IndicatorType Optional. 'ip', 'domain' or 'url'. If omitted, the existing value is kept. .PARAMETER ExternalURL Optional. URL the firewall polls for indicator data. If omitted, the existing value is kept. .PARAMETER Authorization Optional. 'noAuthentication', 'basicAuthentication' or 'apiKey'. If omitted, the existing value is kept. Switching to basicAuthentication or apiKey without a previous value of that type requires the matching secret parameter; see -FeedPassword/-ApiKeyValue. .PARAMETER FeedUsername Optional. Username for -Authorization basicAuthentication. Named differently from the connection parameter -Username because that name is reserved for the API login identity. If omitted, the existing value is kept. .PARAMETER FeedPassword Optional. New password for -Authorization basicAuthentication, as a SecureString. If omitted and the feed is already, or remains, basicAuthentication, the existing password is left unchanged on the firewall. Required when switching from a different -Authorization value to basicAuthentication in the same call. .PARAMETER ApiKeyName Optional. The API key field or header name for -Authorization apiKey. If omitted, the existing value is kept. .PARAMETER ApiKeyValue Optional. New API key secret value for -Authorization apiKey, as a SecureString. If omitted and the feed is already, or remains, apiKey, the existing value is left unchanged on the firewall. Required when switching from a different -Authorization value to apiKey in the same call. .PARAMETER AddTo Optional. 'header' or 'queryParam' for -Authorization apiKey. If omitted, the existing value is kept. .PARAMETER ValidateServerCertificate Optional. '1' or '0'. If omitted, the existing value is kept. .PARAMETER PollingInterval Optional. One of '5m','15m','30m','1h','6h','24h','7d','30d'. If omitted, the existing value is kept. .PARAMETER Enabled Optional. '1' or '0'. If omitted, the existing value is kept. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. The account needs administrative permission. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.Management.Automation.PSCustomObject. Name is bound by property name, for example from Get-SfosThirdPartyFeed. .OUTPUTS None. The cmdlet writes no output and raises an error if the update fails. .EXAMPLE Set-SfosThirdPartyFeed -Name 'AbuseChIPFeed' -Enabled 0 -WhatIf Shows what the call would change without sending it to the firewall. .EXAMPLE Set-SfosThirdPartyFeed -Name 'AbuseChIPFeed' -Enabled 0 Disables a feed, leaving every other field, including any stored secret, unchanged. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/thirdpartyfeeds/operations/AddThird-partythreatfeed%26EditThird-partythreatfeed.html .LINK Get-SfosThirdPartyFeed #> function Set-SfosThirdPartyFeed { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string]$Name, [string]$Description, [ValidateSet('block', 'monitor')] [string]$Action, [ValidateSet('ip', 'domain', 'url')] [string]$IndicatorType, [string]$ExternalURL, [ValidateSet('noAuthentication', 'basicAuthentication', 'apiKey')] [string]$Authorization, [string]$FeedUsername, [SecureString]$FeedPassword, [string]$ApiKeyName, [SecureString]$ApiKeyValue, [ValidateSet('header', 'queryParam')] [string]$AddTo, [ValidateSet('1', '0')] [string]$ValidateServerCertificate, [ValidateSet('5m', '15m', '30m', '1h', '6h', '24h', '7d', '30d')] [string]$PollingInterval, [ValidateSet('1', '0')] [string]$Enabled, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $bp = $PSBoundParameters $existing = @(Get-SfosThirdPartyFeed -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -NameLike $Name ` -SkipCertificateCheck:$params.SkipCertificateCheck | Where-Object -FilterScript { $_.Name -eq $Name }) if ($existing.Count -eq 0) { throw "The ThirdPartyFeed object '$Name' was not found." } $current = $existing[0] $targetDescription = if ($bp.ContainsKey('Description')) { $Description } else { [string]$current.Description } $targetAction = if ($bp.ContainsKey('Action')) { $Action } else { $current.Action } $targetIndicatorType = if ($bp.ContainsKey('IndicatorType')) { $IndicatorType } else { $current.IndicatorType } $targetExternalURL = if ($bp.ContainsKey('ExternalURL')) { $ExternalURL } else { $current.ExternalURL } $targetAuthorization = if ($bp.ContainsKey('Authorization')) { $Authorization } else { $current.Authorization } $targetValidateServerCertificate = if ($bp.ContainsKey('ValidateServerCertificate')) { $ValidateServerCertificate } else { $current.ValidateServerCertificate } $targetPollingInterval = if ($bp.ContainsKey('PollingInterval')) { $PollingInterval } else { $current.PollingInterval } $targetEnabled = if ($bp.ContainsKey('Enabled')) { $Enabled } else { $current.Enabled } $authXml = '' if ($targetAuthorization -eq 'basicAuthentication') { $targetUsername = if ($bp.ContainsKey('FeedUsername')) { $FeedUsername } else { [string]$current.Username } $usernameEsc = ConvertTo-SfosXmlEscaped -Text $targetUsername if ($bp.ContainsKey('FeedPassword')) { $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($FeedPassword) try { $plainPassword = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) } $passwordEsc = ConvertTo-SfosXmlEscaped -Text $plainPassword $authXml = "<Username>$usernameEsc</Username><Password>$passwordEsc</Password>" } elseif ($current.Authorization -eq 'basicAuthentication') { # Omitting Password here, while staying basicAuthentication, preserves the # stored secret. Resending PasswordHash silently drops the whole update instead. $authXml = "<Username>$usernameEsc</Username>" } else { throw "ThirdPartyFeed '$Name': switching -Authorization to basicAuthentication requires -FeedPassword." } } elseif ($targetAuthorization -eq 'apiKey') { $targetApiKeyName = if ($bp.ContainsKey('ApiKeyName')) { $ApiKeyName } else { [string]$current.Key } $keyEsc = ConvertTo-SfosXmlEscaped -Text $targetApiKeyName $targetAddTo = if ($bp.ContainsKey('AddTo')) { $AddTo } else { $current.AddTo } if ($bp.ContainsKey('ApiKeyValue')) { $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($ApiKeyValue) try { $plainValue = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) } $valueEsc = ConvertTo-SfosXmlEscaped -Text $plainValue $authXml = "<Key>$keyEsc</Key><Value>$valueEsc</Value><AddTo>$targetAddTo</AddTo>" } elseif ($current.Authorization -eq 'apiKey') { # Same preserve-on-omit behaviour as Password above. $authXml = "<Key>$keyEsc</Key><AddTo>$targetAddTo</AddTo>" } else { throw "ThirdPartyFeed '$Name': switching -Authorization to apiKey requires -ApiKeyName, -ApiKeyValue and -AddTo." } } if (-not $PSCmdlet.ShouldProcess("ThirdPartyFeed '$Name' on $($params.Firewall)", 'Update')) { return } $nameEsc = ConvertTo-SfosXmlEscaped -Text $Name $descriptionEsc = ConvertTo-SfosXmlEscaped -Text $targetDescription $externalUrlEsc = ConvertTo-SfosXmlEscaped -Text $targetExternalURL $inner = @" <Set operation="update"> <ThirdPartyFeed> <Name>$nameEsc</Name> <Description>$descriptionEsc</Description> <Action>$targetAction</Action> <IndicatorType>$targetIndicatorType</IndicatorType> <ExternalURL>$externalUrlEsc</ExternalURL> <Authorization>$targetAuthorization</Authorization> $authXml <ValidateServerCertificate>$targetValidateServerCertificate</ValidateServerCertificate> <PollingInterval>$targetPollingInterval</PollingInterval> <Enabled>$targetEnabled</Enabled> </ThirdPartyFeed> </Set> "@ try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to update ThirdPartyFeed object '$Name': $($_.Exception.Message)" } $XmlResponse = [xml]$response.Content Assert-SfosApiReturnSuccess -Xml $XmlResponse -ObjectName 'ThirdPartyFeed' -Action 'update' -Target $Name } } <# .SYNOPSIS Removes a ThirdPartyFeed object from the Sophos Firewall. .DESCRIPTION Removes a ThirdPartyFeed using the Sophos Firewall XML API. Reads the object first and throws a clear "not found" error if it does not exist. Remove-SfosThirdPartyFeed decides whether the removal succeeded by reading the object back afterwards, because the firewall's own delete response for this entity does not reliably indicate success or failure. .PARAMETER Name Required. Name of the feed to remove. Accepts pipeline input by property name. .PARAMETER Session Optional. A session object from Connect-SfosFirewall, or the name of a session that was registered with Connect-SfosFirewall -Name. Use it to address a specific firewall when you work with more than one at a time. Any connection parameter you pass explicitly still takes precedence. If omitted, the stored default connection is used. .PARAMETER Firewall Optional. Host name or IP address of the firewall. If omitted, the value from the current connection is used. .PARAMETER Port Optional. TCP port of the management API, usually 4444. If omitted, the value from the current connection is used. .PARAMETER Username Optional. User name for the API login. The account needs administrative permission. If omitted, the value from the current connection is used. .PARAMETER Password Optional. Password for the API login, as a SecureString. If omitted, the value from the current connection is used. .PARAMETER SkipCertificateCheck Optional. Accepts the firewall certificate without validating it. Use this only for appliances that still present a self-signed certificate. If omitted, the certificate is validated. .INPUTS System.Management.Automation.PSCustomObject. Name is bound by property name, for example from Get-SfosThirdPartyFeed. .OUTPUTS None. The cmdlet writes no output and raises an error if the removal fails or cannot be confirmed. .EXAMPLE Remove-SfosThirdPartyFeed -Name 'AbuseChIPFeed' -WhatIf Shows what the call would remove without sending it to the firewall. .EXAMPLE Remove-SfosThirdPartyFeed -Name 'AbuseChIPFeed' Removes the ThirdPartyFeed object 'AbuseChIPFeed'. .LINK https://docs.sophos.com/nsg/sophos-firewall/22.0/API/PROTECT/Active%20threat%20response/thirdpartyfeeds/operations/Delete%20Third-party%20threat%20feed.html .LINK Get-SfosThirdPartyFeed #> function Remove-SfosThirdPartyFeed { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string]$Name, [string]$Firewall, [int]$Port, [string]$Username, [SecureString]$Password, [switch]$SkipCertificateCheck, [object]$Session ) begin { $params = Resolve-SfosParameters -BoundParameters $PSBoundParameters } process { $existing = @(Get-SfosThirdPartyFeed -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -NameLike $Name ` -SkipCertificateCheck:$params.SkipCertificateCheck | Where-Object -FilterScript { $_.Name -eq $Name }) if ($existing.Count -eq 0) { throw "The ThirdPartyFeed object '$Name' was not found." } if (-not $PSCmdlet.ShouldProcess("ThirdPartyFeed '$Name' on $($params.Firewall)", 'Remove')) { return } $nameEsc = ConvertTo-SfosXmlEscaped -Text $Name $inner = @" <Remove> <ThirdPartyFeed> <Name>$nameEsc</Name> </ThirdPartyFeed> </Remove> "@ try { $response = Invoke-SfosApi -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -InnerXml $inner -SkipCertificateCheck:$params.SkipCertificateCheck -ErrorAction Stop } catch { throw "Failed to remove ThirdPartyFeed object '$Name': $($_.Exception.Message)" } # The status code/message this entity returns on Remove cannot distinguish success # from failure, so only the login is checked here and the real outcome is confirmed # below with a follow-up Get. $XmlResponse = [xml]$response.Content $loginNode = $XmlResponse.SelectSingleNode('/Response/Login/status') if ($loginNode -and [string]$loginNode.InnerText -notmatch 'Success') { throw "Sophos API login failed while trying to remove ThirdPartyFeed object '$Name'. $([string]$loginNode.InnerText)" } $stillThere = @(Get-SfosThirdPartyFeed -Firewall $params.Firewall ` -Port $params.Port ` -Username $params.Username ` -Password $params.Password ` -NameLike $Name ` -SkipCertificateCheck:$params.SkipCertificateCheck | Where-Object -FilterScript { $_.Name -eq $Name }) if ($stillThere.Count -gt 0) { throw "Failed to remove ThirdPartyFeed object '$Name': the firewall's delete response cannot be trusted for this entity and the object is still present." } } } #endregion |