PSSymantecCloud.psm1
#Region '.\Private\GetConfigurationPath.ps1' 0 function GetConfigurationPath { <# .SYNOPSIS returns hashtable object with the BaseURL, SepCloudCreds, SepCloudToken full path .DESCRIPTION .INPUTS None .OUTPUTS Hashtable #> @{ BaseUrl = "api.sep.securitycloud.symantec.com" SepCloudCreds = "$env:TEMP\SepCloudOAuthCredentials.xml" SepCloudToken = "$env:TEMP\SepCloudToken.xml" } } #EndRegion '.\Private\GetConfigurationPath.ps1' 19 #Region '.\Public\Export-SepCloudPolicyToExcel.ps1' 0 function Export-SepCloudPolicyToExcel { <# TODO fill description .SYNOPSIS Export an Allow List policy object to excel .DESCRIPTION Takes an allow list policy object as input and exports it to an Excel file, with one tab per allow type (filename/file hash/directory etc...) .EXAMPLE Get-SepCloudPolicyDetails -Name "My Policy" | Export-SepCloudPolicyToExcel -Path "allow_list.xlsx" Gathers policy in an object, pipes the output to Export-SepCloudPolicyToExcel #> param ( # Path of Export [Parameter()] [string] $Path, # Policy Obj to work with [Parameter( ValueFromPipeline, Mandatory )] [pscustomobject] $obj_policy ) <# Using as a template the following command $allow_list | ConvertTo-Json -Depth 100 | Out-File -FilePath "C:\Users\Douda\Documents\Amcor\Servers - Amcor Core Allow List Policy_v69.json" Get-SepCloudPolicyDetails -Policy_UUID "5e867f84-5e23-421c-adfd-XXXXXXXXXXXX" -Policy_version 9 | Convert-SepCloudPolicyToExcel -Path "C:\Amcor_local\test5.xlsx" Parsing the custom object to get the list of $obj_policy.features.configuration.applications $obj_policy.features.configuration.applications.processfile $obj_policy.features.configuration.applications.processfile.name $obj_policy.features.configuration.applications.processfile.sha2 $obj_policy.features.configuration.certificates $obj_policy.features.configuration.webdomains $obj_policy.features.configuration.ips_hosts $obj_policy.features.configuration.extensions $obj_policy.features.configuration.extensions.names $obj_policy.features.configuration.windows.files $obj_policy.features.configuration.windows.directories #> $Applications = $obj_policy.features.configuration.applications.processfile $Certificates = $obj_policy.features.configuration.certificates $Webdomains = $obj_policy.features.configuration.webdomains $Ips_Hosts = $obj_policy.features.configuration.ips_hosts $Extensions = $obj_policy.features.configuration.extensions.names $Files = $obj_policy.features.configuration.windows.files $Directories = $obj_policy.features.configuration.windows.directories Import-Module -Name ImportExcel $Applications | Export-Excel $Path -WorksheetName "Applications" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Certificates | Export-Excel $Path -WorksheetName "Certificates" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Webdomains | Export-Excel $Path -WorksheetName "Webdomains" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Ips_Hosts | Export-Excel $Path -WorksheetName "Ips_Hosts" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Extensions | Export-Excel $Path -WorksheetName "Extensions" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Files | Export-Excel $Path -WorksheetName "Files" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter $Directories | Export-Excel $Path -WorksheetName "Directories" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter } #EndRegion '.\Public\Export-SepCloudPolicyToExcel.ps1' 60 #Region '.\Public\Get-SepCloudDeviceInfo.ps1' 0 function Get-SepCloudDeviceInfo { param ( # Mandatory device_ID parameter [Parameter(mandatory)] [string] $Device_ID ) # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/devices/$Device_ID" # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { # HTTP body content containing all the queries $Body = @{} $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token Body = $Body } $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing return $Response } } #EndRegion '.\Public\Get-SepCloudDeviceInfo.ps1' 28 #Region '.\Public\Get-SepCloudDeviceList.ps1' 0 function Get-SepCloudDeviceList { <# TODO fill up description .SYNOPSIS Gathers list of devices from the SEP Cloud console .DESCRIPTION A longer description of the function, its purpose, common use cases, etc. .PARAMETER Computername Specify one or many computer names. Accepts pipeline (up to 10 devices per query) Supports partial match .PARAMETER is_online Switch to lookup only online machines .PARAMETER Device_status Lookup devices per security status. Accepts only "SECURE", "AT_RISK", "COMPROMISED", "NOT_COMPUTED" .EXAMPLE Get-SepCloudDeviceList .EXAMPLE Get-SepCloudDeviceList -Computername MyComputer .EXAMPLE Get-SepCloudDeviceList -is_online -Device_status AT_RISK #> [CmdletBinding()] param ( <# Optional ComputerName parameter TODO work to allow multiple values from Computername More info https://apidocs.securitycloud.symantec.com/# name query name of the device. [NOTE] Provide comma seperated values in case of multiple name search Note : seems to be limited to 10 values max #> [Parameter( ValueFromPipeline = $true )] [string] $Computername, # Optional Is_Online parameter [Parameter()] [Alias("Online")] [switch] $is_online, # Optional include_details parameter [Parameter()] [Alias("Details")] [switch] $include_details, # Device Group [Parameter()] [Alias("Group")] [string] $Device_group, # Optional Device_Status parameter [Parameter()] [Alias("DeviceStatus")] [ValidateSet("SECURE", "AT_RISK", "COMPROMISED", "NOT_COMPUTED")] $Device_status ) # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/devices" # Get token $Token = Get-SEPCloudToken if ($null -ne $Token ) { # HTTP body content containing all the queries $Body = @{} # Iterating through all parameter and add them to the HTTP body if ($Computername -ne "") { $Body.Add("name", "$Computername") } if ($is_online -eq $true ) { $body.add("is_online", "true") } if ($include_details -eq $true) { $Body.Add("include_details", "true") } if ($Device_status -ne "") { $Body.Add("device_status", "$Device_status") } if ($Device_group -ne "") { $Body.Add("device_group", "$Device_group") } $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token Body = $Body } try { $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing return $Response } catch { $StatusCode = $_.Exception.Response.StatusCode Write-Warning "Query error - Expected HTTP 200, got $([int]$StatusCode)" } } } #EndRegion '.\Public\Get-SepCloudDeviceList.ps1' 110 #Region '.\Public\Get-SepCloudEvents.ps1' 0 function Get-SepCloudEvents { <# TODO fill description for Get-SepCloudEvents .SYNOPSIS Get list of SEP Cloud Events. By default, every events for the past 30 days .DESCRIPTION A longer description of the function, its purpose, common use cases, etc. .PARAMETER FileDetection Runs the following query under the hood "feature_name:MALWARE_PROTECTION AND ( type_id:8031 OR type_id:8032 OR type_id:8033 OR type_id:8027 OR type_id:8028 ) AND ( id:12 OR id:11 AND type_id:8031 )" .LINK https://github.com/Douda/PSSymantecCloud .EXAMPLE Get-SepCloudEvents -FileDetection .EXAMPLE Get-SepCloudEvents - Query "type_id:8031 OR type_id:8032 OR type_id:8033" #> param ( # file Detection [Parameter()] [switch] $FileDetection, # Custom query to run [Parameter()] [string] $Query ) begin { # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/event-search" $ArrayResponse = @() } process { # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { # HTTP body content containing all mandatory info to start a query $Body = @{ "product" = "SAEP" "feature_name" = "ALL" } <# Setting dates for the query Date Format required : -UFormat "%Y-%m-%dT%T.000+00:00" Example : "start_date": "2022-10-16T00:00:00.000+00:00", "end_date": "2022-11-16T00:00:00.000+00:00" #> $end_date = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK" $start_date = ((Get-Date).addDays(-29) | Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK") $Body.Add("start_date", $start_date) $Body.Add("end_date", $end_date) # Iterating through all parameter and adding them to the HTTP body switch ($PSBoundParameters.Keys) { 'FileDetection' { $Body.Add("query", '( feature_name:MALWARE_PROTECTION AND ( type_id:8031 OR type_id:8032 OR type_id:8033 OR type_id:8027 OR type_id:8028 ) AND ( id:12 OR id:11 AND type_id:8031 ) )') } 'Query' { $Body.Add("query", "$Query") } Default { } } # Convert body to Json after adding potential query with parameters $Body_Json = ConvertTo-Json $Body $Headers = @{ Host = $BaseURL Accept = "application/json" "Content-Type" = "application/json" Authorization = $Token } try { $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing $ArrayResponse += $Response if ($null -ne $Response.next) { <# If pagination #> do { # change the "next" offset for next query $Body.Remove("next") $Body.Add("next", $Response.next) $Body_Json = ConvertTo-Json $Body # Run query & add it to the array $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing $ArrayResponse += $Response } until ( ($null -eq $Response.next) ) } } catch { $StatusCode = $_ $StatusCode } } } end { return $ArrayResponse.events } } #EndRegion '.\Public\Get-SepCloudEvents.ps1' 106 #Region '.\Public\Get-SepCloudFeatureList.ps1' 0 function Get-SepCloudFeatureList { <# TODO : fill in description Get-SepCloudFeatureList .SYNOPSIS A short one-line action-based description, e.g. 'Tests if a function is valid' .DESCRIPTION A longer description of the function, its purpose, common use cases, etc. .NOTES Information or caveats about the function e.g. 'This function is not supported in Linux' .LINK Specify a URI to a help page, this will show when Get-Help -Online is used. .EXAMPLE Test-MyTestFunction -Verbose Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines #> param ( ) # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/devices/enums" # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { # HTTP body content containing all the queries $Body = @{} $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token Body = $Body } $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing return $Response } } #EndRegion '.\Public\Get-SepCloudFeatureList.ps1' 38 #Region '.\Public\Get-SepCloudIncidents.ps1' 0 function Get-SepCloudIncidents { <# TODO fill description for Get-SepCloudIncidents .SYNOPSIS Get list of SEP Cloud incidents. By default, shows opened incidents .DESCRIPTION Get list of SEP Cloud incidents. Using the LUCENE query syntax, you can customize which incidents to gather. More information : https://techdocs.broadcom.com/us/en/symantec-security-software/endpoint-security-and-management/endpoint-security/sescloud/Endpoint-Detection-and-Response/investigation-page-overview-v134374740-d38e87486/Cloud-Database-Search/query-and-filter-operators-by-data-type-v134689952-d38e88796.html .PARAMETER Open filters only opened incidents. Simulates a query "state_id: [0 TO 3]" which represents incidents with the following states <0 Unknown | 1 New | 2 In Progress | 3 On Hold> .PARAMETER Include_events Includes every events that both are part of the context & triggered incident events .PARAMETER Query Type your customer Lucene query to pass to the API .OUTPUTS PSObject containing all SEP incidents .EXAMPLE Get-SepCloudIncidents -Open -Include_Events .EXAMPLE Get-SepCloudIncidents -Query "state_id: [0 TO 5]" This query a list of every possible incidents (opened, closed and with "Unknown" status) .LINK https://github.com/Douda/PSSymantecCloud #> [CmdletBinding(DefaultParameterSetName = 'QueryOpen')] param ( # Opened incidents [Parameter( ParameterSetName = "QueryOpen" )] [switch] $Open, # Include events [Parameter()] [switch] $Include_events, # Custom query to run [Parameter( ParameterSetName = "QueryCustom" )] [string] $Query ) begin { # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/incidents" $ArrayResponse = @() } process { # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { # HTTP body content containing all the queries $Body = @{} # Settings dates $end_date = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK" $start_date = ((Get-Date).addDays(-29) | Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK") $Body.Add("start_date", $start_date) $Body.Add("end_date", $end_date) $Body_Json = ConvertTo-Json $Body # Iterating through all parameter and adding them to the HTTP body switch ($PSBoundParameters.Keys) { 'Query' { $Body.Add("query", "$Query") } 'Open' { $Body.Add("query", "state_id: [0 TO 3]") } 'Include_events' { $Body.Add("include_events", "true") } Default { } } $Headers = @{ Host = $BaseURL Accept = "application/json" "Content-Type" = "application/json" Authorization = $Token } try { $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing $ArrayResponse += $Response if ($null -ne $Response.next) { <# If pagination #> do { # change the "next" offset for next query $Body.Remove("next") $Body.Add("next", $Response.next) $Body_Json = ConvertTo-Json $Body # Run query & add it to the array $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing $ArrayResponse += $Response } until ( ($null -eq $Response.next) ) } } catch { $StatusCode = $_ $StatusCode } } } end { return $ArrayResponse.incidents } } #EndRegion '.\Public\Get-SepCloudIncidents.ps1' 117 #Region '.\Public\Get-SepCloudPolices.ps1' 0 function Get-SepCloudPolices { # TODO to finish; test cmd-let param ( # Policy UUID [Parameter()] [string] $Policy_UUID ) # Init $BaseURL = (GetConfigurationPath).BaseUrl $URI_Tokens = 'https://' + $BaseURL + "/v1/policies" # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { # HTTP body content containing all the queries $Body = @{} $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token Body = $Body } $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing return $Response } } #EndRegion '.\Public\Get-SepCloudPolices.ps1' 31 #Region '.\Public\Get-SepCloudPolicyDetails.ps1' 0 function Get-SepCloudPolicyDetails { <# TODO finish Get-SepCloudPolicyDetails description .SYNOPSIS A short one-line action-based description, e.g. 'Tests if a function is valid' .DESCRIPTION A longer description of the function, its purpose, common use cases, etc. .NOTES Information or caveats about the function e.g. 'This function is not supported in Linux' .LINK Specify a URI to a help page, this will show when Get-Help -Online is used. .EXAMPLE Test-MyTestFunction -Verbose Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines #> param ( # Policy UUID [Parameter()] [string] $Policy_UUID, # Policy version [Parameter()] [string] [Alias("Version")] $Policy_Version, # Exact policy name [Parameter( ValueFromPipeline, Mandatory )] [string[]] [Alias("Name")] $Policy_Name ) begin { # Init $array_resp = @() } process { # iterating through policy_name list if more than one obj foreach ($p in $Policy_Name) { # Get list of all SEP Cloud policies $obj_policies = (Get-SepCloudPolices).policies $obj_policy = ($obj_policies | Where-Object { $_.name -eq "$p" }) # Use specific version or by default latest if ($Policy_version -ne "") { $obj_policy = $obj_policy | Where-Object { $_.name -eq "$p" -and $_.policy_version -eq $Policy_Version } } else { $obj_policy = ($obj_policy | Sort-Object -Property policy_version -Descending | Select-Object -First 1) } $Policy_UUID = ($obj_policy).policy_uid $Policy_Version = ($obj_policy).policy_version $BaseURL = (GetConfigurationPath).BaseUrl $URI = 'https://' + $BaseURL + "/v1/policies/$Policy_UUID/versions/$Policy_Version" # Get token $Token = Get-SEPCloudToken if ($null -ne $Token) { $Body = @{} $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token Body = $Body } $Resp = Invoke-RestMethod -Method GET -Uri $URI -Headers $Headers -Body $Body -UseBasicParsing $array_resp += $Resp } } } end { return $array_resp } } #EndRegion '.\Public\Get-SepCloudPolicyDetails.ps1' 86 #Region '.\Public\Get-SEPCloudToken.ps1' 0 function Get-SEPCloudToken { <# .SYNOPSIS Generates an authenticated Token from the SEP Cloud API .DESCRIPTION Gathers Bearer Token from the SEP Cloud console to interact with the authenticated API Securely stores credentials or valid token locally (By default on TEMP location) Connection information available here : https://sep.securitycloud.symantec.com/v2/integration/client-applications .PARAMETER ClientID ClientID parameter required to generate a token .PARAMETER Secret Secret parameter required in combinaison to ClientID to generate a token .EXAMPLE Get-SEPCloudToken .EXAMPLE Get-SEPCloudToken(ClientID,Secret) .NOTES Function logic 1. Test locally stored encrypted token 2. Test locally stored encrypted Client/Secret to generate a token 3. Requests Client/Secret to generate token #> [CmdletBinding()] param ( # ClientID from SEP Cloud Connection App [Parameter()] [string] $ClientID, # Secret from SEP Cloud Connection App [Parameter()] [string] $Secret ) # init $BaseURL = (GetConfigurationPath).BaseUrl $SepCloudCreds = (GetConfigurationPath).SepCloudCreds $SepCloudToken = (GetConfigurationPath).SepCloudToken $URI_Tokens = 'https://' + $BaseURL + '/v1/oauth2/tokens' $URI_Features = 'https://' + $BaseURL + '/v1/devices/enums' # Test if we have a token locally stored if (Test-Path -Path $SepCloudToken) { <# If true, test it against the API #> $Token = Import-Clixml -Path $SepCloudToken $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $Token } try { $response = Invoke-RestMethod -Method POST -Uri $URI_Features -Headers $Headers # Valid token, returning it Write-Verbose "Local token - valid" return $Token } catch { $StatusCode = $_.Exception.Response.StatusCode Write-Verbose "Authentication error - From locally stored token - Expected HTTP 200, got $([int]$StatusCode) - Continue ..." # Invalid token, deleting local token file Remove-Item $SepCloudToken } } # Test if OAuth cred present on the disk if (Test-Path -Path "$SepCloudCreds") { <# If true, Attempt to get a token #> $OAuth = Import-Clixml -Path $SepCloudCreds $OAuth_Basic = "Basic " + $OAuth $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $OAuth_Basic } try { $response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers # Get the auth token from the response & store it locally Write-Verbose "Valid credentials - returning valid token" $null = $Bearer_Token = "Bearer " + $response.access_token $Bearer_Token | Export-Clixml -Path $SepCloudToken return $Bearer_Token } catch { $StatusCode = $_.Exception.Response.StatusCode Write-Verbose "Authentication error - From locally stored credentials - Expected HTTP 200, got $([int]$StatusCode) - Continue..." # Invalid Credentials, deleting local credentials file Remove-Item $SepCloudCreds } } <# If no token nor OAuth creds available locally # Encode ClientID and Secret to create Basic Auth string # Authentication requires the following "Basic + encoded CliendID:ClientSecret" #> if ($clientID -eq "" -or $Secret -eq "") { Write-Host "No local credentials found" $ClientID = Read-Host -Prompt "Enter ClientID" $Secret = Read-Host -Prompt "Enter Secret" } $Encoded_Creds = [convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($ClientID + ':' + $Secret))) $Encoded_Creds | Export-Clixml -Path $SepCloudCreds # Create Basic Auth string $BasicAuth = "Basic " + $Encoded_Creds $Headers = @{ Host = $BaseURL Accept = "application/json" Authorization = $BasicAuth } $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -UseBasicParsing # Get the auth token from the response and store it $Bearer_Token = "Bearer " + $Response.access_token $Bearer_Token | Export-Clixml -Path $SepCloudToken return $Bearer_Token } #EndRegion '.\Public\Get-SEPCloudToken.ps1' 127 #Region '.\Public\Test-SepCloudConnectivity.ps1' 0 function Test-SepCloudConnectivity { param ( ) if (Get-SEPCloudToken) { Write-Host "Authentication OK" return $true else { Write-Host "Authentication failed" return false } } } #EndRegion '.\Public\Test-SepCloudConnectivity.ps1' 14 |