SophosCentral.psm1
# ./SophosCentral/private/Get-SophosCentralAuthHeader.ps1 function Get-SophosCentralAuthHeader { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [switch]$Initial, [switch]$PartnerInitial ) if ((Test-SophosCentralAuth) -eq $true) { $header = @{ Authorization = 'Bearer ' + (Unprotect-Secret -Secret $SCRIPT:SophosCentral.access_token) } if (($Initial -ne $true) -and ($PartnerInitial -ne $true)) { switch ($SCRIPT:SophosCentral.IDType) { 'partner' { $header.Add('X-Tenant-ID', $SCRIPT:SophosCentral.CustomerTenantID) } 'tenant' { $header.Add('X-Tenant-ID', $SCRIPT:SophosCentral.TenantID) } 'organization' { $header.Add('X-Tenant-ID', $SCRIPT:SophosCentral.CustomerTenantID) } } } if ($PartnerInitial) { switch ($SCRIPT:SophosCentral.IDType) { 'partner' { $header.Add('X-Partner-ID', $SCRIPT:SophosCentral.TenantID) } 'organization' { $header.Add('X-Organization-ID', $SCRIPT:SophosCentral.TenantID) } } } $header } } # ./SophosCentral/private/Invoke-SophosCentralWebRequest.ps1 function Invoke-SophosCentralWebRequest { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.URI]$Uri, [System.Collections.Hashtable]$CustomHeader, [ValidateSet('Get', 'Post', 'Put', 'Delete')] [string]$Method = 'Get', [System.Collections.Hashtable]$Body ) if ($PSVersionTable.PSVersion.Major -lt 7) { Write-Warning 'Unsupported version of PowerShell detected' } if ($null -ne $CustomHeader) { $header = $CustomHeader } else { try { $header = Get-SophosCentralAuthHeader } catch { throw $_ } } #inital request $webRequest = @{ Uri = $uri Headers = $header UseBasicParsing = $true Method = $Method } if (($null -eq $body) -and ($Method -in ('Post', 'Put'))) { #API endpoints that use a 'post'/'put' require a body. If no body is present it will give an error back, so supply an empty body $bodyTmp = @{} | ConvertTo-Json $webRequest.Add('Body', $bodyTmp) } elseif (($null -ne $Body) -and ($Method -eq 'Get')) { $webRequest.Add('Body', $Body) } elseif ($null -ne $Body) { $webRequest.Add('Body', ($Body | ConvertTo-Json -Depth 5)) } if ($Method -notin ('Delete', 'Get')) { $webRequest.Add('ContentType', 'application/json') } #query api and return the first page $response = Invoke-RestMethod @webRequest if ($null -ne $response.items) { $response.items } else { $response } #pagination $finished = $false if ($response.pages.total -gt 1) { #enterprise/partner tenant pagination - based on total returned from the initial lookup #see here for details on pagination https://developer.sophos.com/getting-started > step 4 #doco says the initial page is 1, so the following pages start at 2 onwards for ($i = 2; $i -le $response.pages.total; $i++) { $webRequest['Uri'] = $uri.AbsoluteUri.Replace('pageTotal=true', "page=$($i.ToString())") $responseLoop = Invoke-RestMethod @webRequest if ($null -ne $response.items) { $responseLoop.items } else { $responseLoop } } } else { #standard pagination - based on nextKey value returned from the previous lookup do { if ($response.pages.nextKey) { if ($uri.AbsoluteUri -like '*`?*') { $webRequest['Uri'] = $uri.AbsoluteUri + '&pageFromKey=' + $response.pages.nextKey } else { $webRequest['Uri'] = $uri.AbsoluteUri + '?pageFromKey=' + $response.pages.nextKey } $response = Invoke-RestMethod @webRequest $response.items } else { $finished = $true } } while ($finished -eq $false) } } # ./SophosCentral/private/New-UriWithQuery.ps1 function New-UriWithQuery { [CmdletBinding()] [OutputType([System.Uri])] param ( [Parameter(Mandatory = $true)] [System.Uri]$Uri, [Parameter(Mandatory = $true)] [hashtable]$OriginalPsBoundParameters, [Parameter(Mandatory = $false)] [Alias('filteredParmeters')] [array]$FilteredParameters ) $uriBuilder = [System.UriBuilder]::New($Uri.AbsoluteUri) $blockedKeys = 'Verbose', 'Force', 'Debug', 'WhatIf' + $FilteredParameters $keys = $OriginalPsBoundParameters.Keys | Where-Object { $blockedKeys -notcontains $_ } foreach ($param in $keys) { if (($null -ne $OriginalPsBoundParameters[$param]) -and ($null -ne $param)) { $paraCaseSensitive = $param.ToString()[0].ToString().ToLower() + $param.ToString().Substring(1) if ( $OriginalPsBoundParameters[$param] -is [array]) { $queryPart = $paraCaseSensitive + '=' + ($OriginalPsBoundParameters[$param] -join ',') } else { #convert time time to ISO 8601 Universal Format Specifier if ($OriginalPsBoundParameters[$param].GetType().Name -eq 'DateTime') { $OriginalPsBoundParameters[$param] = $OriginalPsBoundParameters[$param].ToUniversalTime().ToString('u').Replace(' ', 'T') } $queryPart = $paraCaseSensitive + '=' + $OriginalPsBoundParameters[$param] } if (($null -eq $uriBuilder.Query) -or ($uriBuilder.Query.Length -le 1 )) { $uriBuilder.Query = $queryPart } else { $uriBuilder.Query = $uriBuilder.Query.Substring(1) + '&' + $queryPart } } } [System.Uri]::New($uriBuilder.Uri) } # ./SophosCentral/private/Show-UntestedWarning.ps1 function Show-UntestedWarning { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$CustomWarning ) if ($null -eq $SCRIPT:TestWarning) { $SCRIPT:TestWarning = $true } if ($SCRIPT:TestWarning -eq $true) { if ($null -ne $CustomWarning) { Write-Warning $CustomWarning } else { Write-Warning 'This command has not been tested' } $action = Read-Host -Prompt "Continue?`ny: Continue`nn: Stop`nf: Ignore untested warnings for this session`nEnter response here" switch ($action) { 'y' { } 'n' { throw 'cancelling' } 'f' { $SCRIPT:TestWarning = $false } Default { throw 'cancelling' } } } } # ./SophosCentral/private/Test-SophosCentralAuth.ps1 function Test-SophosCentralAuth { [CmdletBinding()] [OutputType([bool])] param ( ) if ($SCRIPT:SophosCentral) { $date = Get-Date if ($SCRIPT:SophosCentral.expires_at -le $date) { Write-Verbose 'Access token has expired' #request new token try { Write-Verbose 'Attempting to obtain new access token' Connect-SophosCentral -ClientID $SCRIPT:SophosCentral.client_id -ClientSecret $SCRIPT:SophosCentral.client_secret -AccessTokenOnly Write-Verbose 'Testing new access token' Test-SophosCentralAuth } catch { Write-Error 'error requesting new token' return $false } } else { return $true } } else { Write-Error "You must connect with 'Connect-SophosCentral' before running any commands" return $false } } # ./SophosCentral/private/Test-SophosCentralConnected.ps1 function Test-SophosCentralConnected { [CmdletBinding()] param ( ) if ($null -eq $SCRIPT:SophosCentral.access_token) { throw "You must connect with 'Connect-SophosCentral' before running any commands" } } # ./SophosCentral/private/Test-SophosEnterprise.ps1 function Test-SophosEnterprise { [CmdletBinding()] [OutputType([bool])] param ( ) if ($SCRIPT:SophosCentral.IDType -ne 'organization') { return $false } else { Write-Verbose 'currently logged in using a Sophos Central Partner Service Principal' return $true } } # ./SophosCentral/private/Test-SophosPartner.ps1 function Test-SophosPartner { [CmdletBinding()] [OutputType([bool])] param ( ) if ($SCRIPT:SophosCentral.IDType -ne 'partner') { return $false } else { Write-Verbose 'currently logged in using a Sophos Central Partner Service Principal' return $true } } # ./SophosCentral/private/Unprotect-Secret.ps1 function Unprotect-Secret { <# .SYNOPSIS Convert a [SecureString] to a [String] .EXAMPLE $plaintextsecret = Unprotect-Secret -Secret $clientsecret #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true, HelpMessage = 'The Secure String to convert to plain text')] [SecureString]$Secret ) $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret) [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) } # ./SophosCentral/public/Connect-SophosCentral.ps1 function Connect-SophosCentral { <# .SYNOPSIS Connect to Sophos Central using your client ID and client secret, from you API credentials/service principal .DESCRIPTION Connect to Sophos Central using your client ID and client secret, from you API credentials/service principal Sophos customers can connect to their tenant using a client id/secret. Follow Step 1 here to create it https://developer.sophos.com/getting-started-tenant Sophos partners can use a partner client id/secret to connect to their customer tenants. Follow Step 1 here to create it https://developer.sophos.com/getting-started Sophos enterprise customers can connect to their tenants using a client/secret. Follow Step 1 here to create it <https://developer.sophos.com/getting-started-organization> .PARAMETER ClientID The client ID from the Sophos Central API credential/service principal .PARAMETER ClientSecret The client secret from the Sophos Central API credential/service principal .PARAMETER SecretVault Login using a client ID and client secret retrieved from Secret Vault (Microsoft.PowerShell.SecretManagement). Setup example found in https://github.com/simon-r-watson/SophosCentral/wiki/AzureKeyVaultExample This is not exclusive to using it with Azure Key Vault, you can use other providers supported by Microsoft.PowerShell.SecretManagement, such as a local one .PARAMETER AzKeyVault Calls Connect-AzAccount before retrieving the secrets from the secret vault, this can be skipped if you are already connected Uses the Microsoft.PowerShell.SecretManagement and Az.KeyVault modules for retrieving secrets Setup example found in https://github.com/simon-r-watson/SophosCentral/wiki/AzureKeyVaultExample .PARAMETER AccessTokenOnly Internal use (for this module) only. Used to generate a new access token when the current one expires .PARAMETER SecretVaultName Name of the secret vault, defaults to AzKV .PARAMETER SecretVaultClientIDName Name of the secret containing the client ID in the vault .PARAMETER SecretVaultClientSecretName Name of the secret containing the client secret in the vault .EXAMPLE Connect-SophosCentral -ClientID "asdkjsdfksjdf" -ClientSecret (Read-Host -AsSecureString -Prompt "Client Secret:") .EXAMPLE Connect-SophosCentral -SecretVault -AzKeyVault Connect using default values for Secret Key Vault name, Client ID name, and Client Secret name, with secret vault configured to use Azure Key Vault .EXAMPLE Connect-SophosCentral -SecretVault -AzKeyVault -SecretVaultName 'secrets' -SecretVaultClientIDName 'sophosclientid' -SecretVaultClientSecretName 'sophosclientsecret' Connect using custom Secret Vault name, Client ID Name, and Client Secret Name, with secret vault configured to use Azure Key Vault .EXAMPLE Connect-SophosCentral -SecretVault -SecretVaultName 'secrets' -SecretVaultClientIDName 'sophosclientid' -SecretVaultClientSecretName 'sophosclientsecret' Connect using custom Secret Vault name, Client ID Name, and Client Secret Name when using a locally stored Secret Vault (or another Microsoft.PowerShell.SecretManagement integration) .LINK https://developer.sophos.com/getting-started-tenant .LINK https://developer.sophos.com/getting-started #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('AvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'SecureStrings main usage is to stop items from appearing in the console, and not encrypting memory', Scope = 'Function')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'StdAuth', HelpMessage = 'The client ID from the Sophos Central API credential/service principal')] [String]$ClientID, [Parameter(ParameterSetName = 'StdAuth', HelpMessage = 'The client secret from the Sophos Central API credential/service principal')] [SecureString]$ClientSecret, [Parameter(ParameterSetName = 'StdAuth', HelpMessage = 'Internal use (for this module) only. Used to generate a new access token when the current one expires')] [Switch]$AccessTokenOnly, [Parameter(Mandatory = $true, ParameterSetName = 'SecretVaultAuth', HelpMessage = 'Enable secret vault auth using the Microsoft.PowerShell.SecretManagement module')] [Switch]$SecretVault, [Parameter(ParameterSetName = 'SecretVaultAuth', HelpMessage = 'Calls Connect-AzAccount before retrieving the secrets from the secret vault')] [Switch]$AzKeyVault, [Parameter(ParameterSetName = 'SecretVaultAuth', HelpMessage = 'Name of the secret vault, defaults to AzKV')] [String]$SecretVaultName = 'AzKV', [Parameter(ParameterSetName = 'SecretVaultAuth', HelpMessage = 'Name of the secret containing the client ID in the vault')] [String]$SecretVaultClientIDName = 'SophosCentral-Partner-ClientID', [Parameter(ParameterSetName = 'SecretVaultAuth', HelpMessage = 'Name of the secret containing the client secret in the vault')] [String]$SecretVaultClientSecretName = 'SophosCentral-Partner-ClientSecret' ) if ($PSVersionTable.PSVersion.Major -lt 7) { Write-Warning 'Unsupported version of PowerShell detected' } if ($PsCmdlet.ParameterSetName -eq 'StdAuth') { if ($null -eq $ClientSecret) { $ClientSecret = Read-Host -AsSecureString -Prompt 'Client Secret:' } $loginUri = [System.Uri]::new('https://id.sophos.com/api/v2/oauth2/token') $body = @{ grant_type = 'client_credentials' client_id = $ClientID client_secret = Unprotect-Secret -Secret $ClientSecret scope = 'token' } try { $response = Invoke-WebRequest -Uri $loginUri -Body $body -ContentType 'application/x-www-form-urlencoded' -Method Post -UseBasicParsing } catch { throw "Error requesting access token: $($_)" } if ($response.Content) { $authDetails = $response.Content | ConvertFrom-Json $expiresAt = (Get-Date).AddSeconds($authDetails.expires_in - 60) if ($AccessTokenOnly -eq $true) { $SCRIPT:SophosCentral.access_token = $authDetails.access_token | ConvertTo-SecureString -AsPlainText -Force $SCRIPT:SophosCentral.expires_at = $expiresAt } else { $authDetails | Add-Member -MemberType NoteProperty -Name expires_at -Value $expiresAt $authDetails.access_token = $authDetails.access_token | ConvertTo-SecureString -AsPlainText -Force $SCRIPT:SophosCentral = $authDetails $tenantInfo = Get-SophosCentralTenantInfo $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name GlobalEndpoint -Value $tenantInfo.apiHosts.global $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name RegionEndpoint -Value $tenantInfo.apiHosts.dataRegion $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name TenantID -Value $tenantInfo.id $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name IDType -Value $tenantInfo.idType $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name client_id -Value $ClientID $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name client_secret -Value $ClientSecret } } } elseif ($PsCmdlet.ParameterSetName -eq 'SecretVaultAuth' -or $SecretVault) { #verify modules installed if ($AzKeyVault -eq $true) { $modules = 'Microsoft.PowerShell.SecretManagement', 'Az', 'Az.KeyVault' } else { $modules = 'Microsoft.PowerShell.SecretManagement' } foreach ($module in $modules) { if (-not(Get-Module $module -ListAvailable)) { throw "$module PowerShell Module is not installed" } } #verify secret vault exists try { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseDeclaredVarsMoreThanAssignments', '', Justification = 'Only used for checking vault exists')] $vault = Get-SecretVault -Name $SecretVaultName } catch { throw "$SecretVaultName is not registered as a Secret Vault in Microsoft.PowerShell.SecretManagement" } #connect to Azure if using Key Vault for the Secret Vault if ($AzKeyVault -eq $true) { try { #check whether already logged into Azure $context = Get-AzContext if ($null -eq $context.Account) { Connect-AzAccount | Out-Null } } catch { throw 'Error connecting to Azure PowerShell' } } #get secrets from vault try { #try twice, as sometimes the call silently fails $clientID = Get-Secret $SecretVaultClientIDName -Vault $SecretVaultName -AsPlainText $clientSecret = Get-Secret -Name $SecretVaultClientSecretName -Vault $SecretVaultName $clientID = Get-Secret $SecretVaultClientIDName -Vault $SecretVaultName -AsPlainText $clientSecret = Get-Secret -Name $SecretVaultClientSecretName -Vault $SecretVaultName } catch { throw "Error retrieving secrets from Azure Key Vault: $_" } #connect to Sophos Central Connect-SophosCentral -ClientID $clientID -ClientSecret $clientSecret } } # ./SophosCentral/public/Connect-SophosCentralCustomerTenant.ps1 function Connect-SophosCentralCustomerTenant { <# .SYNOPSIS Connect to a Customer tenant (for Sophos partners/enterprise customers only) .DESCRIPTION Connect to a Customer tenant (for Sophos partners/enterprise customers only). You must connect with "Connect-SophosCentral" first using a partners/enterprise service principal To find the customer tenant ID, use the "Get-SophosCentralCustomerTenant" function. Enterprise customers must have the following set within the sub estates/tenants your connecting to - https://support.sophos.com/support/s/article/KB-000036994?language=en_US Partners should follow similar instructions in the customer tenants - this is enabled by default for trials/new accounts created from the Partner Dashboard .PARAMETER CustomerTenantID The Customers tenant ID .PARAMETER CustomerNameSearch Search the tenants you have access to by their name in Sophos Central, use "*" as a wildcard. For example, if you want to connect to "Contoso Legal" ` you could enter "Contoso*" here. .PARAMETER PerformConnectionTest Setting this will perform a connection test to the tenant. The connection test currently works by doing a test call to the alerts API, as all Sophos Central tenants should have this feature enabled. .EXAMPLE Connect-SophosCentralCustomerTenant -CustomerTenantID "7d565595-e281-4128-9711-c97eb1d202c5" Connect to the tenant with an ID of "7d565595-e281-4128-9711-c97eb1d202c5" .EXAMPLE Connect-SophosCentralCustomerTenant -CustomerNameSearch "Contoso*" Connect to Contoso .EXAMPLE Connect-SophosCentralCustomerTenant -CustomerNameSearch "Contoso*" -PerformConnectionTest Connect to Contoso and perform connection test .EXAMPLE Connect-SophosCentralCustomerTenant -CustomerNameSearch "Contoso*" Connect to Contoso whilst refreshing the cache of tenants stored in memory .LINK https://developer.sophos.com/getting-started #> [CmdletBinding()] [Alias('Select-SophosCentralCustomerTenant', 'Select-SophosCentralEnterpriseTenant', 'Connect-SophosCentralEnterpriseTenant')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'ByID' )] [string]$CustomerTenantID, [Parameter(Mandatory = $true, ParameterSetName = 'BySearchString' )] [string]$CustomerNameSearch, [switch]$SkipConnectionTest, [switch]$PerformConnectionTest, [switch]$ForceTenantRefresh ) Test-SophosCentralConnected if (((Test-SophosPartner) -or (Test-SophosEnterprise)) -eq $false) { throw 'You are not currently logged in using a Sophos Central Partner/Enterprise Service Principal' } else { Write-Verbose 'currently logged in using a Sophos Central Partner/Enterprise Service Principal' } if ((-not($SCRIPT:SophosCentralCustomerTenants)) -or ($ForceTenantRefresh -eq $true)) { try { $SCRIPT:SophosCentralCustomerTenants = Get-SophosCentralCustomerTenant } catch { throw 'Unable to retrieve customer/enterprise tenants using Get-SophosCentralCustomerTenant' } } if (-not($CustomerTenantID)) { $tenantInfo = $SCRIPT:SophosCentralCustomerTenants | Where-Object { $_.Name -like $CustomerNameSearch } switch ($tenantInfo.count) { { $PSItem -eq 1 } { Write-Verbose "1 customer tenants returned: $($tenantInfo.Name)" } { $PSItem -gt 1 } { throw "$PSItem customer tenants returned: " + (($tenantInfo).name -join ';') } { $PSItem -lt 1 } { throw "$PSItem customer tenants returned" } } } else { $tenantInfo = $SCRIPT:SophosCentralCustomerTenants | Where-Object { $_.ID -eq $CustomerTenantID } } if ($null -ne $tenantInfo) { $SCRIPT:SophosCentral.RegionEndpoint = $tenantInfo.apiHost if ($SCRIPT:SophosCentral.CustomerTenantID) { $SCRIPT:SophosCentral.CustomerTenantID = $tenantInfo.id } else { $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name CustomerTenantID -Value $tenantInfo.id } if ($SCRIPT:SophosCentral.CustomerTenantName) { $SCRIPT:SophosCentral.CustomerTenantName = $tenantInfo.Name } else { $SCRIPT:SophosCentral | Add-Member -MemberType NoteProperty -Name CustomerTenantName -Value $tenantInfo.Name } if (($PerformConnectionTest -eq $true) -and ($SkipConnectionTest -eq $false)) { try { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseDeclaredVarsMoreThanAssignments', '', Justification = 'Used for checking permissions to the tenant')] $alertTest = Get-SophosCentralAlert } catch { throw "Unable to connect to the tenant, you may not have permissions to the tenant.`n`n $($_)" } } } else { throw 'Tenant does not exist' } } # ./SophosCentral/public/Get-SophosCentralAccessToken.ps1 function Get-SophosCentralAccessToken { <# .SYNOPSIS Get all access tokens for a tenant. Currently the only type is 'sophosLinuxSensor' .DESCRIPTION Get all access tokens for a tenant. Currently the only type is 'sophosLinuxSensor' .EXAMPLE Get-SophosCentralAccessToken .LINK https://developer.sophos.com/docs/accounts-v1/1/routes/access-tokens/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.GlobalEndpoint + '/accounts/v1/access-tokens') Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralAccountHealthCheck.ps1 function Get-SophosCentralAccountHealthCheck { <# .SYNOPSIS The Account Health Check API allows you to retrieve a health report for your Sophos Central account indicating whether you are making the best use of your Sophos security products. .DESCRIPTION The Account Health Check API allows you to retrieve a health report for your Sophos Central account indicating whether you are making the best use of your Sophos security products. .EXAMPLE Get-SophosCentralAccountHealthCheck .LINK https://developer.sophos.com/account-health-check #> [CmdletBinding()] param ( ) Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/account-health-check/v1/health-check') Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralAdmin.ps1 function Get-SophosCentralAdmin { <# .SYNOPSIS Get admins listed in Sophos Central .DESCRIPTION Get admins listed in Sophos Central .EXAMPLE Get-SophosCentralAdmin .LINK https://developer.sophos.com/docs/common-v1/1/routes/admins/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected $uriChild = '/common/v1/admins' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralAdminRole.ps1 function Get-SophosCentralAdminRole { <# .SYNOPSIS Get admin roles in Sophos Central .DESCRIPTION Get admin roles listed in Sophos Central .EXAMPLE Get-SophosCentralAdminRole .LINK https://developer.sophos.com/docs/common-v1/1/routes/roles/get #> [CmdletBinding()] param ( [ValidateSet('predefined', 'custom')] [string]$Type, [ValidateSet('user', 'service')] [string]$PrincipalType ) Test-SophosCentralConnected $uriChild = '/common/v1/roles' $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralAlert.ps1 function Get-SophosCentralAlert { <# .SYNOPSIS Get alerts listed in Sophos Central .DESCRIPTION Get alerts listed in Sophos Central .PARAMETER Product Alerts for a product. You can query by product types. .PARAMETER Category Alert category. You can query by different categories. .PARAMETER Severity Alerts for a specific severity level. You can query by severity levels. .EXAMPLE Get-SophosCentralAlert Get all active alerts in the tenant .EXAMPLE Get-SophosCentralAlert -Product 'server' -Severity 'high Get all alerts relating to Sophos Central for Server protection wih High severity .LINK https://developer.sophos.com/docs/common-v1/1/routes/alerts/get .LINK https://developer.sophos.com/docs/common-v1/1/routes/alerts/search/post #> [CmdletBinding()] [Alias('Get-SophosCentralAlerts')] param ( [Parameter(ParameterSetName = 'search')] [ValidateSet('other', 'endpoint', 'server', 'mobile', 'encryption', 'emailGateway', 'webGateway', 'phishThreat', 'wireless', 'iaas', 'firewall')] [string[]]$Product, [Parameter(ParameterSetName = 'search')] [ValidateSet('azure', 'adSync', 'applicationControl', 'appReputation', 'blockListed', 'connectivity', 'cwg', 'denc', 'downloadReputation', 'endpointFirewall', 'fenc', 'forensicSnapshot', 'general', 'iaas', 'iaasAzure', 'isolation', 'malware', 'mtr', 'mobiles', 'policy', 'protection', 'pua', 'runtimeDetections', 'security', 'smc', 'systemHealth', 'uav', 'uncategorized', 'updating', 'utm', 'virt', 'wireless', 'xgEmail')] [string[]]$Category, [Parameter(ParameterSetName = 'search')] [ValidateSet('low', 'medium', 'high')] [string[]]$Severity ) Test-SophosCentralConnected if ($PsCmdlet.ParameterSetName -ne 'search') { $uriChild = '/common/v1/alerts' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } elseif ($PsCmdlet.ParameterSetName -eq 'search') { $uriChild = '/common/v1/alerts/search' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $searchParam = @{} if ($Product) { $searchParam.Add('product', $Product) } if ($Category) { $searchParam.Add('category', $Category) } if ($Severity) { $searchParam.Add('severity', $Severity) } Invoke-SophosCentralWebRequest -Uri $uri -Body $searchParam -Method Post } } # ./SophosCentral/public/Get-SophosCentralAllowedItem.ps1 function Get-SophosCentralAllowedItem { <# .SYNOPSIS Get Endpoint allowed Items .DESCRIPTION Get Endpoint allowed Items .EXAMPLE Get-SophosCentralAllowedItem .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/settings/allowed-items/get #> [CmdletBinding()] [Alias('Get-SophosCentralAllowedItems')] param ( ) Test-SophosCentralConnected $uriChild = '/endpoint/v1/settings/allowed-items' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralBlockedItem.ps1 function Get-SophosCentralBlockedItem { <# .SYNOPSIS Get Endpoint blocked Items .DESCRIPTION Get Endpoint blocked Items .EXAMPLE Get-SophosCentralBlockedItem .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/settings/blocked-items/get #> [CmdletBinding()] [Alias('Get-SophosCentralBlockedItems')] param ( ) Test-SophosCentralConnected $uriChild = '/endpoint/v1/settings/blocked-items' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralCustomerTenant.ps1 function Get-SophosCentralCustomerTenant { <# .SYNOPSIS List Sophos Central customer/enterprise tenants that can be connected too (for Sophos partners/enterprise customers only) .DESCRIPTION List Sophos Central customer/enterprise tenants that can be connected too (for Sophos partners/enterprise customers only) .EXAMPLE Get-SophosCentralCustomerTenant .LINK https://developer.sophos.com/docs/partner-v1/1/routes/tenants/get .LINK https://developer.sophos.com/getting-started .LINK https://developer.sophos.com/getting-started-organization #> [CmdletBinding()] [Alias('Get-SophosCentralCustomerTenants', 'Get-SophosCentralEnterpriseTenant')] param ( ) Test-SophosCentralConnected if (((Test-SophosPartner) -or (Test-SophosEnterprise)) -eq $false) { throw 'You are not currently logged in using a Sophos Central Partner/Enterprise Service Principal' } try { $header = Get-SophosCentralAuthHeader -PartnerInitial } catch { throw $_ } switch ($SCRIPT:SophosCentral.IDType) { 'partner' { $uri = [System.Uri]::New('https://api.central.sophos.com/partner/v1/tenants?pageTotal=true') } 'organization' { $uri = [System.Uri]::New('https://api.central.sophos.com/organization/v1/tenants?pageTotal=true') } } Invoke-SophosCentralWebRequest -Uri $uri -CustomHeader $header } # ./SophosCentral/public/Get-SophosCentralEndpoint.ps1 function Get-SophosCentralEndpoint { <# .SYNOPSIS Get Endpoints in Sophos Central (Workstations, Servers) .DESCRIPTION Get Endpoints in Sophos Central (Workstations, Servers) .PARAMETER HealthStatus Find endpoints by health status. The following values are allowed: bad, good, suspicious, unknown .PARAMETER Type Find endpoints by type. The following values are allowed: computer, server, securityVm .PARAMETER TamperProtectionEnabled Find endpoints by whether Tamper Protection is turned on. .PARAMETER LockdownStatus Find endpoints by lockdown status. .PARAMETER IsolationStatus Find endpoints by isolation status. .PARAMETER HostnameContains Find endpoints where the hostname contains the given string. Only the first 10 characters of the given string are matched. .PARAMETER IpAddresses Find endpoints by IP addresses. .PARAMETER MacAddresses Find endpoints by MAC Addresses. Can be in EUI-48 or EUI-64 format, case insensitive, colon, hyphen or dot separated, or with no separator e.g. 01:23:45:67:89:AB, 01-23-45-67-89-ab, 0123.4567.89ab, 0123456789ab, 01:23:45:67:89:ab:cd:ef. .PARAMETER LastSeenBefore Find endpoints last seen before this. Accepts either [datetime] or a string in the ISO 8601 Duration format (https://en.wikipedia.org/wiki/ISO_8601#Durations) .PARAMETER LastSeenAfter Find endpoints last seen after this. Accepts either [datetime] or a string in the ISO 8601 Duration format (https://en.wikipedia.org/wiki/ISO_8601#Durations) .PARAMETER ID Find endpoints with the specified IDs. .EXAMPLE Get-SophosCentralEndpoint List all endpoints in the tenant .EXAMPLE Get-SophosCentralEndpoint -HealthStatus 'bad' List all endpoints with a bad health status .EXAMPLE Get-SophosCentralEndpoint -TamperProtectionEnabled $false List all endpoints with tamper protection disabled .EXAMPLE Get-SophosCentralEndpoint -LastSeenBefore '-P90D' List all endpoints seen more than 90 day ago .EXAMPLE Get-SophosCentralEndpoint -LastSeenAfter '-P1D' List all endpoints seen in the last 1 day .EXAMPLE Get-SophosCentralEndpoint -LastSeenAfter (Get-Date).AddDays(-1) List all endpoints seen in the last 1 day .EXAMPLE Get-SophosCentralEndpoint -LastSeenAfter '-PT2H' List all endpoints seen in the last 2 hours .EXAMPLE Get-SophosCentralEndpoint -LastSeenAfter '-PT20M' List all endpoints seen in the last 20 minutes .EXAMPLE Get-SophosCentralEndpoint -LastSeenAfter '-P3DT4H5M0S' List all endpoints seen in the last 3 days 4 hours 5 minutes and 0 seconds .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/get #> [CmdletBinding()] [Alias('Get-SophosCentralEndpoints')] param ( [ValidateSet('bad', 'good', 'suspicious', 'unknown')] [string[]]$HealthStatus, [ValidateSet('computer', 'server', 'securityVm')] [string[]]$Type, [System.Boolean]$TamperProtectionEnabled, [ValidateSet('creatingWhitelist', 'installing', 'locked', 'notInstalled', 'registering', 'starting', 'stopping', 'unavailable', 'uninstalled', 'unlocked')] [string[]]$LockdownStatus, [ValidateSet('isolated', 'notIsolated')] [string]$IsolationStatus, [string]$HostnameContains, [string]$IpAddresses, [string]$MacAddresses, [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { throw "See 'Get-Help Get-SophosCentralEndpoint -Examples' for some examples" } } })] $LastSeenBefore, [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { throw "See 'Get-Help Get-SophosCentralEndpoint -Examples' for some examples" } } })] $LastSeenAfter, [ValidateScript({ if ($false -eq [System.Guid]::TryParse($_, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } })] [string[]] $ID ) Test-SophosCentralConnected # ID is ids in query string, update PSBoundParameters to match if ($ID.count -gt 0) { $PsBoundParameters.Add('ids', $PsBoundParameters['ID']) $null = $PsBoundParameters.Remove('ID') } $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/endpoints') $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointGroup.ps1 function Get-SophosCentralEndpointGroup { <# .SYNOPSIS Get Endpoint groups in the directory .DESCRIPTION Get Endpoint groups in the directory .EXAMPLE Get-SophosCentralEndpointGroup .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoint-groups/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/endpoint-groups') Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointInstallerLink.ps1 function Get-SophosCentralEndpointInstallerLink { <# .SYNOPSIS Get all the endpoint installer links for a tenant. .DESCRIPTION Get all the endpoint installer links for a tenant. .EXAMPLE Get-SophosCentralEndpointInstallerLink .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/downloads/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected $uriChild = '/endpoint/v1/downloads' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointMigration.ps1 function Get-SophosCentralEndpointMigration { <# .SYNOPSIS Gets all migration jobs for the tenant. .DESCRIPTION Gets all migration jobs for the tenant. .EXAMPLE Get-SophosCentralEndpointMigration .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/migrations/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected Show-UntestedWarning $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/migrations') Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointMigrationStatus.ps1 function Get-SophosCentralEndpointMigrationStatus { <# .SYNOPSIS Gets the status of endpoints that are being migrated. .DESCRIPTION Gets the status of endpoints that are being migrated. This should be able to be run in either tenant. .EXAMPLE Get-SophosCentralEndpointMigrationStatus -MigrationID 'bbc35a7e-860b-43bc-b668-d48b57cb38ed' .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/migrations/%7BmigrationJobId%7D/endpoints/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$MigrationID ) Test-SophosCentralConnected Show-UntestedWarning $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + "/endpoint/v1/migrations/$($MigrationID)/endpoints?pageTotal=true") Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointPolicy.ps1 function Get-SophosCentralEndpointPolicy { <# .SYNOPSIS Get Policies .DESCRIPTION Get Policies .EXAMPLE Get-SophosCentralEndpointPolicy -All Get all policies .EXAMPLE Get-SophosCentralEndpointPolicy -BasePolicy Get base policies .LINK https://developer.sophos.com/endpoint-policies#get-all-policies #> [CmdletBinding()] [Alias('Get-SophosCentralEndpointPolicies')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseProcessBlockForPipelineCommand', 'All', Justification = 'We do not need to use the variable', Scope = 'Function')] param ( [Parameter(Mandatory = $false, ParameterSetName = 'ID')] [Alias('ID')] [string]$PolicyId, [Parameter(Mandatory = $false, ParameterSetName = 'Base')] [switch]$BasePolicy, [Parameter(Mandatory = $false, ParameterSetName = 'All')] [switch]$All ) Test-SophosCentralConnected if ($BasePolicy) { $PolicyId = 'base' } $uriChild = '/endpoint/v1/policies' if ($All) { $uriChild = $uriChild + '?pageTotal=true' } elseif (-not([string]::IsNullOrEmpty($PolicyId))) { $uriChild = "$($uriChild)/$($PolicyId)" } $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralEndpointTamperProtection.ps1 function Get-SophosCentralEndpointTamperProtection { <# .SYNOPSIS Get Tamper Protection Status .DESCRIPTION Get Tamper Protection Status .PARAMETER EndpointID The ID of the Endpoint. Use Get-SophosCentralEndpoints to list them .EXAMPLE Get-SophosCentralEndpointTamperProtection -EndpointID '23a920fa-9a34-4869-bc3d-a1626e50f670' .EXAMPLE Get-SophosCentralEndpointTamperProtection -EndpointID (Get-SophosCentralEndpoints).ID .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/%7BendpointId%7D/tamper-protection/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID ) begin { Test-SophosCentralConnected $uriChild = '/endpoint/v1/endpoints/{0}/tamper-protection' $uriString = $SCRIPT:SophosCentral.RegionEndpoint + $uriChild } process { foreach ($endpoint in $EndpointID) { $uri = [System.Uri]::New($uriString -f $endpoint) Invoke-SophosCentralWebRequest -Uri $uri } } } # ./SophosCentral/public/Get-SophosCentralEvent.ps1 function Get-SophosCentralEvent { <# .SYNOPSIS Get events within the last 24 hours. .DESCRIPTION Get events within the last 24 hours. .PARAMETER Limit The maximum number of items to return, min is 200, max is 1000. .PARAMETER FromDate The starting date from which alerts will be retrieved. Must be within last 24 hours. .PARAMETER ExcludeType List of types of events to be excluded. .EXAMPLE Get-SophosCentralEvent Get the most recent events .EXAMPLE Get-SophosCentralEvent -FromDate (Get-Date).AddMinutes(-15) Get events from the last 15 minutes .EXAMPLE Get-SophosCentralEvent -ExcludeType 'Event::Endpoint::UpdateSuccess', 'Event::Endpoint::Application::Detected' Get latest events excluding UpdateSuccess and Application Detected events .EXAMPLE Get-SophosCentralEvent -Limit 205 Get 205 of the the most recent events .LINK https://developer.sophos.com/docs/siem-v1/1/routes/events/get #> [CmdletBinding(DefaultParameterSetName = 'nullParam')] param ( [ValidateRange(200, 1000)] [int]$Limit = 200, [ValidateScript({ if (($_ - [datetime]::Now).TotalHours -gt 24) { throw 'Must be within 24 hours' } return $true })] [datetime]$FromDate, [string[]]$ExcludeType ) Test-SophosCentralConnected # Convert datetime to unix timestamp in UTC if ($null -ne $FromDate) { $timestamp = Get-Date -Date $FromDate.ToUniversalTime() -UFormat '%s' if ($timestamp.IndexOf('.') -gt 0) { # Powershell v5 returns a value with .#### where pwsh 7 does not... $timestamp = $timestamp.Substring(0, $timestamp.IndexOf('.')) } $PsBoundParameters.Add('from_date', $timestamp) $null = $PsBoundParameters.Remove('FromDate') } # Transform into API name if ($ExcludeType.Count -gt 0) { $PsBoundParameters.Add('exclude_types', $PsBoundParameters['ExcludeType']) $null = $PsBoundParameters.Remove('ExcludeType') } $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/siem/v1/events') $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralFirewall.ps1 function Get-SophosCentralFirewall { <# .SYNOPSIS Get firewalls in Sophos Central .DESCRIPTION Get firewalls in Sophos Central .EXAMPLE Get-SophosCentralFirewall .PARAMETER GroupId Firewall group ID, or 'ungrouped' .PARAMETER Search Search .EXAMPLE Get-SophosCentralFirewall -GroupId 'ungrouped' List firewalls that aren't part of a firewall group. .EXAMPLE Get-SophosCentralFirewall -GroupId 'e25ec1f2-04f5-477e-a10d-71f2e039ebaf' List firewalls in the group e25ec1f2-04f5-477e-a10d-71f2e039ebaf .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewalls/get #> [CmdletBinding()] param ( [ValidateScript({ if ($_ -eq 'ungrouped') { return $true } elseif ($false -eq [System.Guid]::TryParse($_, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } })] [string]$GroupId, [string]$Search ) Test-SophosCentralConnected $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewalls?pageTotal=true') $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralFirewallGroup.ps1 function Get-SophosCentralFirewallGroup { <# .SYNOPSIS Get firewall groups in Sophos Central .DESCRIPTION Get firewall groups in Sophos Central .EXAMPLE Get-SophosCentralFirewallGroup .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewall-groups/get #> [CmdletBinding()] param ( [System.Boolean]$RecurseSubgroups, [string]$Search ) Test-SophosCentralConnected $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewall-groups') $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralFirewallUpdate.ps1 function Get-SophosCentralFirewallUpdate { <# .SYNOPSIS Get firmware updates available on a firewall .DESCRIPTION Get firmware updates available on a firewall .PARAMETER FirewallID The ID of the firewall. Use Get-SophosCentralFirewall to list them .EXAMPLE Get-SophosCentralFirewallUpdate -FirewallID "6d41e78e-0360-4de3-8669-bb7b797ee515" .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewalls/actions/firmware-upgrade-check/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$FirewallID ) begin { Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewalls/actions/firmware-upgrade-check') $body = @{ firewalls = @() } } process { foreach ($firewall in $FirewallID) { $body['firewalls'] += $firewall } Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } # ./SophosCentral/public/Get-SophosCentralLiveDiscoverQuery.ps1 function Get-SophosCentralLiveDiscoverQuery { <# .SYNOPSIS Get queries matching the given filters. .DESCRIPTION Get queries matching the given filters. .EXAMPLE Get-SophosCentralLiveDiscoverQuery .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/get .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/%7BqueryId%7D/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$categoryId, [Parameter(Mandatory = $false)] [string]$search, [Parameter(Mandatory = $false)] [array]$searchFields, [Parameter(Mandatory = $false)] [ValidateSet('categories', 'code', 'createdAt', 'dataSource', 'description', 'id', 'name', 'performance', 'supportedOSes', 'template', 'type', 'variables')] [array]$Fields, [Parameter(Mandatory = $false)] [string]$QueryID ) $uriChild = '/live-discover/v1/queries' if ($null -ne $QueryID) { $uriChild = $uriChild + '/' + $QueryID } $uriChild = $uriChild + '?pageTotal=true' $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralLiveDiscoverQueryCategory.ps1 function Get-SophosCentralLiveDiscoverQueryCategory { <# .SYNOPSIS Get queries matching the given filters. .DESCRIPTION Get queries matching the given filters. .EXAMPLE Get-SophosCentralLiveDiscoverQueryCategory .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/get #> [CmdletBinding()] [Alias('Get-SophosCentralLiveDiscoverQueryCategories')] param ( [Parameter(Mandatory = $false)] [array]$Fields, [Parameter(Mandatory = $false)] [string]$CategoryID ) $uriChild = '/live-discover/v1/queries/categories' if ($null -ne $categoryID) { $uriChild = $uriChild + '/' + $categoryID } $uriChild = $uriChild + '?pageTotal=true' $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $PsBoundParameters Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralLiveDiscoverQueryRun.ps1 function Get-SophosCentralLiveDiscoverQueryRun { <# .SYNOPSIS Get the list of query runs, or return the results of one run .DESCRIPTION Get the list of query runs, or return the results of one run .EXAMPLE Get-SophosCentralLiveDiscoverQueryRun .EXAMPLE Get-SophosCentralLiveDiscoverQueryRun -RunID 'a9a5c6a3-5467-4bf3-87b0-ebdd4022056a' .EXAMPLE Get-SophosCentralLiveDiscoverQueryRun-RunID 'a9a5c6a3-5467-4bf3-87b0-ebdd4022056a' -Results .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/runs/get .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/runs/%7BrunId%7D/get .LINK https://developer.sophos.com/docs/live-discover-v1/1/routes/queries/runs/%7BrunId%7D/results/get #> [CmdletBinding(DefaultParameterSetName = 'nullParam')] param ( [Parameter(Mandatory = $false, ParameterSetName = 'Results')] [Parameter(Mandatory = $false, ParameterSetName = 'Endpoints')] [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [array]$Sort, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [Parameter(Mandatory = $false, ParameterSetName = 'RunID')] [array]$Fields, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [string]$QueryId, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [string]$CategoryId, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [ValidateSet('pending', 'started', 'finished')] [array]$Status, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [ValidateSet('notAvailable', 'succeeded', 'failed', 'timedOut')] [array]$Result, [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [ValidateSet('service', 'user')] [array]$createdByPrincipalType, [Parameter(Mandatory = $true, ParameterSetName = 'Results')] [Parameter(Mandatory = $true, ParameterSetName = 'Endpoints')] [Parameter(Mandatory = $true, ParameterSetName = 'RunID')] [string]$RunID, [Parameter(Mandatory = $true, ParameterSetName = 'Results')] [switch]$Results, [Parameter(Mandatory = $true, ParameterSetName = 'Endpoints')] [switch]$Endpoints ) $uriChild = '/live-discover/v1/queries/runs' if ($null -ne $RunID) { $uriChild = $uriChild + '/' + $RunID if ($Results -eq $true) { $uriChild = $uriChild + '/results' } if ($endpoints -eq $true) { $uriChild = $uriChild + '/endpoints' } } $uriChild = $uriChild + '?pageTotal=true' $uriTemp = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $filteredPsBoundParameters = $PsBoundParameters #filter out parameters not needed for Query $uri = New-UriWithQuery -Uri $uriTemp -OriginalPsBoundParameters $filteredPsBoundParameters -filteredParameters ('Results', 'Endpoints', 'RunID') Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralPartnerAdmin.ps1 function Get-SophosCentralPartnerAdmin { <# .SYNOPSIS List all partner admins. .DESCRIPTION List all partner admins. .EXAMPLE Get-SophosCentralPartnerAdmin .LINK https://developer.sophos.com/docs/partner-v1/1/routes/admins/get #> [CmdletBinding()] param ( ) Test-SophosCentralConnected if ((Test-SophosPartner) -eq $false) { throw 'You are not currently logged in using a Sophos Central Partner Service Principal' } try { $header = Get-SophosCentralAuthHeader -PartnerInitial } catch { throw $_ } $uri = [System.Uri]::New('https://api.central.sophos.com/partner/v1/admins') Invoke-SophosCentralWebRequest -Uri $uri -CustomHeader $header } # ./SophosCentral/public/Get-SophosCentralPartnerBilling.ps1 function Get-SophosCentralPartnerBilling { <# .SYNOPSIS Get billing usage report .DESCRIPTION Get billing usage report .EXAMPLE Get-SophosCentralPartnerBilling -LastMonth .EXAMPLE Get-SophosCentralPartnerBilling -Month 5 -Year 2022 .LINK https://developer.sophos.com/docs/partner-v1/1/routes/billing/usage/%7Byear%7D/%7Bmonth%7D/get #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory = $true, ParameterSetName = 'Custom')] [ValidateRange(1, 12)] [int]$Month, [Parameter(Position = 1, Mandatory = $true, ParameterSetName = 'Custom')] [ValidateRange(2000, 2050)] [int]$Year, [Parameter(Position = 2, ParameterSetName = 'LastMonth')] [switch]$LastMonth ) Test-SophosCentralConnected if ((Test-SophosPartner) -eq $false) { throw 'You are not currently logged in using a Sophos Central Partner Service Principal' } if ($LastMonth) { $date = (Get-Date).AddMonths(-1) $Year = $date.Year $Month = $date.Month } try { $header = Get-SophosCentralAuthHeader -PartnerInitial } catch { throw $_ } $uri = [System.Uri]::New("https://api.central.sophos.com/partner/v1/billing/usage/$year/$month") Invoke-SophosCentralWebRequest -Uri $uri -CustomHeader $header } # ./SophosCentral/public/Get-SophosCentralTenantInfo.ps1 function Get-SophosCentralTenantInfo { <# .SYNOPSIS Get information of the tenant the service principal resides in .DESCRIPTION Get information of the tenant the service principal resides in .EXAMPLE Get-SophosCentralTenantInfo .LINK https://developer.sophos.com/docs/whoami-v1/1/routes/get #> Test-SophosCentralConnected $uri = [System.Uri]::New('https://api.central.sophos.com/whoami/v1') $header = Get-SophosCentralAuthHeader -Initial Invoke-SophosCentralWebRequest -Uri $uri -CustomHeader $header } # ./SophosCentral/public/Get-SophosCentralUser.ps1 function Get-SophosCentralUser { <# .SYNOPSIS Get users listed in Sophos Central .DESCRIPTION Get users listed in Sophos Central .EXAMPLE Get-SophosCentralUser -ID 0eb3048c-ed91-4a01-8d39-923c6ca90868 Find the user with the ID of 0eb3048c-ed91-4a01-8d39-923c6ca90868 .EXAMPLE Get-SophosCentralUser -Search 'John' Search for users full name containing John .EXAMPLE Get-SophosCentralUser -Search 'Smith' -SearchField 'lastName' Search for users last name containing Smith .EXAMPLE Get-SophosCentralUser -SourceType 'activeDirectory' Search for users sourced from Active Directory .PARAMETER ID ID to match .PARAMETER Search Search for items that match the given terms .PARAMETER SearchFields Search only within the specified fields. When not specified, the default behavior is to search the full names of users only. .PARAMETER SourceType Types of sources of directory information. All users and groups created using this API have the source type custom. All users and groups synced from Active Directory or Azure Active Directory have the source type activeDirectory or azureActiveDirectory. .PARAMETER GroupId Search for users in a group that has this ID. .PARAMETER Domain List the items that match the given domain. .LINK https://developer.sophos.com/docs/common-v1/1/routes/directory/users/get #> [CmdletBinding()] [Alias('Get-SophosCentralUsers')] param ( [ValidateScript({ if ($false -eq [System.Guid]::TryParse($_, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } })] [string]$ID, [string]$Search, [ValidateSet('name', 'firstName', 'lastName', 'email', 'exchangeLogin')] [string]$SearchField, [ValidateSet('custom', 'activeDirectory', 'azureActiveDirectory')] [string]$SourceType, [ValidateScript({ if ($false -eq [System.Guid]::TryParse($_, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } })] [string]$GroupID, [string]$Domain ) Test-SophosCentralConnected $body = @{} if ($ID) { $body.Add('ids', $id) } if ($Search) { $body.Add('search', $Search) } if ($SearchField) { $body.Add('searchFields', $SearchField) } if ($SourceType) { $body.Add('sourceType', $SourceType) } if ($GroupID) { $body.Add('groupId', $GroupID) } if ($Domain) { $body.Add('domain', $Domain) } $uriChild = '/common/v1/directory/users?pageTotal=true' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) if ($body.Keys.Count -eq 0) { Invoke-SophosCentralWebRequest -Uri $uri } else { Invoke-SophosCentralWebRequest -Uri $uri -Body $body } } # ./SophosCentral/public/Get-SophosCentralUserGroup.ps1 function Get-SophosCentralUserGroup { <# .SYNOPSIS Get User Groups listed in Sophos Central .DESCRIPTION Get User Groups listed in Sophos Central .EXAMPLE Get-SophosCentralUserGroup .LINK https://developer.sophos.com/docs/common-v1/1/routes/directory/user-groups/get #> [CmdletBinding()] [Alias('Get-SophosCentralUserGroups')] param ( ) Test-SophosCentralConnected $uriChild = '/common/v1/directory/user-groups' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralXDRQuery.ps1 function Get-SophosCentralXDRQuery { <# .SYNOPSIS Get the details of a query. .DESCRIPTION Get the details of a query. .EXAMPLE Get-SophosCentralXDRQuery .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/%7BqueryId%7D/get .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$QueryID ) Show-UntestedWarning $uriChild = '/xdr-query/v1/queries' if ($null -ne $QueryID) { $uriChild = $uriChild + '/' + $QueryID } $uriChild = $uriChild + '?pageTotal=true' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralXDRQueryCategory.ps1 function Get-SophosCentralXDRQueryCategory { <# .SYNOPSIS Fetch all categories, built-in as well as custom .DESCRIPTION Fetch all categories, built-in as well as custom .EXAMPLE Get-SophosCentralXDRQueryCategory .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/categories/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$CategoryID ) Show-UntestedWarning $uriChild = '/xdr-query/v1/queries/categories' if ($null -ne $CategoryID) { $uriChild = $uriChild + '/' + $CategoryID } $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Get-SophosCentralXDRQueryRun.ps1 function Get-SophosCentralXDRQueryRun { <# .SYNOPSIS Get the list of query runs, or return the results of one run .DESCRIPTION Get the list of query runs, or return the results of one run .EXAMPLE Get-SophosCentralXDRQueryRun .EXAMPLE Get-SophosCentralXDRQueryRun -RunID 'a9a5c6a3-5467-4bf3-87b0-ebdd4022056a' .EXAMPLE Get-SophosCentralXDRQueryRun -RunID 'a9a5c6a3-5467-4bf3-87b0-ebdd4022056a' -Results .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/get .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/%7BrunId%7D/get .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/%7BrunId%7D/results/get #> [CmdletBinding(DefaultParameterSetName='nullParam')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Run ID')] [Parameter(Mandatory = $true, ParameterSetName = 'Results')] [string]$RunID, [Parameter(Mandatory = $true, ParameterSetName = 'Results')] [switch]$Results ) $uriChild = '/xdr-query/v1/queries/runs' if ($null -ne $RunID) { $uriChild = $uriChild + '/' + $RunID if ($Results -eq $true) { $uriChild = $uriChild + '/results' } } $uriChild = $uriChild + '?pageTotal=true' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) Invoke-SophosCentralWebRequest -Uri $uri } # ./SophosCentral/public/Invoke-SophosCentralEndpointInstallerDownload.ps1 function Invoke-SophosCentralEndpointInstallerDownload { <# .SYNOPSIS Download the endpoint installer. .DESCRIPTION Download the endpoint installer. .EXAMPLE Invoke-SophosCentralEndpointInstallerDownload -RequestedProduct interceptX -Platform windows -FilePath 'C:\SophosSetup.exe' .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/downloads/get #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateSet('coreAgent', 'interceptX', 'xdr', 'endpointProtection', 'deviceEncryption', 'mtr', 'mtd', 'ztna')] [string]$RequestedProduct = 'interceptX', [Parameter(Mandatory = $false)] [ValidateSet('windows', 'linux', 'macOS')] [string]$Platform = 'windows', [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateScript({ if ($_ | Test-Path) { throw 'File already exists' } return $true })] [System.IO.FileInfo]$FilePath ) Test-SophosCentralConnected $links = Get-SophosCentralEndpointInstallerLink foreach ($installers in $links.installers) { if (($installers.supportedProducts -contains $RequestedProduct) -and ($installers.platform -eq $Platform)) { Invoke-WebRequest -Uri $installers.downloadUrl -UseBasicParsing -OutFile $FilePath } } if (-not(Test-Path $FilePath)) { Write-Error 'Installer was not downloaded. Ensure you selected the correct product/platform' } } # ./SophosCentral/public/Invoke-SophosCentralEndpointMigrationReceive.ps1 function Invoke-SophosCentralEndpointMigrationReceive { <# .SYNOPSIS Create a migration job in the receiving tenant. .DESCRIPTION Create a migration job in the receiving tenant. This command will cause your session to connect to the destination tenant. This is Step 1 of a migration. .PARAMETER EndpointID The ID of the Endpoints. Use Get-SophosCentralEndpoints to list them .PARAMETER SourceTenantID The ID of the source tenant. Use Get-SophosCentralCustomerTenant to list them .PARAMETER DestinationTenantID The ID of the destination tenant. Use Get-SophosCentralCustomerTenant to list them .EXAMPLE $jobDetails = Invoke-SophosCentralEndpointMigrationReceive -EndpointID '6d41e78e-0360-4de3-8669-bb7b797ee515' -SourceTenantID 'c4ce7035-d6c1-44b9-9b11-b4a8b13e979b' -DestinationTenantID 'c924009e-1fac-4174-aace-8ccbe4296f95' .EXAMPLE $jobDetails = Invoke-SophosCentralEndpointMigrationReceive -EndpointID (Get-SophosCentralEndpoint).ID -SourceTenantID 'c4ce7035-d6c1-44b9-9b11-b4a8b13e979b' -DestinationTenantID 'c924009e-1fac-4174-aace-8ccbe4296f95' With this example you would connect to the source tenant first, so that '(Get-SophosCentralEndpoint).ID' runs in its context .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/migrations/post .LINK https://developer.sophos.com/endpoint-migrations #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID, [Parameter(Mandatory = $true)] [string]$SourceTenantID, [Parameter(Mandatory = $true)] [string]$DestinationTenantID, [switch]$Force ) begin { Test-SophosCentralConnected } process { if ($DestinationTenantID -ne $SCRIPT:SophosCentral.CustomerTenantID) { try { Write-Warning "Connecting to $($DestinationTenantID), this connection will overwrite the tenant you were connected to previously ($($SCRIPT:SophosCentral.CustomerTenantName))" Connect-SophosCentralCustomerTenant -CustomerTenantID $DestinationTenantId } catch { throw 'Unable to connect to the destination tenant, check the ID is correct and you have the correct permissions to it' } } $body = @{ 'fromTenant' = $SourceTenantID 'endpoints' = $EndpointID } $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/migrations') if ($Force -or $PSCmdlet.ShouldProcess('Create Receive Job', $DestinationTenantID )) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } end { } } # ./SophosCentral/public/Invoke-SophosCentralEndpointMigrationSend.ps1 function Invoke-SophosCentralEndpointMigrationSend { <# .SYNOPSIS Start a migration job in the sending tenant. .DESCRIPTION Start a migration job in the sending tenant. This command will cause your session to connect to the source tenant. This is Step 2 of a migration. .PARAMETER EndpointID The ID of the Endpoints. Use Get-SophosCentralEndpoints to list them .PARAMETER SourceTenantID The ID of the source tenant. Use Get-SophosCentralCustomerTenant to list them .PARAMETER MigrationID id returned from Invoke-SophosCentralEndpointMigrationReceive .PARAMETER MigrationToken token returned from Invoke-SophosCentralEndpointMigrationReceive .EXAMPLE $jobDetails = Invoke-SophosCentralEndpointMigrationSend -EndpointID '6d41e78e-0360-4de3-8669-bb7b797ee515','245fe806-9ff8-4da1-b136-eea2a1d14812' -SourceTenantID 'c4ce7035-d6c1-44b9-9b11-b4a8b13e979b' -MigrationID 'bbc35a7e-860b-43bc-b668-d48b57cb38ed' -MigrationToken 'eyJ0b2tlbiI6ICJUaGlzIGlzIG9ubHkgYSBzYW1wbGUgdG9rZW4uIn0=' .EXAMPLE $jobDetails = Invoke-SophosCentralEndpointMigrationSend -EndpointID (Get-SophosCentralEndpoint).ID -SourceTenantID 'c4ce7035-d6c1-44b9-9b11-b4a8b13e979b' With this example you would connect to the source tenant first, so that '(Get-SophosCentralEndpoint).ID' runs in its context .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/migrations/%7BmigrationJobId%7D/put .LINK https://developer.sophos.com/endpoint-migrations #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID, [Parameter(Mandatory = $true)] [string]$SourceTenantID, [Parameter(Mandatory = $true)] [string]$MigrationID, [Parameter(Mandatory = $true)] [string]$MigrationToken, [switch]$Force ) begin { Test-SophosCentralConnected } process { if ($SourceTenantID -ne $SCRIPT:SophosCentral.CustomerTenantID) { try { Write-Warning "Connecting to $($SourceTenantID), this connection will overwrite the tenant you were connected to previously ($($SCRIPT:SophosCentral.CustomerTenantName))" Connect-SophosCentralCustomerTenant -CustomerTenantID $SourceTenantID } catch { throw 'Unable to connect to the source tenant, check the ID is correct and you have the correct permissions to it' } } $body = @{ 'token' = $MigrationToken 'endpoints' = $EndpointID } $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/migrations/' + $MigrationID) if ($Force -or $PSCmdlet.ShouldProcess('Create Send Job', $SourceTenantID )) { Invoke-SophosCentralWebRequest -Uri $uri -Method Put -Body $body } } end { } } # ./SophosCentral/public/Invoke-SophosCentralEndpointScan.ps1 function Invoke-SophosCentralEndpointScan { <# .SYNOPSIS Trigger a scan on Endpoints in Sophos Central .DESCRIPTION Trigger a scan on Endpoints in Sophos Central .PARAMETER EndpointID The ID of the Endpoint. Use Get-SophosCentralEndpoints to list them .EXAMPLE Invoke-SophosCentralEndpointScan -EndpointID "6d41e78e-0360-4de3-8669-bb7b797ee515" .EXAMPLE Invoke-SophosCentralEndpointScan -EndpointID (Get-SophosCentralEndpoint).ID .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/%7BendpointId%7D/scans/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID ) begin { Test-SophosCentralConnected $uriChild = '/endpoint/v1/endpoints/{0}/scans' $uriString = $SCRIPT:SophosCentral.RegionEndpoint + $uriChild } process { foreach ($endpoint in $EndpointID) { $uri = [System.Uri]::New($uriString -f $endpoint) Invoke-SophosCentralWebRequest -Uri $uri -Method Post } } } # ./SophosCentral/public/Invoke-SophosCentralEndpointUpdate.ps1 function Invoke-SophosCentralEndpointUpdate { <# .SYNOPSIS Trigger an update on an Endpoint in Sophos Central .DESCRIPTION Trigger an update on an Endpoint in Sophos Central .PARAMETER EndpointID The ID of the Endpoint. Use Get-SophosCentralEndpoints to list them .EXAMPLE Invoke-SophosCentralEndpointUpdate -EndpointID "6d41e78e-0360-4de3-8669-bb7b797ee515" .EXAMPLE Invoke-SophosCentralEndpointUpdate -EndpointID (Get-SophosCentralEndpoint).ID .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/%7BendpointId%7D/update-checks/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID ) begin { Test-SophosCentralConnected $uriChild = '/endpoint/v1/endpoints/{0}/update-checks' $uriString = $SCRIPT:SophosCentral.RegionEndpoint + $uriChild } process { foreach ($endpoint in $EndpointID) { $uri = [System.Uri]::New($uriString -f $endpoint) Invoke-SophosCentralWebRequest -Uri $uri -Method Post } } } # ./SophosCentral/public/Invoke-SophosCentralFirewallApproval.ps1 function Invoke-SophosCentralFirewallApproval { <# .SYNOPSIS Approve management of a firewall .DESCRIPTION Approve management of a firewall .PARAMETER FirewallID The ID of the firewall. Use Get-SophosCentralFirewall to list them .EXAMPLE Invoke-SophosCentralFirewallApproval -FirewallID "6d41e78e-0360-4de3-8669-bb7b797ee515" .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewalls/%7BfirewallId%7D/action/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$FirewallID, [switch]$Force ) begin { Test-SophosCentralConnected $uriTemp = $SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewalls/{0}/action ' $body = @{ action = 'approveManagement' } } process { foreach ($firewall in $FirewallID) { $uri = [System.Uri]::New($uriTemp -f $firewall) if ($Force -or $PSCmdlet.ShouldProcess('Approve', $firewall)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } } } # ./SophosCentral/public/Invoke-SophosCentralFirewallUpdate.ps1 function Invoke-SophosCentralFirewallUpdate { <# .SYNOPSIS Trigger an update on an firewall in Sophos Central .DESCRIPTION Trigger an update on an firewall in Sophos Central .PARAMETER FirewallID The ID of the firewall. Use Get-SophosCentralFirewall to list them .PARAMETER UpgradeToVersion The version to upgrade to. Check available firmware updates using Get-SophosCentralFirewallUpdate .PARAMETER UpgradeAt The time to perform the update. If not specified it'll queue the update immediately .EXAMPLE Invoke-SophosCentralFirewallUpdate -FirewallID "6d41e78e-0360-4de3-8669-bb7b797ee515" -UpgradeToVersion 'some-version' .EXAMPLE Invoke-SophosCentralFirewallUpdate -FirewallID "6d41e78e-0360-4de3-8669-bb7b797ee515" -UpgradeToVersion 'some-version' -UpgradeAt (Get-Date).AddHours(8) .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewalls/actions/firmware-upgrade/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$FirewallID, [string]$UpgradeToVersion, [datetime]$UpgradeAt, [switch]$Force ) begin { Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewalls/actions/firmware-upgrade') $body = @{ firewalls = @() } } process { foreach ($firewall in $FirewallID) { $firewallHash = @{ id = $firewall upgradeToVersion = $UpgradeToVersion } if ($UpgradeAt) { $UpgradeAt = $UpgradeAt.ToUniversalTime().ToString('u').Replace(' ', 'T') $firewallHash.Add('upgradeAt', $UpgradeAt) } $body['firewalls'] += $firewallHash } if ($Force -or $PSCmdlet.ShouldProcess('Update', ($FirewallID -join ', '))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } } # ./SophosCentral/public/Invoke-SophosCentralLiveDiscoverQueryRun.ps1 function Invoke-SophosCentralLiveDiscoverQueryRun { <# .SYNOPSIS Run a saved EDR query or an ad hoc query on remote endpoints. .DESCRIPTION Run a saved EDR query or an ad hoc query on remote endpoints. .PARAMETER CustomBody The query to run as a hashtable, see this for query options - https://developer.sophos.com/docs/live-discover-query-v1/1/routes/queries/runs/post The values in the example bodies below may not be correct (such as the variables sub hash tables), but the structure of the hashtable should be correct .PARAMETER categoryId string (uuid) Query category ID. .PARAMETER queryId string (uuid) Saved query ID. .PARAMETER queryName string Name for the ad hoc query. 1 ≤ length ≤ 300. .PARAMETER query string SQL statement for the query. This can contain replacement variables wrapped in $$ (double dollar sign) delimiters. 15 ≤ length ≤ 50000 .PARAMETER variables Values of variables to be replaced in the template SQL. Array of hashes each contains the following keys: name Variable name dataType Data types supported for EDR Data Lake queries. The following values are allowed: double, integer, text, dateTime, boolean value String value of the variable. pivotType The meaning of an input parameter of a query. The following values are allowed: deviceId, deviceName, sophosPid, ipAddress, username, sha256, filePath, registryKey, url Filter parameters - up to 5 may be specified - if no filter parameter are specified the matchEndpoints=all is added .PARAMETER healthStatus array Find endpoints by health status. .PARAMETER type array Find endpoints by type. .PARAMETER tamperProtectionEnabled boolean Find endpoints by whether Tamper Protection is turned on. .PARAMETER lockdownStatus array Find endpoints by lockdown status. .PARAMETER ids array Find endpoints with the specified IDs. Must contain from 1 to 1000 items. .PARAMETER lastSeenBefore string Find endpoints that were last seen before the given date and time (UTC) or a duration relative to the current date and time (exclusive). .PARAMETER lastSeenAfter string Find endpoints that were last seen after the given date and time (UTC) or a duration relative to the current date and time (inclusive). .PARAMETER hostnameContains string Find endpoints where the hostname contains the given string. .PARAMETER associatedPersonContains string Find endpoints where the name of the person associated with the endpoint contains the given string. .PARAMETER groupNameContains string Find endpoints where the name of the group the endpoint is in contains the given string. .PARAMETER os array Matches endpoints with any of the supplied operating system versions. .PARAMETER ipAddresses array Find endpoints by IP addresses. .PARAMETER search string Term to search for in the specified search fields. .PARAMETER searchFields array List of search fields for finding the given search term. Defaults to all applicable fields. .EXAMPLE Full custom body: $body = @{ 'matchEndpoints' = @{ 'filters' = @( @{ 'hostnameContains' = '17' } ) } 'adHocQuery' = @{ 'template' = 'select * from file WHERE path = ''c:\windows\system32\drivers\etc\hosts''' 'name' = 'HostFile' } } $query = Invoke-SophosCentralLiveDiscoverQueryRun -customBody $body .EXAMPLE Custom query with filters: Invoke-SophosCentralLiveDiscoverQueryRun -query "select * from file WHERE path = 'c:\windows\system32\drivers\etc\hosts'" -endpointFilters (@{hostnameContains="17"},@{type=@("computer")}) .EXAMPLE Invoke-SophosCentralLiveDiscoverQueryRun -query "select * from file WHERE path = 'c:\windows\system32\drivers\etc\hosts'" -ipAddresses ("192.168.0.1") -hostnameContains "cthulu" .EXAMPLE Custom query with variables: Invoke-SophosCentralLiveDiscoverQueryRun -query 'select * from file WHERE path = $$path$$' -ipAddresses ("192.168.0.1") -variables (@{name='path';dataType='text';value='c:\windows\system32\drivers\etc\host'}) .EXAMPLE Canned query with variables and filter: Variables are an array of hashes!: Invoke-SophosCentralLiveDiscoverQueryRun -queryID c2942032-fecc-4b04-b3e8-f0485bc3f40a -variables @( @{name='start_time';dataType='dateTime';value=(get-date).addDays(-5)}, @{name='ip_address';dataType='text';value='8.8.8.8'}, @{name='end_time';dataType='dateTime';value=get-date}) -ipAddresses ("192.168.0.1") .LINK https://developer.sophos.com/docs/Live-Discover-query-v1/1/routes/queries/runs/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ParameterSetName = 'CustomBody')] [hashtable]$customBody, [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [string]$categoryId, [Parameter(Mandatory = $true, ParameterSetName = 'CannedQuery')] [string]$queryId, [Parameter(Mandatory = $true, ParameterSetName = 'CustomQuery')] [string]$query, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [string]$queryName = 'AdHoc', [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateSet('good', 'suspicious', 'bad', 'unknown')] [array]$healthStatus, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateSet('computer', 'server', 'securityVm')] [array]$type, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [Boolean]$tamperProtectionEnabled, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateSet('creatingWhitelist', 'installing', 'locked', 'notInstalled', 'registering', 'starting', 'stopping', 'unavailable', 'uninstalled', 'unlocked')] [array]$lockdownStatus, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [array]$ids, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { try { $_ | Get-Date -ErrorAction stop } catch { throw 'lastSeenBefore should be [datetime] or ISO_8601 or something get-date recognises' } } } })] [string]$lastSeenBefore, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { try { $_ | Get-Date -ErrorAction stop } catch { throw 'lastSeen After should be [datetime] or ISO_8601 or something get-date recognises' } } } })] [string]$lastSeenAfter, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [string]$hostnameContains, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [string]$associatedPersonContains, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [string]$groupNameContains, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [array]$os, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [array]$ipAddresses, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [string]$search, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [ValidateSet('hostname', 'groupName', 'associatedPersonName', 'ipAddresses', 'osName')] [array]$searchFields, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'CannedQuery')] [array]$variables ) $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/live-discover/v1/queries/runs') if ($PSCmdlet.ParameterSetName -eq 'CustomBody') { Write-Verbose 'Custom Body' $body = $customBody } else { $body = @{} $endpointFilters = @{} if ($healthStatus) { $endpointFilters.healthStatus = $healthStatus } if ($type) { $endpointFilters.type = $type } if ($tamperProtectionEnabled) { $endpointFilters.tamperProtectionEnabled = $tamperProtectionEnabled } if ($lockdownStatus) { $endpointFilters.lockdownStatus = $lockdownStatus } if ($ids) { $endpointFilters.ids = $ids } if ($lastSeenBefore) { try { $lastSeenBeforeTemp = $lastSeenBefore | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' -ErrorAction Stop } catch { $lastSeenBeforeTemp = $lastSeenBefore } $endpointFilters.lastSeenBefore = $lastSeenBeforeTemp } if ($lastSeenAfter) { try { $lastSeenAfterTemp = $lastSeenAfter | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' -ErrorAction Stop } catch { $lastSeenAfterTemp = $lastSeenAfter } $endpointFilters.lastSeenAfter = $lastSeenAfterTemp } if ($hostnameContains) { $endpointFilters.hostnameContains = $hostnameContains } if ($associatedPersonContains) { $endpointFilters.associatedPersonContains = $associatedPersonContains } if ($groupNameContains) { $endpointFilters.groupNameContains = $groupNameContains } if ($os) { $endpointFilters.os = $os } if ($ipAddresses) { $endpointFilters.ipAddresses = $ipAddresses } if ($search) { $endpointFilters.search = $search } if ($searchFields) { $endpointFilters.searchFields = $searchFields } if ($endpointFilters) { $body.matchEndpoints = @{ 'filters' = @($endpointFilters) } } else { $body.matchEndpoints = @{ 'all' = 'true' } } # force times into format acceptable to Sophos if ($variables) { foreach ($var in $variables) { if ($var.dataType -eq 'datetime') { try { $var.value = $var.value | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' -ErrorAction Stop } catch { throw "Invalid dateTime variable format for variable $($var.name)" } } } $body.variables = $variables } if ($PSCmdlet.ParameterSetName -eq 'CustomQuery') { Write-Verbose 'Custom Query' $body.'adHocQuery' = @{ 'template' = $query 'name' = $queryName } } else { Write-Verbose 'Canned Query' $body.savedQuery = @{ 'queryId' = $queryId 'categoryId' = $categoryId } } } Write-Verbose ($body | ConvertTo-Json -Depth 5) Write-Verbose $uri Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } # ./SophosCentral/public/Invoke-SophosCentralXDRQueryRun.ps1 function Invoke-SophosCentralXDRQueryRun { <# .SYNOPSIS Run a query against the Sophos Data Lake. .DESCRIPTION Run a query against the Sophos Data Lake. The values in the example bodies below may not be correct (such as the variables sub hashtables), but the structure of the hashtable should be correct .PARAMETER CustomBody The query to run as a hashtable, see this for query options - https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/post .PARAMETER categoryId Query category ID. .PARAMETER queryId (required) Saved query ID. .PARAMETER adHocQuery Ad hoc query to run. Required if a saved query isn't supplied. .PARAMETER name Name for the ad hoc query. .PARAMETER template (required) SQL statement for the query. This can contain replacement variables wrapped in $$ (double dollar sign) delimiters. .PARAMETER variables Values of variables to be replaced in the template SQL. Array of hashes each containg the following keys: name Variable name dataType Data types supported for EDR Data Lake queries. The following values are allowed: double, integer, text, dateTime, boolean value String value of the variable. pivotType The meaning of an input parameter of a query. The following values are allowed: deviceId, deviceName, sophosPid, ipAddress, username, sha256, filePath, registryKey, url .PARAMETER ids array Find endpoints with the specified IDs. Must contain from 1 to 1000 items. If not specfied then all endpoints are queried .PARAMETER from Start of time range that is applied when running the query (inclusive). It can be in ISO duration format, full UTC timestamp or date only. .PARAMETER to End of time range that is applied when running the query (inclusive). It can be in ISO duration format, full UTC timestamp or date only. .EXAMPLE $body = @{ 'adHocQuery' = @{ 'template' = 'select * from \"xdr_data\" limit 10' 'name' = 'test search' } 'from' = '2022-01-01T12:02:01.000Z' 'to' = '2022-01-21T12:02:01.700Z' } $query = Invoke-SophosCentralXDRQueryRun -CustomBody $body .EXAMPLE $body = @{ 'adHocQuery' = @{ 'template' = 'select * from \"xdr_data\" limit 10' 'name' = 'test search' } 'from' = '2022-01-01T12:02:01.000Z' 'to' = '2022-01-21T12:02:01.700Z' 'variables' = @{ 'name' = 'var1' 'dataType' = 'text' 'value' = 'asdfwsdfsdf' 'pivotType' = 'deviceId' }, @{ 'name' = 'var2' 'dataType' = 'double' 'value' = 'asdfwsdfsdf' 'pivotType' = 'sha256' } 'matchEndpoints' = @{ 'filters' = @( @{ 'ids' = @( '7076e453-662f-40b9-bac6-5589691bd6de', '7edf66a6-325f-40a3-bcb6-3b63ecbcba74' ) } ) } } $query = Invoke-SophosCentralXDRQueryRun -CustomBody $body .EXAMPLE $query = Invoke-SophosCentralXDRQueryRun -Query "SELECT name, meta_hostname FROM xdr_data WHERE query_name = 'windows_startup_items' AND name = 'someSVC'" -From (Get-Date).AddDays(-7) -to get-date .EXAMPLE $query = Invoke-SophosCentralXDRQueryRun -Query "SELECT name, meta_hostname FROM xdr_data WHERE query_name = 'windows_startup_items' AND name = 'imDmsSvc'" -From (Get-Date).AddDays(-7) -to get-date .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $false, ParameterSetName = 'SavedQuery')] [string]$categoryId, [Parameter(Mandatory = $true, ParameterSetName = 'SavedQuery')] [string]$queryId, [Parameter(Mandatory = $true, ParameterSetName = 'CustomBody')] [hashtable]$customBody, [Parameter(Mandatory = $true, ParameterSetName = 'CustomQuery')] [string]$Query, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'SavedQuery')] [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { throw 'Invaid From time - should be either a [datetime] or a ISO_8601 duration' } } })] $From, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'SavedQuery')] [ValidateScript({ if ($_.GetType().Name -eq 'DateTime') { return $true } else { #match this duration format https://en.wikipedia.org/wiki/ISO_8601#Durations $regex = '^[-+]?P(?!$)(([-+]?\d+Y)|([-+]?\d+\.\d+Y$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?(([-+]?\d+W)|([-+]?\d+\.\d+W$))?(([-+]?\d+D)|([-+]?\d+\.\d+D$))?(T(?=[\d+-])(([-+]?\d+H)|([-+]?\d+\.\d+H$))?(([-+]?\d+M)|([-+]?\d+\.\d+M$))?([-+]?\d+(\.\d+)?S)?)??$' if ($_ -match $regex) { return $true } else { throw 'Invaid To time - should be either a [datetime] or a ISO_8601 duration' } } })] $To, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [string]$queryName = 'AdHoc', [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'SavedQuery')] [array]$ids, [Parameter(Mandatory = $false, ParameterSetName = 'CustomQuery')] [Parameter(Mandatory = $false, ParameterSetName = 'SavedQuery')] [array]$variables ) $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/xdr-query/v1/queries/runs') if ($PSCmdlet.ParameterSetName -eq 'CustomBody') { Write-Verbose 'Custom Body' $body = $customBody } else { $body = @{} # force times into format acceptable to Sophos if ($variables) { foreach ($var in $variables) { if ($var.dataType -eq 'datetime') { try { $var.value = $var.value | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' -ErrorAction Stop } catch { throw "Invalid dateTime variable format for variable $($var.name)" } } } } $body.variables = $variables if ($From) { if ($From.GetType().name -eq 'DateTime') { $body.from = $From | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' } else { $body.from = $From } } if ($To) { if ($To.GetType().name -eq 'DateTime') { $body.to = $To | Get-Date -AsUTC -Format 'yyyy-MM-dd"t"hh:mm:ssZ' } else { $body.to = $To } } if ($ids) { $endpointFilters += @{ids = $ids } } if ($endpointFilters) { $body.matchEndpoints = @{ 'filters' = @( @{ 'ids' = $ids } ) } } if ($PSCmdlet.ParameterSetName -eq 'CustomQuery') { Write-Verbose 'Custom Query' $body.adHocQuery = @{ 'template' = $query 'name' = $queryName } } else { Write-Verbose 'Canned Query' $body.savedQuery = @{ 'queryId' = $queryId 'categoryId' = $categoryId } if ($variables) { $body.variables = $variables } } } Write-Verbose ($body | ConvertTo-Json -Depth 5) Write-Verbose $uri Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $Body } # ./SophosCentral/public/New-SophosCentralAccessToken.ps1 function New-SophosCentralAccessToken { <# .SYNOPSIS Create access token for a tenant. Currently the only type is 'sophosLinuxSensor' .DESCRIPTION Create access token for a tenant. Currently the only type is 'sophosLinuxSensor' .EXAMPLE New-SophosCentralAccessToken .LINK https://developer.sophos.com/docs/accounts-v1/1/routes/access-tokens/post #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Label, [Parameter(Mandatory = $true)] [ValidateSet('sophosLinuxSensor')] [string]$Type, [datetime]$ExipresAt ) Test-SophosCentralConnected $body = @{ label = $Label type = $Type } if ($ExipresAt) { $body.Add('expiresAt', $ExipresAt) } $uri = [System.Uri]::New($SCRIPT:SophosCentral.GlobalEndpoint + '/accounts/v1/access-tokens') Invoke-SophosCentralWebRequest -Uri $uri -Body $body -Method Post } # ./SophosCentral/public/New-SophosCentralAdmin.ps1 function New-SophosCentralAdmin { <# .SYNOPSIS Create a tenant admin from a directory user. .DESCRIPTION Create a tenant admin from a directory user. .PARAMETER UserID ID of an existing user to add admin roles to. .PARAMETER RoleID ID of roles to assign to the user .EXAMPLE New-SophosCentralAdmin -UserID 'd5a81643-34db-4c44-a942-d83207ca402c' -RoleID 'fd18b044-a832-4b1a-a7a3-85e663366303' .LINK https://developer.sophos.com/docs/common-v1/1/routes/admins/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateScript({ if ($false -eq [System.Guid]::TryParse($_, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } })] [string]$UserID, [Parameter(Mandatory = $true)] [ValidateScript({ foreach ($role in $_) { if ($false -eq [System.Guid]::TryParse($role, $([ref][guid]::Empty))) { throw 'Not a valid GUID' } else { return $true } } })] [string[]]$RoleID, [switch]$Force ) Test-SophosCentralConnected $uriChild = '/common/v1/admins' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $body = @{ userId = $UserID roleAssignments = @() } foreach ($role in $RoleID) { $roleHash = @{ roleId = $role } $body['roleAssignments'] += $roleHash } if ($Force -or $PSCmdlet.ShouldProcess('Assign admin role', ($UserID))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } # ./SophosCentral/public/New-SophosCentralCustomerTenant.ps1 function New-SophosCentralCustomerTenant { <# .SYNOPSIS Create a new tenant. .DESCRIPTION Create a new tenant. .PARAMETER Name Name of the tenant .EXAMPLE New-SophosCentralCustomerTenant -Name 'Test User' -DataGeography AU -BillingType 'trial' -FirstName 'John' -LastName 'Smith' -Email 'test@contoso.com' -Phone '+612000000' -Address1 '31 Bligh St' -City 'Sydney' -CountryCode 'AU' -PostalCode '2000' -State 'New South Whales' .LINK https://developer.sophos.com/docs/partner-v1/1/routes/tenants/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] param ( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [ValidateSet('US', 'IE', 'DE', 'CA', 'AU', 'JP')] [string]$DataGeography, [Parameter(Mandatory = $true)] [ValidateSet('trial', 'usage')] [string]$BillingType, [Parameter(Mandatory = $true)] [string]$FirstName, [Parameter(Mandatory = $true)] [string]$LastName, [Parameter(Mandatory = $true)] [string]$Email, [Parameter(Mandatory = $true)] [string]$Phone, [Parameter(Mandatory = $true)] [string]$Address1, [string]$Address2, [string]$Address3, [Parameter(Mandatory = $true)] [string]$City, [string]$State, [Parameter(Mandatory = $true)] [string]$CountryCode, [Parameter(Mandatory = $true)] [string]$PostalCode, [switch]$Force ) Test-SophosCentralConnected if ((Test-SophosPartner) -eq $false) { throw 'You are not currently logged in using a Sophos Central Partner Service Principal' } $uri = [System.Uri]::New('https://api.central.sophos.com/partner/v1/tenants') $body = @{ name = $Name dataGeography = $DataGeography billingType = $billingType contact = @{ firstName = $firstName lastName = $lastName email = $email phone = $Phone address = @{ address1 = $address1 city = $City countryCode = $countryCode postalCode = $postalCode } } } if ($address2) { $body['contact']['address'].Add('address2', $address2) } if ($address3) { $body['contact']['address'].Add('address3', $address3) } if ($state) { $body['contact']['address'].Add('state', $state) } try { $header = Get-SophosCentralAuthHeader -PartnerInitial } catch { throw $_ } if ($Force -or $PSCmdlet.ShouldProcess($Name, ($body.keys -join ', '))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body -CustomHeader $header } } # ./SophosCentral/public/New-SophosCentralUser.ps1 function New-SophosCentralUser { <# .SYNOPSIS Create a new user in Sophos Central .DESCRIPTION Create a new user in Sophos Central .PARAMETER Name This parameter is mandatory .PARAMETER GroupIDs A list/array of group ID's to add them to. To determine the ID of the groups use Get-SophosCentralUserGroups .EXAMPLE New-SophosCentralUser -Name "John Smith" -FirstName "John" -LastName "Smith" -Email "jsmith@contoso.com" .LINK https://developer.sophos.com/docs/common-v1/1/routes/directory/users/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] param ( [Parameter(Mandatory = $true)] [string]$Name, [string]$FirstName, [string]$LastName, [string]$Email, [string]$ExchangeLogin, [string[]]$GroupIDs, [switch]$Force ) Test-SophosCentralConnected $uriChild = '/common/v1/directory/users' $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) $body = @{ name = $Name } if ($firstName) { $body.Add('firstName', $FirstName) } if ($LastName) { $body.Add('lastName', $LastName) } if ($email) { $body.Add('email', $email) } if ($exchangeLogin) { $body.Add('exchangeLogin', $exchangeLogin) } if ($groupIds) { $body.Add('groupIds', $groupIds) } if ($Force -or $PSCmdlet.ShouldProcess('Create user', ($Name))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } # ./SophosCentral/public/Remove-SophosCentralAccessToken.ps1 function Remove-SophosCentralAccessToken { <# .SYNOPSIS Revoke access token for a tenant. .DESCRIPTION Revoke access token for a tenant. .EXAMPLE Remove-SophosCentralAccessToken .LINK https://developer.sophos.com/docs/accounts-v1/1/routes/access-tokens/%7BtokenId%7D/delete #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory = $true)] [Alias('ID')] [string[]]$TokenID ) Test-SophosCentralConnected foreach ($token in $TokenID) { $uri = [System.Uri]::New("$($SCRIPT:SophosCentral.GlobalEndpoint)/accounts/v1/access-tokens/$($token)") if ($Force -or $PSCmdlet.ShouldProcess('Remove access token', $token)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } # ./SophosCentral/public/Remove-SophosCentralAdmin.ps1 function Remove-SophosCentralAdmin { <# .SYNOPSIS Remove an admin by ID. .DESCRIPTION Remove an admin by ID. .EXAMPLE Remove-SophosCentralAdmin -UserID 8a823dcd-5f09-463b-a5f3-e019cf280d79 .LINK https://developer.sophos.com/docs/common-v1/1/routes/admins/%7BadminId%7D/delete #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory = $true)] [Alias('ID')] [string[]]$UserID ) Test-SophosCentralConnected foreach ($idTmp in $UserID) { $uri = [System.Uri]::New("$($SCRIPT:SophosCentral.RegionEndpoint)/common/v1/admins/$($idTmp)") if ($Force -or $PSCmdlet.ShouldProcess('Remove admin', $idTmp)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } # ./SophosCentral/public/Remove-SophosCentralEndpoint.ps1 function Remove-SophosCentralEndpoint { <# .SYNOPSIS Deletes a specified endpoint. .DESCRIPTION Deletes a specified endpoint. .PARAMETER EndpointID The ID of the endpoint .EXAMPLE Remove-SophosCentralEndpoint -EndpointID 59412c23-0ef1-49d6-9f4f-3b8b4863c176 .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/get #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID, [switch]$Force ) begin { Test-SophosCentralConnected } process { foreach ($endpoint in $EndpointID) { $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/endpoints/' + $endpoint) if ($Force -or $PSCmdlet.ShouldProcess('Remove Endpoint', $Endpoint)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } end { } } # ./SophosCentral/public/Remove-SophosCentralFirewallGroup.ps1 function Remove-SophosCentralFirewallGroup { <# .SYNOPSIS Remove a firewall group .DESCRIPTION Remove a firewall group .PARAMETER GroupID The ID of the group. Use Get-SophosCentralFirewallGroup to list them .EXAMPLE Remove-SophosCentralFirewallGroup -GroupID 6fed0eb5-d8ff-44ee-9c37-df8a9924373d .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewall-groups/%7BgroupId%7D/delete #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$GroupID, [switch]$Force ) begin { Test-SophosCentralConnected } process { foreach ($group in $GroupID) { $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewall-groups/' + $group) if ($Force -or $PSCmdlet.ShouldProcess('Remove', $group )) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } end { } } # ./SophosCentral/public/Remove-SophosCentralFirewallUpdate.ps1 function Remove-SophosCentralFirewallUpdate { <# .SYNOPSIS Cancel a scheduled firewall update .DESCRIPTION Cancel a scheduled firewall update .PARAMETER FirewallID The ID of the firewall. Use Get-SophosCentralFirewall to list them .EXAMPLE Remove-SophosCentralFirewallUpdate -FirewallID 6fed0eb5-d8ff-44ee-9c37-df8a9924373d .LINK https://developer.sophos.com/docs/firewall-v1/1/routes/firewalls/actions/firmware-upgrade/delete #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$FirewallID, [switch]$Force ) begin { Test-SophosCentralConnected } process { foreach ($firewall in $FirewallID) { $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/firewall/v1/firewalls/actions/firmware-upgrade?ids=' + $firewall) if ($Force -or $PSCmdlet.ShouldProcess('Cancel update', $firewall )) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } end { } } # ./SophosCentral/public/Remove-SophosCentralUser.ps1 function Remove-SophosCentralUser { <# .SYNOPSIS Delete a user by ID .DESCRIPTION Delete a user by ID .EXAMPLE Remove-SophosCentralUser -UserID 8a823dcd-5f09-463b-a5f3-e019cf280d79 .LINK https://developer.sophos.com/docs/common-v1/1/routes/directory/users/%7BuserId%7D/delete #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory = $true)] [Alias('ID')] [string[]]$UserID ) Test-SophosCentralConnected foreach ($idTmp in $UserID) { $uri = [System.Uri]::New("$($SCRIPT:SophosCentral.RegionEndpoint)/common/v1/directory/users/$($idTmp)") if ($Force -or $PSCmdlet.ShouldProcess('Remove user', $idTmp)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Delete } } } # ./SophosCentral/public/Remove-SophosCentralXDRQueryRun.ps1 function Remove-SophosCentralXDRQueryRun { <# .SYNOPSIS Cancel a query run by ID. .DESCRIPTION Cancel a query run by ID. .PARAMETER RunId Query run ID. .EXAMPLE Remove-SophosCentralXDRQueryRun -RunID 6fed0eb5-d8ff-44ee-9c37-df8a9924373d .LINK https://developer.sophos.com/docs/xdr-query-v1/1/routes/queries/runs/%7BrunId%7D/cancel/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$RunID, [switch]$Force ) begin { Test-SophosCentralConnected } process { foreach ($run in $RunID) { $uriChild = "/xdr-query/v1/queries/runs/$($run)/cancel" $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + $uriChild) if ($Force -or $PSCmdlet.ShouldProcess('Remove', $run)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post } } } end { } } # ./SophosCentral/public/Set-SophosCentralAlertAction.ps1 function Set-SophosCentralAlertAction { <# .SYNOPSIS Update an alert in Sophos Central .DESCRIPTION Update an alert in Sophos Central .PARAMETER AlertID The ID of the alert. Use Get-SophosCentralAlerts to list them .PARAMETER Action The alert action to perform. To get the possible actions for an alert, check the results from Get-SophosCentralAlerts The action must be in the same capitalization as listed, otherwise it will fail Possible options: 'acknowledge', 'cleanPua', 'cleanVirus', 'authPua', 'clearThreat', 'clearHmpa', 'sendMsgPua', 'sendMsgThreat' .PARAMETER Message Message to send for the action. .EXAMPLE Set-SophosCentralAlertAction -AlertID "6d41e78e-0360-4de3-8669-bb7b797ee515" -Action "clearThreat" .LINK https://developer.sophos.com/docs/common-v1/1/routes/alerts/%7BalertId%7D/actions/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory = $true)] [Alias('ID')] [string[]]$AlertID, [Parameter(Mandatory = $true)] [ValidateSet('acknowledge', 'cleanPua', 'cleanVirus', 'authPua', 'clearThreat', 'clearHmpa', 'sendMsgPua', 'sendMsgThreat')] [string]$Action, [string]$Message, [switch]$Force ) begin { Test-SophosCentralConnected $uriChild = '/common/v1/alerts/{0}/actions' $uriString = $SCRIPT:SophosCentral.RegionEndpoint + $uriChild } process { foreach ($alert in $AlertID) { $uri = [System.Uri]::New($uriString -f $alert) $body = @{ action = $Action } if ($Message) { $body.Add('message', $Message) } if ($Force -or $PSCmdlet.ShouldProcess($alert, $Action)) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } } } # ./SophosCentral/public/Set-SophosCentralEndpointIsolation.ps1 function Set-SophosCentralEndpointIsolation { <# .SYNOPSIS Turn on or off endpoint isolation for multiple endpoints. .DESCRIPTION Turn on or off endpoint isolation for multiple endpoints. .PARAMETER EndpointID The ID of the Endpoint. Use Get-SophosCentralEndpoints to list them .PARAMETER Enabled Use $true to enable isolation, $false to disable .PARAMETER Comment Reason the endpoints should be isolated or not .EXAMPLE Set-SophosCentralEndpointIsolation -EndpointID '23a920fa-9a34-4869-bc3d-a1626e50f670' -Enabled $false -Comment "disable iso" .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/isolation/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID, [Parameter(Mandatory = $true, ParameterSetName = 'Update Status')] [System.Boolean]$Enabled, [Parameter(Mandatory = $true)] [string]$Comment, [switch]$Force ) begin { Test-SophosCentralConnected $uri = [System.Uri]::New($SCRIPT:SophosCentral.RegionEndpoint + '/endpoint/v1/endpoints/isolation') } process { $body = @{ enabled = $Enabled comment = $Comment ids = @() } foreach ($endpoint in $EndpointID) { $body['ids'] += $endpoint } if ($Force -or $PSCmdlet.ShouldProcess('isolation', ($EndpointID -join ', '))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } } # ./SophosCentral/public/Set-SophosCentralEndpointTamperProtection.ps1 function Set-SophosCentralEndpointTamperProtection { <# .SYNOPSIS Update Tamper Protection settings .DESCRIPTION Update Tamper Protection settings .PARAMETER EndpointID The ID of the Endpoint. Use Get-SophosCentralEndpoints to list them .PARAMETER Enabled Use $true to enable Tamper Protection, $false to disable .PARAMETER RegeneratePassword Use this switch to generate a new Tamper Protection password .EXAMPLE Set-SophosCentralEndpointTamperProtection -EndpointID '23a920fa-9a34-4869-bc3d-a1626e50f670' -Enabled $false .EXAMPLE Set-SophosCentralEndpointTamperProtection -EndpointID '23a920fa-9a34-4869-bc3d-a1626e50f670' -RegeneratePassword .LINK https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/%7BendpointId%7D/tamper-protection/post #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID')] [string[]]$EndpointID, [Parameter(Mandatory = $true, ParameterSetName = 'Update Status')] [System.Boolean]$Enabled, [Parameter(Mandatory = $true, ParameterSetName = 'Regenerate Password')] [switch]$RegeneratePassword, [switch]$Force ) begin { Test-SophosCentralConnected $uriChild = '/endpoint/v1/endpoints/{0}/tamper-protection' $uriString = $SCRIPT:SophosCentral.RegionEndpoint + $uriChild } process { foreach ($endpoint in $EndpointID) { $uri = [System.Uri]::New($uriString -f $endpoint) $body = @{} if ($Enabled) { $body.Add('enabled', $Enabled) } if ($RegeneratePassword) { $body.Add('regeneratePassword', $RegeneratePassword) } if ($Force -or $PSCmdlet.ShouldProcess($EndpointID, ($body.keys -join ', '))) { Invoke-SophosCentralWebRequest -Uri $uri -Method Post -Body $body } } } } |