PSSEPCloud.psm1
#Region '.\Classes\1.class1.ps1' -1 class Class1 { [string]$Name = 'Class1' Class1() { #default Constructor } [String] ToString() { # Typo "calss" is intentional return ( 'This calss is {0}' -f $this.Name) } } #EndRegion '.\Classes\1.class1.ps1' 16 #Region '.\Classes\2.class2.ps1' -1 class Class2 { [string]$Name = 'Class2' Class2() { #default constructor } [String] ToString() { return ( 'This calss is {0}' -f $this.Name) } } #EndRegion '.\Classes\2.class2.ps1' 15 #Region '.\Classes\3.class11.ps1' -1 class Class11 : Class1 { [string]$Name = 'Class11' Class11 () { } [String] ToString() { return ( 'This calss is {0}:{1}' -f $this.Name,'class1') } } #EndRegion '.\Classes\3.class11.ps1' 14 #Region '.\Classes\4.class12.ps1' -1 class Class12 : Class1 { [string]$Name = 'Class12' Class12 () { } [String] ToString() { return ( 'This calss is {0}:{1}' -f $this.Name,'class1') } } #EndRegion '.\Classes\4.class12.ps1' 14 #Region '.\Private\Build-QueryURI.ps1' -1 function Build-QueryURI { <# .SYNOPSIS Constructs a URI from a base URI and query strings .DESCRIPTION Constructs a URI from a base URI and query strings .PARAMETER BaseURI The base URI to use .PARAMETER QueryStrings A hashtable of query strings to add to the URI .NOTES helper function .EXAMPLE $BaseURI = "https://Server01:8446/sepm/api/v1/computers" $QueryStrings = @{ sort = "COMPUTER_NAME" pageIndex = 1 pageSize = 100 } $URI = Build-QueryURI -BaseURI $BaseURI -QueryStrings $QueryStrings This example will : - Construct a URI from the base URI "https://Server01:8446/sepm/api/v1/computers" - With the query strings "sort=COMPUTER_NAME&pageIndex=1&pageSize=100" resulting in "https://Server01:8446/sepm/api/v1/computers?sort=COMPUTER_NAME&pageIndex=1&pageSize=100" #> param ( [string]$BaseURI, [hashtable]$QueryStrings ) # Construct the URI $builder = New-Object System.UriBuilder($BaseURI) $query = [System.Web.HttpUtility]::ParseQueryString($builder.Query) foreach ($param in $QueryStrings.GetEnumerator()) { $query[$param.Key] = $param.Value } $builder.Query = $query.ToString() $URL = $builder.Uri.AbsoluteUri return $URL } #EndRegion '.\Private\Build-QueryURI.ps1' 46 #Region '.\Private\ConvertTo-FlatObject.ps1' -1 # From https://github.com/EvotecIT/PSSharedGoods/tree/master/Public/Converts Function ConvertTo-FlatObject { <# .SYNOPSIS Flattends a nested object into a single level object. .DESCRIPTION Flattends a nested object into a single level object. .PARAMETER Objects The object (or objects) to be flatten. .PARAMETER Separator The separator used between the recursive property names .PARAMETER Base The first index name of an embedded array: - 1, arrays will be 1 based: <Parent>.1, <Parent>.2, <Parent>.3, … - 0, arrays will be 0 based: <Parent>.0, <Parent>.1, <Parent>.2, … - "", the first item in an array will be unnamed and than followed with 1: <Parent>, <Parent>.1, <Parent>.2, … .PARAMETER Depth The maximal depth of flattening a recursive property. Any negative value will result in an unlimited depth and could cause a infinitive loop. .PARAMETER Uncut The maximal depth of flattening a recursive property. Any negative value will result in an unlimited depth and could cause a infinitive loop. .PARAMETER ExcludeProperty The propertys to be excluded from the output. .EXAMPLE $Object3 = [PSCustomObject] @{ "Name" = "Przemyslaw Klys" "Age" = "30" "Address" = @{ "Street" = "Kwiatowa" "City" = "Warszawa" "Country" = [ordered] @{ "Name" = "Poland" } List = @( [PSCustomObject] @{ "Name" = "Adam Klys" "Age" = "32" } [PSCustomObject] @{ "Name" = "Justyna Klys" "Age" = "33" } [PSCustomObject] @{ "Name" = "Justyna Klys" "Age" = 30 } [PSCustomObject] @{ "Name" = "Justyna Klys" "Age" = $null } ) } ListTest = @( [PSCustomObject] @{ "Name" = "Sława Klys" "Age" = "33" } ) } $Object3 | ConvertTo-FlatObject .NOTES Based on https://powersnippets.com/convertto-flatobject/ #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeLine)][Object[]]$Objects, [String]$Separator = ".", [ValidateSet("", 0, 1)]$Base = 1, [int]$Depth = 5, [string[]] $ExcludeProperty, [Parameter(DontShow)][String[]]$Path, [Parameter(DontShow)][System.Collections.IDictionary] $OutputObject ) Begin { $InputObjects = [System.Collections.Generic.List[Object]]::new() } Process { foreach ($O in $Objects) { if ($null -ne $O) { $InputObjects.Add($O) } } } End { If ($PSBoundParameters.ContainsKey("OutputObject")) { $Object = $InputObjects[0] $Iterate = [ordered] @{} if ($null -eq $Object) { #Write-Verbose -Message "ConvertTo-FlatObject - Object is null" } elseif ($Object.GetType().Name -in 'String', 'DateTime', 'TimeSpan', 'Version', 'Enum') { $Object = $Object.ToString() } elseif ($Depth) { $Depth-- If ($Object -is [System.Collections.IDictionary]) { $Iterate = $Object } elseif ($Object -is [Array] -or $Object -is [System.Collections.IEnumerable]) { $i = $Base foreach ($Item in $Object.GetEnumerator()) { $NewObject = [ordered] @{} If ($Item -is [System.Collections.IDictionary]) { foreach ($Key in $Item.Keys) { if ($Key -notin $ExcludeProperty) { $NewObject[$Key] = $Item[$Key] } } } elseif ($Item -isnot [Array] -and $Item -isnot [System.Collections.IEnumerable]) { foreach ($Prop in $Item.PSObject.Properties) { if ($Prop.IsGettable -and $Prop.Name -notin $ExcludeProperty) { $NewObject["$($Prop.Name)"] = $Item.$($Prop.Name) } } } else { $NewObject = $Item } $Iterate["$i"] = $NewObject $i += 1 } } else { foreach ($Prop in $Object.PSObject.Properties) { if ($Prop.IsGettable -and $Prop.Name -notin $ExcludeProperty) { $Iterate["$($Prop.Name)"] = $Object.$($Prop.Name) } } } } If ($Iterate.Keys.Count) { foreach ($Key in $Iterate.Keys) { if ($Key -notin $ExcludeProperty) { ConvertTo-FlatObject -Objects @(, $Iterate["$Key"]) -Separator $Separator -Base $Base -Depth $Depth -Path ($Path + $Key) -OutputObject $OutputObject -ExcludeProperty $ExcludeProperty } } } else { $Property = $Path -Join $Separator if ($Property) { # We only care if property is not empty if ($Object -is [System.Collections.IDictionary] -and $Object.Keys.Count -eq 0) { $OutputObject[$Property] = $null } else { $OutputObject[$Property] = $Object } } } } elseif ($InputObjects.Count -gt 0) { foreach ($ItemObject in $InputObjects) { $OutputObject = [ordered]@{} ConvertTo-FlatObject -Objects @(, $ItemObject) -Separator $Separator -Base $Base -Depth $Depth -Path $Path -OutputObject $OutputObject -ExcludeProperty $ExcludeProperty [PSCustomObject] $OutputObject } } } } #EndRegion '.\Private\ConvertTo-FlatObject.ps1' 203 #Region '.\Private\Get-PrivateFunction.ps1' -1 function Get-PrivateFunction { <# .SYNOPSIS This is a sample Private function only visible within the module. .DESCRIPTION This sample function is not exported to the module and only return the data passed as parameter. .EXAMPLE $null = Get-PrivateFunction -PrivateData 'NOTHING TO SEE HERE' .PARAMETER PrivateData The PrivateData parameter is what will be returned without transformation. #> [cmdletBinding()] [OutputType([string])] param ( [Parameter()] [String] $PrivateData ) process { Write-Output $PrivateData } } #EndRegion '.\Private\Get-PrivateFunction.ps1' 32 #Region '.\Private\Get-SEPCloudAPIData.ps1' -1 function Get-SEPCloudAPIData { [CmdletBinding()] param ( $endpoint ) process { $api = @{ 'Example' = @{ '1.0' = @{ Description = 'Details about the API endpoint' URI = 'The URI expressed as /api/v#/endpoint' Method = 'Method to use against the endpoint' Body = 'Parameters to use in the body' Query = 'Parameters to use in the URI query' Result = 'If the result content is stored in a higher level key, express it here to be unwrapped in the return' Success = 'The expected HTTP status code for a successful call' Function = 'The PowerShell function to call to process the result' ObjectTName = 'The name of the PSType object to return' } } 'Block-SEPCloudFile' = @{ '1.0' = @{ Description = 'Quarantine files on the device(s)' URI = '/v1/commands/files/contain' Method = 'Post' Body = @{ device_ids = 'device_ids' hash = 'hash' } Query = '' Result = '' Success = '' Function = 'Block-SEPCloudFile' ObjectTName = 'SEPCloud.block-file' } } 'Connect-SEPCloud' = @{ '1.0' = @{ Description = 'Generate new bearer token from the from the oAuth credential' URI = '/v1/oauth2/tokens' Method = 'Post' Body = '' Query = '' Result = '' Filter = '' Success = '200' } } 'Get-SEPCloudComponentType' = @{ '1.0' = @{ Description = 'lets you retrieve policy component host-groups, network-adapters(adapter), network-services(Connection), network IPS details' URI = '/v1/policies/components' Method = 'Get' Body = '' Query = @{ 'offset' = 'offset' 'limit' = 'limit' } Result = 'data' Success = '' Function = 'Get-SEPCloudComponentType' ObjectTName = 'SEPCloud.policyComponentType' # generic PSObject but there could be up to 4 different subtypes # host-group-response # network-services # network-adapter # network_ips_response } } 'Get-SEPCloudCommand' = @{ '1.0' = @{ Description = 'lets you retrieve a list of all commands' URI = '/v1/commands' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudCommand' ObjectTName = 'SEPCloud.Command' } } 'Get-SEPCloudDevice' = @{ '1.0' = @{ Description = 'retrieve the list of devices' URI = '/v1/devices' Method = 'Get' Body = '' Query = @{ offset = 'offset' client_version = 'client_version' device_group = 'device_group' # ID of the parent device group device_status = 'device_status' device_status_reason = 'device_status_reason' device_type = 'device_type' edr_enabled = 'edr_enabled' ipv4_address = 'ipv4_address' include_details = 'include_details' # flag to include product and feature details in response. Possible values: true/false is_cloud = 'is_cloud' is_online = 'is_online' is_virtual = 'is_virtual' mac_address = 'mac_address' name = 'name' os = 'os' # Possible values: windows, Linux, iOS, Mac, Android os_version = 'os_version' } Result = 'devices' Success = '' Function = 'Get-SEPCloudDevice' ObjectTName = 'SEPCloud.Device' } } 'Get-SEPCloudDeviceDetails' = @{ '1.0' = @{ Description = 'Details about the SEP client' URI = '/v1/devices' Method = 'Get' Body = '' Query = @{ device_id = 'device_id' } Result = '' Success = '' Function = 'Get-SEPCloudDeviceDetails' ObjectTName = 'SEPCloud.device-details ' } } 'Get-SEPCloudEDRDumpsList' = @{ '1.0' = @{ Description = 'get the list of endpoint search commands' URI = '/v1/commands/endpoint-search' Method = 'Post' Body = @{ query = 'query' next = 'next' limit = 'limit' } Query = '' Result = 'commands' Success = '' Function = 'Get-SEPCloudEDRDumpsList' ObjectTName = 'SEPCloud.commandsResponse' } } 'Get-SEPCloudEvents' = @{ '1.0' = @{ Description = 'retrieve up to ten thousand events' URI = '/v1/event-search' Method = 'Post' Body = @{ feature_name = 'feature_name' product = 'product' query = 'query' start_date = 'start_date' end_date = 'end_date' next = 'next' limit = 'limit' } Query = '' Result = 'events' Success = '' Function = 'Get-SEPCloudEvents' ObjectTName = 'SEPCloud.Event' } } 'Get-SepCloudFeatureList' = @{ '1.0' = @{ Description = 'retrieve up to ten thousand events' URI = '/v1/devices/enums' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudFeatureList' ObjectTName = 'SEPCloud.FeatureList' } } 'Get-SEPCloudFileHashDetails' = @{ '1.0' = @{ Description = 'retrieve all details of a file based off its hash' URI = '/v1/threat-intel/protection/file/{id}' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudFileHashDetails' ObjectTName = 'SEPCloud.files-hash' } } 'Get-SEPCloudGroup' = @{ '1.0' = @{ Description = 'retrieve a list of device groups' URI = '/v1/device-groups' Method = 'Get' body = '' Query = @{ offset = 'offset' } Result = 'device_groups' Success = '200' Function = 'Get-SEPCloudGroupTest' ObjectTName = 'SEPCloud.Device-Group' # root object is 'SEPCloud.Device-Group-List' but children objects only are exposed as 'SEPCloud.Device-Group' } } 'Get-SEPCloudGroupPolicies' = @{ '1.0' = @{ Description = 'retrieve a list of policies that are targeted on a device group' URI = '/v1/device-groups/{id}/policies' Method = 'Get' body = '' Query = @{ group_id = 'group_id' } Result = 'policies' Success = '200' Function = 'Get-SEPCloudGroupPolicies' ObjectTName = 'SEPCloud.targeted-policy' } } 'Get-SepCloudIncidents' = @{ '1.0' = @{ Description = 'retrieve incidents and incident events' URI = '/v1/incidents' Method = 'Post' body = @{ start_date = 'start_date' end_date = 'end_date' next = 'next' limit = 'limit' include_events = 'include_events' query = 'query' } Query = '' Result = 'incidents' Success = '200' Function = 'Get-SepCloudIncidents' ObjectTName = 'SEPCloud.incident-response' } } 'Get-SepCloudIncidentDetails' = @{ '1.0' = @{ Description = 'retrieve details for a specific incident' URI = '/v1/incidents' Method = 'Get' body = '' Query = @{ incident_id = 'incident_id' } Result = 'incident' Success = '200' Function = 'Get-SepCloudIncidentDetails' ObjectTName = 'SEPCloud.incident-details' } } 'Get-SEPCloudPolicesSummary' = @{ '1.0' = @{ Description = 'retrieve a list of your policies (without details)' URI = '/v1/policies' Method = 'Get' Body = '' Query = @{ limit = 'limit' offset = 'offset' name = 'name' type = 'type' } Result = 'policies' Success = '' Function = 'Get-SEPCloudPolicesSummary' ObjectTName = 'SEPCloud.policy' } } 'Get-SEPCloudPolicyDetails' = @{ '1.0' = @{ Description = 'lets you retrieve the details for a policy by using its uid and version.' URI = '/v1/policies/{id}/versions/{id}' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudPolicyDetails' ObjectTName = 'SEPCloud.policy-by-uid' } } 'Get-SepCloudTargetRules' = @{ '1.0' = @{ Description = 'retrieve a list of target rules' URI = '/v1/policies/target-rules' Method = 'Get' Body = '' Query = @{ limit = 'limit' offset = 'offset' } Result = 'target_rules' Success = '' Function = 'Get-SepCloudTargetRules' ObjectTName = 'SEPCloud.target-rule' } } 'Get-SEPCloudThreatIntelCveProtection' = @{ '1.0' = @{ Description = 'returns information whether a given CVE has been blocked by any Symantec technologies' URI = '/v1/threat-intel/protection/cve' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelCveProtection' ObjectTName = 'SEPCloud.cve-protection' } } 'Get-SEPCloudThreatIntelFileInsight' = @{ '1.0' = @{ Description = 'returns file insight enrichments for given file sha256' URI = '/v1/threat-intel/insight/file' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelFileInsight' ObjectTName = 'SEPCloud.file-insight' } } 'Get-SEPCloudThreatIntelNetworkInsight' = @{ '1.0' = @{ Description = 'returns network enrichments for given URL, domain or IP' URI = '/v1/threat-intel/insight/network' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelNetworkInsight' ObjectTName = 'SEPCloud.network-insight' } } 'Get-SEPCloudThreatIntelFileProtection' = @{ '1.0' = @{ Description = 'returns information whether a given file has been blocked by any Symantec technologies' URI = '/v1/threat-intel/protection/file/{id}' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelFileProtection' ObjectTName = 'SEPCloud.file-protection' } } 'Get-SEPCloudThreatIntelFileRelated' = @{ '1.0' = @{ Description = 'returns information whether a given file has been blocked by any Symantec technologies' URI = '/v1/threat-intel/related/file/' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelFileRelated' ObjectTName = 'SEPCloud.file-related' } } 'Get-SEPCloudThreatIntelNetworkProtection' = @{ '1.0' = @{ Description = 'returns information whether a given file has been blocked by any Symantec technologies' URI = '/v1/threat-intel/protection/network' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelNetworkProtection' ObjectTName = 'SEPCloud.network-protection' } } 'Get-SEPCloudThreatIntelFileProcessChain' = @{ '1.0' = @{ Description = 'returns topK process lineage enrichment for the provided file sha256' URI = '/v1/threat-intel/processchain/file' Method = 'Get' Body = '' Query = '' Result = '' Success = '' Function = 'Get-SEPCloudThreatIntelFileProcessChain' ObjectTName = 'SEPCloud.file-processchain' } } 'Move-SEPCloudDevice' = @{ '1.0' = @{ Description = 'lets you transfer multiple devices from one device group to another device group' URI = '/v1/device-groups/{id}/devices' Method = 'Put' Body = @{ device_uids = 'device_uids' } Query = '' Result = '' Success = '' Function = 'Move-SEPCloudDevice' ObjectTName = 'SEPCloud.Bulk-Device-List' } } 'New-SEPCloudEDRFullDump' = @{ '1.0' = @{ Description = 'Send the full dump command on the device' URI = '/v1/commands/endpoint-search/fulldump' Method = 'Post' Body = @{ device_id = 'device_id' description = 'description' from_date = 'from_date' to_date = 'to_date' } Query = '' Result = '' Success = '' Function = 'New-SEPCloudEDRFullDump' ObjectTName = 'SEPCloud.DumpCommandResponse' } } 'Remove-SEPCloudPolicy' = @{ '1.0' = @{ Description = 'Removes a SEP Cloud policy from a device group' URI = '/v1/policies/{id}/versions/{id}/device-groups' Method = 'Delete' Body = @{ target_rules = 'target_rules' device_group_ids = 'device_group_ids' } Query = '' Result = '' Success = '' Function = 'Remove-SEPCloudPolicy' ObjectTName = 'SEPCloud.remove-policy' } } 'Set-SEPCloudPolicy' = @{ '1.0' = @{ Description = 'apply a policy to device groups' URI = '/v1/policies/{id}/versions/{id}/device-groups' Method = 'Post' Body = @{ target_rules = 'target_rules' device_group_ids = 'device_group_ids' override = 'override' } Query = '' Result = '' Success = '204' Function = 'Set-SEPCloudPolicy' ObjectTName = 'SEPCloud.apply-policy' } } 'Start-SEPCloudDefinitionUpdate' = @{ '1.0' = @{ Description = 'Update security definitions of devices' URI = '/v1/commands/update_content' Method = 'Post' Body = @{ device_ids = 'device_ids' org_unit_ids = 'org_unit_ids' is_recursive = 'is_recursive' } Query = '' Result = '' Success = '' Function = 'Start-SEPCloudDefinitionUpdate' ObjectTName = 'SEPCloud.DeviceCommandResponse' } } 'Start-SEPCloudFullScan' = @{ '1.0' = @{ Description = 'initiate a full scan on devices managed' URI = '/v1/commands/scans/full' Method = 'Post' Body = @{ device_ids = 'device_ids' org_unit_ids = 'org_unit_ids' is_recursive = 'is_recursive' } Query = '' Result = '' Success = '' Function = 'Start-SEPCloudFullScan' ObjectTName = 'SEPCloud.DeviceCommandResponse' } } 'Start-SepCloudQuickScan' = @{ '1.0' = @{ Description = 'initiate a quick scan on devices managed' URI = '/v1/commands/scans/quick' Method = 'Post' Body = @{ device_ids = 'device_ids' org_unit_ids = 'org_unit_ids' is_recursive = 'is_recursive' } Query = '' Result = '' Success = '' Function = 'Start-SepCloudQuickScan' ObjectTName = 'SEPCloud.DeviceCommandResponse' } } } # Use the latest version of the API endpoint $version = $api.$endpoint.Keys | Sort-Object | Select-Object -Last 1 if ($null -eq $version) { $ErrorSplat = @{ Message = "No matching endpoint found for $Endpoint that corresponds to the current cluster version." ErrorAction = 'Stop' TargetObject = $api.$endpoint.keys -join ',' Category = 'ObjectNotFound' } Write-Error @ErrorSplat } else { Write-Verbose -Message "Selected $version API Data for $endpoint" return $api.$endpoint.$version } } } #EndRegion '.\Private\Get-SEPCloudAPIData.ps1' 537 #Region '.\Private\Get-SEPCloudGroupFullPath.ps1' -1 function Get-SEPCloudGroupFullPath { <# .SYNOPSIS Recursively builds a chain of group names from a group to the root. .DESCRIPTION Recursively builds a chain of group names from a group to the root. .EXAMPLE Get-SEPCloudGroupFullPath -CurrentGroup $Group -AllGroups $Groups #> param ( [PSCustomObject]$CurrentGroup, [Array]$AllGroups, [String]$Chain = "" ) # If $allGroups is provided, build the chain from the list of groups. if ($AllGroups) { # If the current group is root (no parent_id), prepend its name to the chain. if (-not $CurrentGroup.parent_id) { if ($Chain -eq "") { return $CurrentGroup.name # If chain is empty, it's the root group. } else { return $CurrentGroup.name + "\" + $Chain # Prepend root name to chain. } } else { # Find the parent group. $ParentGroup = $AllGroups | Where-Object { $_.id -eq $CurrentGroup.parent_id } if ($ParentGroup) { # If there's a parent, prepend the parent's name to the chain and recurse. $NewChain = if ($Chain -eq "") { $CurrentGroup.name } else { $CurrentGroup.name + "\" + $Chain } return Get-SEPCloudGroupFullPath -CurrentGroup $ParentGroup -AllGroups $AllGroups -Chain $NewChain } else { # If no parent found (which shouldn't happen), return the current chain. return $Chain } } } # If the allGroups parameter was not provided, recursively build the path by querying the API group by group ID. else { # If the current group is root (no parent_id), prepend its name to the chain. if (-not $CurrentGroup.parent_id) { if ($Chain -eq "") { return $CurrentGroup.name # If chain is empty, it's the root group. } else { return $CurrentGroup.name + "\" + $Chain # Prepend root name to chain. } } else { # Find the parent group. $parentGroupId = $CurrentGroup.parent_id if ($parentGroupId) { # If there's a parent $parentGroup = Get-SEPCloudGroup -GroupID $parentGroupId # prepend the parent's name to the chain and recurse. $NewChain = if ($Chain -eq "") { $CurrentGroup.name } else { $CurrentGroup.name + "\" + $Chain } return Get-SEPCloudGroupFullPath -CurrentGroup $parentGroup -Chain $NewChain } else { # If no parent found (which shouldn't happen), return the current chain. return $Chain } } } } #EndRegion '.\Private\Get-SEPCloudGroupFullPath.ps1' 104 #Region '.\Private\Invoke-SEPCloudWebRequest.ps1' -1 function Invoke-SEPCloudWebRequest { <# .SYNOPSIS Gather WebRequest from a URL or redirect URL. .DESCRIPTION Gather WebRequest from a URL or redirect URL. Preserves the Authorization header upon redirect. This function is a wrapper around the System.Net.WebRequest class. .PARAMETER Uri URL to gather WebRequest from. .PARAMETER Method HTTP method to use. .PARAMETER Headers Headers to include in the request. Must be a hashtable as per example below. .OUTPUTS JSON object .EXAMPLE $params = @{ Method = 'GET' Uri = "https://example.com/v1/endpoint" Headers = @{ Host = "https://example.com/v1/endpoint" Accept = "application/json" Authorization = "Bearer xxxxxxxx" } queryParameters = @{ "ComputerName" = "MyComputer01" } } Invoke-SEPCloudWebRequest @params This example will : - Send a GET request to https://example.com/v1/endpoint - With the Authorization header set to "Bearer xxxxxxxx" - With the query parameter ComputerName set to "MyComputer01" (https://example.com/v1/endpoint?ComputerName=MyComputer01) .EXAMPLE $params = @{ Method = 'POST' Uri = "https://example.com/v1/endpoint" Headers = @{ Host = "https://example.com/v1/endpoint" Accept = "application/json" Authorization = "Bearer xxxxxxxx" } body = @{ "ComputerName" = "MyComputer01" } } Invoke-SEPCloudWebRequest @params This example will : - Send a POST request to https://example.com/v1/endpoint - With the Authorization header set to "Bearer xxxxxxxx" - With the body set to JSON format {"ComputerName":"MyComputer01"} #> [CmdletBinding()] param ( # URL [Parameter(Mandatory = $true)] [string]$uri, # Method [Parameter(Mandatory = $true)] [string]$method, # List of headers [Parameter(Mandatory = $true)] [hashtable]$headers, # Query parameters [hashtable]$queryStrings = @{}, # Body [hashtable]$body = @{} ) process { # Add query parameters if ($queryStrings.Count -gt 0) { # Construct the URI $uri = Build-QueryURI -BaseURI $uri -QueryStrings $queryStrings } # Initial request $initialRequest = [System.Net.WebRequest]::CreateHttp($uri); $initialRequest.Method = $method $initialRequest.AllowAutoRedirect = $false # Add body if ($body.Count -gt 0) { $initialRequest.ContentType = "application/json" $json = $body | ConvertTo-Json -Depth 100 $bytes = [System.Text.Encoding]::UTF8.GetBytes($json) $initialRequest.ContentLength = $bytes.Length $initialRequestStream = $initialRequest.GetRequestStream() $initialRequestStream.Write($bytes, 0, $bytes.Length) $initialRequestStream.Close() } # Add headers foreach ($header in $Headers.GetEnumerator()) { $initialRequest.Headers.Add($header.Key, $header.Value) } # Send the initial request try { $inititalResponse = $initialRequest.GetResponse(); Write-Verbose -Message "URI = $($inititalResponse.GetResponseHeader("Location"))" Write-Verbose -Message "Status code : $($inititalResponse.StatusCode)" } catch { throw $_ } # IF HTTP status code is linked to redirected URL if ($inititalResponse.StatusCode.value__ -in (301, 302, 303, 307, 308)) { Write-Verbose -Message "URI to redirect : $($inititalResponse.GetResponseHeader("Location"))" # Create new request with the redirect URL $redirectUrl = $inititalResponse.GetResponseHeader("Location") $newRequest = [System.Net.WebRequest]::CreateHttp($redirectUrl); $newRequest.Method = $Method $newRequest.AllowAutoRedirect = $false # Add query parameters if ($queryStrings.Count -gt 0) { # Construct the URI $uri = Build-QueryURI -BaseURI $uri -QueryStrings $queryStrings } # Add body if ($body.Count -gt 0) { $newRequest.ContentType = "application/json" $json = $body | ConvertTo-Json -Depth 100 $bytes = [System.Text.Encoding]::UTF8.GetBytes($json) $newRequest.ContentLength = $bytes.Length $newRequestStream = $newRequest.GetRequestStream() $newRequestStream.Write($bytes, 0, $bytes.Length) $newRequestStream.Close() } # Add headers # TODO verify why when adding all the headers and not just the Authorization header, the request fails wih 400 # Reuse all headers from the initial request (including Authorization header) foreach ($header in $Headers.GetEnumerator()) { $newRequest.Headers.Add($header.Key, $header.Value) } # $newRequest.Headers.Add("Authorization", $Headers.Authorization) # $newRequest.Headers.Add("Accept", $Headers.Accept) # $newRequest.Headers.Add("Host", $Headers.Host) # Send the new request try { $newResponse = $newRequest.GetResponse() Write-Verbose -Message "Status Code : $($newResponse.StatusCode.value__)" } catch { Write-Error "Error in Invoke-SEPCloudWebRequest: $($_.Exception.InnerException.Message)" } # Parse the response $stream = $newResponse.GetResponseStream() $reader = New-Object System.IO.StreamReader($stream) $content = $reader.ReadToEnd() } else { # Get the response from the initial request $stream = $inititalResponse.GetResponseStream() $reader = New-Object System.IO.StreamReader($stream) $content = $reader.ReadToEnd() } return $content | ConvertFrom-Json -Depth 100 } } #EndRegion '.\Private\Invoke-SEPCloudWebRequest.ps1' 191 #Region '.\Private\New-BodyString.ps1' -1 function New-BodyString($bodykeys, $parameters) { <# .SYNOPSIS Function to create the body payload for an API request .DESCRIPTION This function compares the defined body parameters within Get-SEPCloudAPIData with any parameters set within the invocation process. If matches are found, a properly formatted and valid body payload is created and returned. .PARAMETER bodykeys All of the body options available to the endpoint .PARAMETER parameters All of the parameter options available within the parent function #> # If sending a GET request, no body is needed if ($resources.Method -eq 'Get') { return $null } # Look at the list of parameters that were set by the invocation process # This is how we know which params were actually set by the call, versus defaulting to some zero, null, or false value # Now that custom params are added, let's inventory all invoked params Write-Verbose -Message 'Build the body parameters' $bodystring = @{ } # Walk through all of the available body options presented by the endpoint # Note: Keys are used to search in case the value changes in the future across different API versions foreach ($body in $bodykeys) { Write-Verbose "Adding $body..." # Array Object if ($resources.Body.$body.GetType().BaseType.Name -eq 'Array') { $bodyarray = $resources.Body.$body.Keys $arraystring = @{ } foreach ($arrayitem in $bodyarray) { # Walk through all of the parameters defined in the function # Both the parameter name and parameter alias are used to match against a body option # It is suggested to make the parameter name "human friendly" and set an alias corresponding to the body option name foreach ($param in $parameters) { # If the parameter name or alias matches the body option name, build a body string if ($param.Name -eq $arrayitem -or $param.Aliases -eq $arrayitem) { # Switch variable types if ((Get-Variable -Name $param.Name).Value.GetType().Name -eq 'SwitchParameter') { $arraystring.Add($arrayitem, (Get-Variable -Name $param.Name).Value.IsPresent) } # All other variable types elseif ($null -ne (Get-Variable -Name $param.Name).Value) { $arraystring.Add($arrayitem, (Get-Variable -Name $param.Name).Value) } } } } $bodystring.Add($body, @($arraystring)) } # Non-Array Object else { # Walk through all of the parameters defined in the function # Both the parameter name and parameter alias are used to match against a body option # It is suggested to make the parameter name "human friendly" and set an alias corresponding to the body option name foreach ($param in $parameters) { # If the parameter name or alias matches the body option name, build a body string if (($param.Name -eq $body -or $param.Aliases -eq $body)) { if ((Get-Variable -Name $param.Name).Value) { # Switch variable types if ((Get-Variable -Name $param.Name).Value.GetType().Name -eq 'SwitchParameter') { $bodystring.Add($body, (Get-Variable -Name $param.Name).Value.IsPresent) } # All other variable types elseif ($null -ne (Get-Variable -Name $param.Name).Value -and (Get-Variable -Name $param.Name).Value.Length -gt 0) { $bodystring.Add($body, (Get-Variable -Name $param.Name).Value) } } } } } } # Store the results into a JSON string if (0 -ne $bodystring.count) { # $bodystring = ConvertTo-Json -InputObject $bodystring Write-Verbose -Message "Body = $(ConvertTo-Json -InputObject $bodystring)" } else { Write-Verbose -Message 'No body for this request' } return $bodystring } #EndRegion '.\Private\New-BodyString.ps1' 110 #Region '.\Private\New-QueryString.ps1' -1 function New-QueryString($query, $uri) { <# .SYNOPSIS Adds query parameters to a URI .DESCRIPTION This function compares the defined query parameters within SEPCloudAPIData with any parameters set within the invocation process. If matches are found, a properly formatted and valid query string is created and appended to a returned URI .PARAMETER query An array of query values that are added based on which $objects have been passed by the user .PARAMETER uri The entire URI without any query values added #> # TODO: It seems like there's a more elegant way to do this logic, but this code is stable and functional. foreach ($_ in $query) { # The query begins with a "?" character, which is appended to the $uri after determining that at least one $params was collected if ($_ -eq $query[0]) { $uri += '?' + $_ } # Subsequent queries are separated by a "&" character else { $uri += '&' + $_ } } return $uri } #EndRegion '.\Private\New-QueryString.ps1' 35 #Region '.\Private\New-URIQuery.ps1' -1 function New-URIQuery($queryKeys, $parameters, $uri) { <# .SYNOPSIS Builds a URI with query parameters for an uri .DESCRIPTION Builds a URI with query parameters for an uri. This function takes a list of keys and values, and constructs an URI with the query parameters. .PARAMETER queryKeys The query keys as defined in Get-SEPCloudAPIData .PARAMETER parameters The set of parameters passed as query values .PARAMETER uri The base URI to build from #> # Construct the uri $builder = New-Object System.UriBuilder($uri) $query = [System.Web.HttpUtility]::ParseQueryString($builder.Query) Write-Verbose -Message "Build the query parameters for $(if ($queryKeys){$queryKeys -join ','}else{'<null>'})" # Walk through all of the available query options foreach ($queryKey in $queryKeys) { # Walk through all of the parameters defined in the function # Both the parameter name and parameter alias are used to match against a query option # This will allow for easier readability of the code foreach ($param in $parameters) { # If the parameter name matches the query option name, build a query string if ($param.ContainsKey($queryKey)) { if ($null -ne $param.Values) { $query.Add($queryKey, $param[$queryKey]) } } } } $builder.Query = $query.ToString() $uri = $builder.Uri.AbsoluteUri Write-Verbose -Message "URI = $uri" return $uri } #EndRegion '.\Private\New-URIQuery.ps1' 50 #Region '.\Private\New-URIString.ps1' -1 function New-URIString { <# .SYNOPSIS Builds a valid URI .DESCRIPTION Builds a valid URI based off of the constructs defined in the Get-SEPCLoudAPIData resources for the cmdlet. Inserts any object IDs into the URI if {id} is specified within the constructs. .PARAMETER baseURL The base URL for the API .PARAMETER id The ID of an object to be inserted into the URI Accepts an array of IDs from 0 to 2 strings .PARAMETER endpoint The endpoint to be inserted into the URI Optionally at the end of the base URL if no {id} is specified .EXAMPLE New-URIString -baseURL "192.168.3.11" -id 56789 -endpoint "/v1/device-groups" Returns "https://192.168.3.11/v1/device-groups/56789" .EXAMPLE New-URIString -baseURL "192.168.3.11" -id 56789 -endpoint "/v1/device-groups/{id}/devices" Returns "https://192.168.3.11/v1/device-groups/56789/devices" #> [CmdletBinding()] param ( [Parameter()] [string] $baseURL = $script:SEPCloudConnection.BaseURL, [Parameter()] [ValidateCount(0, 2)] [array] $id, [Parameter( Mandatory = $true )] [string] $endpoint ) Write-Verbose -Message 'Build the URI' $uri = ('https://' + $baseUrl + $endpoint) # If we find {id} in the path, replace it with the $id value if ($endpoint -match '{id}') { # regex to replace the {id} with the next value in the array $idx = @(0) $uri = [regex]::Replace($uri, '{id}|$', { # if there is a "next value" in the list if ($next = $id[$idx[0]++]) { # if matching EOL if (-not $args[0].Value) { return '/' + $next } else { $next } } }) } # Otherwise, only add the $id value at the end if it exists (for single object retrieval) else { # If $id has 2 elements can't append both ids to URI if ($id.Count -gt 1) { $message = "2 ids provided : '$id'" $message += "endpoint $endpoint allows only one id :" Write-Error -Message $message -ErrorAction Stop } if ($id.Count -eq 1) { $uri += "/$id" } } Write-Verbose -Message "URI = $uri" return $uri } # live test # $BaseURL = "api.my.test.com" # $endpoint = "/v1/{id}/device-groups" # $id = @("123456", "789012") # New-URIString -endpoint $endpoint -id $id -baseURL $BaseURL #EndRegion '.\Private\New-URIString.ps1' 97 #Region '.\Private\New-UserAgentString.ps1' -1 function New-UserAgentString { <# .SYNOPSIS Helper function, creates a user agent string .DESCRIPTION Function that generates a user agent string containing the module name, version and OS / platform information .NOTES Written by Jaap Brasser for community usage Twitter: @jaap_brasser GitHub: jaapbrasser .EXAMPLE New-UserAgentString PSSymantecCloud-0.0--7.4.2--platform--Win32NT--platform_version--Microsoft.Windows.10.0.22631 Will generate a new user agent string containing the module name, version and OS / platform information New-UserAgentString -UserAgentHash @{platform_integration='Poshbot.Rubrik'} Will generate a new user agent string containing the module name, version and OS / platform information with the additional information specified in UserAgentHash #> param( [hashtable] $UserAgentHash ) process { $OS, $OSVersion = if ($psversiontable.PSVersion.Major -lt 6) { 'Win32NT' try { Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop | ForEach-Object { ($_.Name -Split '\|')[0], $_.BuildNumber -join '' } } catch { } } else { $psversiontable.platform if ($psversiontable.os.Length -gt 64) { $psversiontable.os.Substring(0, 64) -replace ':', '.' $psversiontable.os.Substring(0, 64) -replace ' ', '.' } else { $psversiontable.os.Trim() -replace ' ', '.' } } $PlatformDetails = "platform--$OS--platform_version--$OSVersion" $ModuleVersion = try { if (-not [string]::IsNullOrWhiteSpace($MyInvocation.MyCommand.ScriptBlock.Module.PrivateData.PSData.Prerelease)) { $MyInvocation.MyCommand.ScriptBlock.Module.Version.ToString(), $MyInvocation.MyCommand.ScriptBlock.Module.PrivateData.PSData.Prerelease.ToString() -join '.' } else { $MyInvocation.MyCommand.ScriptBlock.Module.Version.ToString() } } catch { } $UserAgent = "$script:ModuleName-{0}--{1}--{2}" -f $ModuleVersion, $psversiontable.psversion.tostring(), $PlatformDetails if ($UserAgentHash) { $UserAgentHash.keys | ForEach-Object -Begin { [string]$StringBuilder = '' } -Process { $StringBuilder += "--$_--$($UserAgentHash[$_])" } -End { $UserAgent += $StringBuilder } } return $UserAgent } } #EndRegion '.\Private\New-UserAgentString.ps1' 98 #Region '.\Private\Remove-SEPCloudToken.ps1' -1 function Remove-SEPCloudToken { <# TODO write help .SYNOPSIS This is a sample Private function only visible within the module. .DESCRIPTION This sample function is not exported to the module and only return the data passed as parameter. .EXAMPLE $null = Remove-SEPCloudToken -PrivateData 'NOTHING TO SEE HERE' .PARAMETER PrivateData The PrivateData parameter is what will be returned without transformation. #> [cmdletBinding()] [OutputType([string])] param() process { $script:SEPCloudConnection | Add-Member -MemberType NoteProperty -Name AccessToken -Value $null -Force -ErrorAction SilentlyContinue $script:configuration | Add-Member -MemberType NoteProperty -Name AccessToken -Value $null -Force -ErrorAction SilentlyContinue if ($script:configuration.CachedTokenPath) { try { Remove-Item $script:configuration.CachedTokenPath -Force } catch { Write-Error "$_" } } } } #EndRegion '.\Private\Remove-SEPCloudToken.ps1' 38 #Region '.\Private\Set-ObjectTypeName.ps1' -1 function Set-ObjectTypeName($typename, $result) { <# .SYNOPSIS Assigns an Object TypeName to cmdlet results .DESCRIPTION In order to better display results for cmdlets returning many objects with many properties TypeName formats may be used. This function will assign a TypeName if it exists to a set of returned objects. .PARAMETER typename The name of the TypeName to insert .PARAMETER result The response content which recieves the typename. #> process { if ($null -ne $result -and $null -ne $typename) { # Using ForEach-Object instead of .ForEach as .ForEach doesn't support single results. Write-Verbose -Message "Applying $typename TypeName to results" $result | ForEach-Object { $_.PSObject.TypeNames.Insert(0, $typename) } } return $result } } #EndRegion '.\Private\Set-ObjectTypeName.ps1' 33 #Region '.\Private\Submit-Request.ps1' -1 function Submit-Request { [cmdletbinding()] param( # The endpoint's URI $uri, # The header containing authentication details $header = $script:SEPCloudConnection.header, # The action (method) to perform on the endpoint $method = $($resources.Method), # Any optional body data being submitted to the endpoint $body ) Write-Verbose -Message 'Submitting the request' Write-Verbose -Message "method : $method" $WebResult = Invoke-SEPCloudWebRequest -Uri $uri -Headers $header -Method $method -Body $body return $WebResult } #EndRegion '.\Private\Submit-Request.ps1' 25 #Region '.\Private\Test-QueryObject.ps1' -1 function Test-QueryObject($object, $location, $query) { <# .SYNOPSIS Builds a query string for an endpoint .DESCRIPTION The Test-QueryObject function is used to build a custom query string for supported endpoints .PARAMETER object The parent function's variable holding the user generated query data .PARAMETER location The key/value pair that contains the correct query name value .PARAMETER params An array of query values that are added based on which $objects have been passed by the user #> if ((-not [string]::IsNullOrWhiteSpace($object)) -and ($location)) { # This builds the individual query item for the endpoint # Example: /vmware/vm?search_value=SE-CWAHL-WIN&limit=9999 contains 2 queries - search_value and limit return "$location=$object" } } #EndRegion '.\Private\Test-QueryObject.ps1' 27 #Region '.\Private\Test-QueryParam.ps1' -1 function Test-QueryParam($querykeys, $parameters, $uri) { <# .SYNOPSIS Builds a URI with query parameters for an endpoint .DESCRIPTION The Test-QueryParam function is used to build and test a custom query string for supported endpoints. .PARAMETER querykeys The endpoints query keys as defined in Get-SEPCloudAPIData .PARAMETER parameters The set of parameters passed within the cmdlets invocation .PARAMETER uri The endpoints URI #> Write-Verbose -Message "Build the query parameters for $(if ($querykeys){$querykeys -join ','}else{'<null>'})" $querystring = @() # Walk through all of the available query options presented by the endpoint # Note: Keys are used to search in case the value changes in the future across different API versions foreach ($query in $querykeys) { # Walk through all of the parameters defined in the function # Both the parameter name and parameter alias are used to match against a query option # It is suggested to make the parameter name "human friendly" and set an alias corresponding to the query option name foreach ($param in $parameters) { # If the parameter name matches the query option name, build a query string if (($param.Name -eq $query.Keys) -or ($param.Name -eq $query)) { if ((Get-Variable -Name $param.Name).Value) { Write-Verbose ('Building Query with "{0}: {1}"' -f $resources.Query[$param.Name], (Get-Variable -Name $param.Name).Value) } $querystring += Test-QueryObject -object (Get-Variable -Name $param.Name).Value -location $resources.Query[$param.Name] -params $querystring } # If the parameter alias matches the query option name, build a query string elseif (($param.Aliases -eq $query.Keys) -or ($param.Aliases -eq $query)) { if ((Get-Variable -Name $param.Name).Value) { Write-Verbose ('Building Query with "{0}: {1}"' -f (-join $resources.Query[$param.Aliases]), (Get-Variable -Name $param.Name).Value) } $querystring += Test-QueryObject -object (Get-Variable -Name $param.Name).Value -location $resources.Query[$param.Aliases] -params $querystring } } } # After all query options are exhausted, build a new URI with all defined query options $uri = New-QueryString -query $querystring -uri $uri Write-Verbose -Message "URI = $uri" return $uri } #EndRegion '.\Private\Test-QueryParam.ps1' 58 #Region '.\Private\Test-ReturnFormat.ps1' -1 function Test-ReturnFormat($result, $location) { <# .SYNOPSIS Removes parent encapsulation from returned responses .DESCRIPTION The Test-ReturnFormat function is used to remove any parent variables surrounding return data, such as encapsulating results in a "data" key .PARAMETER result The unformatted API response content .PARAMETER location The key/value pair that contains the name of the key holding the response content's data #> Write-Verbose -Message 'Formatting return value' if ($location -and ($null -ne ($result).$location)) { # The $location check assumes that not all endpoints will require findng (and removing) a parent key # If one does exist, this extracts the value so that the $result data is consistent across API versions return ($result).$location } else { # When no $location is found, return the original $result return $result } } #EndRegion '.\Private\Test-ReturnFormat.ps1' 30 #Region '.\Private\Test-SEPCloudConnection.ps1' -1 function Test-SEPCloudConnection { Write-Verbose -Message "Test-SEPCloudConnection: $script:SEPCloudConnection.AccessToken.Token" Write-Verbose -Message "Validate the SEP Cloud token" if (Test-SEPCloudToken) { Write-Verbose -Message "token valid - returning" return $True } else { Write-Verbose -Message "token expired or invalid - requesting a new one" Get-SEPCloudToken Write-Verbose -Message ("New token will expire at" + $((Get-Date) -lt $script:SEPCloudConnection.AccessToken.Expiration)) } } #EndRegion '.\Private\Test-SEPCloudConnection.ps1' 19 #Region '.\Private\Test-SEPCloudToken.ps1' -1 function Test-SEPCloudToken { [CmdletBinding()] param ( [Parameter()] [PSCustomObject] $token ) # Token passed as parameter if ($token) { if ((Get-Date) -lt $token.Expiration) { return $True } } # In memory token if ($script:SEPCloudConnection.AccessToken) { if ((Get-Date) -lt $script:SEPCloudConnection.AccessToken.Expiration) { return $True } else { Remove-SEPCloudToken return $false } } return $False } #EndRegion '.\Private\Test-SEPCloudToken.ps1' 35 #Region '.\Private\zz_Initialize-SEPCloudConfiguration.ps1' -1 #################################### # Init script for the whole module # #################################### ## This is the initialization script for the module. It is invoked at the end of the module's ## prefix file as "zz_" to load this module at last. This is done to ensure that all other functions are first loaded ## This function should be private but will stay Public for the moment as it needs to be the last function to be loaded in the module ## TODO make this function private # Update the data types when loading the module Update-TypeData -PrependPath (Join-Path -Path $PSScriptRoot -ChildPath 'PSSEPCloud.Types.ps1xml') # The credentials used to authenticate to the SES Cloud API [string] $script:Credential = $null # string type used as credentials is OAuth2 token # The session-cached copy of the module's configuration properties # Configuration contains user-defined properties # SEPCloudConnection contains the connection information to the SES Cloud API [PSCustomObject] $script:configuration = $null [PSCustomObject] $script:SEPCloudConnection = [PSCustomObject]@{ BaseURL = "api.sep.eu.securitycloud.symantec.com" Credential = $null AccessToken = $null time = (Get-Date) header = $null } # Module name [string] $script:ModuleName = "PSSymantecCloud" # Load the configuration file $script:configuration = [PSCustomObject]@{ BaseURL = "api.sep.securitycloud.symantec.com" SEPCloudCredsPath = [System.IO.Path]::Combine( [System.Environment]::GetFolderPath('LocalApplicationData'), 'PSSymantecCloud', 'creds.xml') CachedTokenPath = [System.IO.Path]::Combine( [System.Environment]::GetFolderPath('LocalApplicationData'), 'PSSymantecCloud', 'accessToken.xml') } function Initialize-SEPCloudConfiguration { <# .SYNOPSIS Populates the configuration of the module for this session, loading in any values that may have been saved to disk. .DESCRIPTION Populates the configuration of the module for this session, loading in any values that may have been saved to disk. .NOTES Internal helper method. This is actually invoked at the END of this file. #> [CmdletBinding()] param() # Load credential from disk if it exists if (Test-Path -Path $($script:configuration.SEPCloudCredsPath)) { try { Write-Verbose -Message "Loading credential from $($script:configuration.SEPCloudCredsPath)" $script:Credential = Import-Clixml -Path $($script:configuration.SEPCloudCredsPath) -ErrorAction SilentlyContinue $script:SEPCloudConnection.Credential = Import-Clixml -Path $($script:configuration.SEPCloudCredsPath) -ErrorAction SilentlyContinue } catch { Write-Verbose "No credentials found from $($script:configuration.SEPCloudCredsPath)" } } # Load access token from disk if (Test-Path -Path $($script:configuration.CachedTokenPath)) { try { Write-Verbose -Message "Loading access token from $($script:configuration.CachedTokenPath)" Add-Member -Type NoteProperty -Name AccessToken -Value (Import-Clixml -Path $($script:configuration.CachedTokenPath) -ErrorAction SilentlyContinue) -InputObject $SEPCloudConnection -Force } catch { Write-Verbose -Message "Failed to import access token from $($script:configuration.CachedTokenPath): $_" -Verbose } } # Test for existing access token and refresh token if (Test-SEPCloudToken) { # Load headers if access token exists $UserAgentString = New-UserAgentString $script:SEPCloudConnection.Header = @{ 'Authorization' = $script:SEPCloudConnection.AccessToken.Token_Bearer 'User-Agent' = $UserAgentString } } # Attempt to connect to the SaaS with cached token or credentials # Will only attempt to connect via cached method (token or credentials) and not prompt for credentials Connect-SEPCloud -cacheOnly } # Invoke the initialization method to populate the configuration Initialize-SEPCloudConfiguration #-Verbose #TODO remove verbose when done testing #EndRegion '.\Private\zz_Initialize-SEPCloudConfiguration.ps1' 109 #Region '.\Public\Block-SEPCloudFile.ps1' -1 function Block-SEPCloudFile { <# .SYNOPSIS Quarantines one or many files on one or many SEP Cloud managed endpoint .DESCRIPTION Quarantines one or many files on one or many SEP Cloud managed endpoint .PARAMETER device_ids The ID of the SEP Cloud managed endpoint to quarantine file(s) from .PARAMETER hash hash of the file to quarantine .LINK https://github.com/Douda/PSSymantecCloud .EXAMPLE Block-SEPCloudFile -Verbose -device_ids "dGKQS2SyQlCbPjC2VxqO0w" -hash "C4C3115E3A1AF01D6747401AA22AF90A047292B64C4EEFF4D8021CC0CB60B22D" BLocks a specific file on a specific computer by its device_id and hash #> [CmdletBinding()] Param( [Alias('deviceId')] [String[]] $device_ids, [Alias('sha256')] [String[]] $hash ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { # changing "Host" header specifically for this query, otherwise 500 $script:SEPCloudConnection.header += @{ 'Host' = $script:SEPCloudConnection.BaseURL } $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # removing the "Host" header specifically for this query, otherwise 500 $script:SEPCloudConnection.header.remove('Host') return $result } } #EndRegion '.\Public\Block-SEPCloudFile.ps1' 66 #Region '.\Public\Clear-SEPCloudAuthentication.ps1' -1 function Clear-SEPCloudAuthentication { <# .SYNOPSIS Clears out any API token from memory, as well as from local file storage. .DESCRIPTION Clears out any API token from memory, as well as from local file storage. .EXAMPLE Clear-SepCloudAuthentication Clears out any API token from memory, as well as from local file storage. #> [CmdletBinding(SupportsShouldProcess)] param () # Remove the cached authentication data from memory # Using if statements to avoid errors when the variable does not exist or not initialized if ($script:configuration.CachedToken) { $script:configuration.CachedToken = $null } if ($script:Credential) { $script:Credential = $null } if ($script:SEPCloudConnection.AccessToken) { $script:SEPCloudConnection.AccessToken = $null } if ($script:SEPCloudConnection.Credential) { $script:SEPCloudConnection.Credential = $null } # remove the cached authentication data from disk Remove-Item -Path $($script:configuration.CachedTokenPath) -Force -ErrorAction SilentlyContinue -ErrorVariable ev Remove-Item -Path $($script:configuration.SEPCloudCredsPath) -Force -ErrorAction SilentlyContinue -ErrorVariable ev if (($null -ne $ev) -and ($ev.Count -gt 0) -and ($ev[0].FullyQualifiedErrorId -notlike 'PathNotFound*')) { $message = "Experienced a problem trying to remove the file that persists the Access Token " + $($script:configuration.SEPCloudCredsPath) $message += "Experienced a problem trying to remove the file that persists the Access Credentials " + $($script:configuration.CachedTokenPath) Write-Warning -Message $message } } #EndRegion '.\Public\Clear-SEPCloudAuthentication.ps1' 49 #Region '.\Public\Connect-SEPCloud.ps1' -1 function Connect-SEPCloud { [CmdletBinding()] param ( # Additional information to be added, takes hashtable as input [hashtable] $UserAgent, [switch] $cacheOnly, $clientId, $secret ) process { # Create User Agent string $UserAgentString = New-UserAgentString -UserAgentHash $UserAgent $PSBoundParameters.Remove($UserAgent) | Out-Null Remove-Variable -Force -Name UserAgent -ErrorAction SilentlyContinue Write-Verbose -Message "Using User Agent $($UserAgentString)" # If called from Initialize-SEPCloudConfiguration # get token from cache only to avoid prompting for creds while loading the module if ($cacheOnly) { Write-Verbose -Message "Token request using cachedOnly" $token = Get-SEPCloudToken -cacheOnly } elseif ($clientId -and $secret) { Write-Verbose -Message "Token request using client and secret" $token = Get-SEPCloudToken -client $clientId -Secret $secret } else { $token = Get-SEPCloudToken } # if we have a token, add it to the header if ($null -ne $token) { $head = @{ 'Authorization' = "$($Token.Token_Bearer)"; 'User-Agent' = $UserAgentString#; # 'Host' = $($script:SEPCloudConnection.BaseURL) } $script:SEPCloudConnection | Add-Member -Type NoteProperty -Name 'header' -Value $head -Force } else { # If no token, just add User-Agent $head = @{ 'User-Agent' = $UserAgentString#; # 'Host' = $($script:SEPCloudConnection.BaseURL) } $script:SEPCloudConnection | Add-Member -Type NoteProperty -Name 'header' -Value $head -Force } } } #EndRegion '.\Public\Connect-SEPCloud.ps1' 59 #Region '.\Public\Get-SEPCloudComponentType.ps1' -1 function Get-SEPCloudComponentType { <# .SYNOPSIS This API lets you retrieve policy component host-groups, network-adapters(adapter), network-services(Connection), network IPS details .DESCRIPTION This API lets you retrieve policy component host-groups, network-adapters(adapter), network-services(Connection), network IPS details .NOTES Information or caveats about the function e.g. 'This function is not supported in Linux' .LINK https://github.com/Douda/PSSymantecCloud .EXAMPLE Get-SEPCloudComponentType -componentType 'network-adapters' Provides the full list of network adapters available on the cloud. #> [CmdletBinding()] Param( # Component Type is one of the list [Parameter( Mandatory = $true )] [ValidateSet( 'network-ips', 'host-groups', 'network-adapters', 'network-services' )] [string] $ComponentType, $offset, $limit = 1000 ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { # changing "Content-Type" header specifically for this query, otherwise 415 : unsupported media type $script:SEPCloudConnection.header += @{ 'Content-Type' = 'application/json' } $uri = New-URIString -endpoint ($resources.URI) -id $ComponentType $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if (($result.total -gt $result.data.count) -or ($result.total_count -gt $result.data.count)) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination $offset = $result.data.count $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.data += $nextResult.data } until (($result.data.count -ge $result.total) -or ($result.data.count -ge $result.total_count)) } $result = Test-ReturnFormat -result $result -location $resources.Result # apply correct PSType based on the 4 possible results options if ($null -ne $result.identification) { $resources.ObjectTName = "SEPCloud.adapter" } if ($null -ne $result.classifications) { $resources.ObjectTName = "SEPCloud.ips_metadata" } if ($null -ne $result.services) { $resources.ObjectTName = "SEPCloud.network-services" } if ($null -ne $result.hosts) { $resources.ObjectTName = "SEPCloud.host-group" } # Setting PSType to the correct type $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # Removing "Content-Type: application/json" header $script:SEPCloudConnection.header.remove('Content-Type') return $result } } #EndRegion '.\Public\Get-SEPCloudComponentType.ps1' 109 #Region '.\Public\Get-SEPCloudDevice.ps1' -1 function Get-SEPCloudDevice { <# .SYNOPSIS Gathers list of devices from the SEP Cloud console .DESCRIPTION Gathers list of devices from the SEP Cloud console .PARAMETER client_version Version of agent installed on device. [NOTE] Provide comma seperated values in case of multiple version search. .PARAMETER device_group ID of the parent device group. [NOTE] Provide comma seperated values in case of multiple name search. .PARAMETER device_status Device status Possible values: SECURE,AT_RISK, COMPROMISED,NOT_COMPUTED [NOTE] Provide comma seperated values in case of multiple status search. .PARAMETER device_type os type of the device [NOTE] Provide comma seperated values in case of multiple os type search. Possible values: WORKSTATION, SERVER, MOBILE .PARAMETER name name of the device. [NOTE] Provide comma seperated values in case of multiple name search. .PARAMETER ipv4_address ipv4 address of a device. .EXAMPLE Get-SEPCloudDevice Get all devices (very slow) .EXAMPLE Get-SEPCloudDevice -Computername MyComputer Get detailed information about a computer .EXAMPLE Get-SEPCloudDevice -client_version "14.2.1031.0100,14.2.770.0000" Get all devices with client version 14.2.1031.0100 and 14.2.770.0000 .EXAMPLE Get-SEPCloudDevice -device_group "Fmp5838YRsyElHM27PdZww,123456789" Get all devices from the 2 groups with the group IDs "Fmp5838YRsyElHM27PdZww" and "123456789 .EXAMPLE Get-SEPCloudDevice -device_status AT_RISK Get all online devices with AT_RISK status .EXAMPLE Get-SEPCloudDevice -Client_version "14.3.9681.7000" -device_type WORKSTATION Get all workstations with client version 14.3.9681.7000 .EXAMPLE Get-SEPCloudDevice -IPv4 "192.168.1.1" Get all devices with IPv4 address #> [CmdletBinding()] param ( [Alias("ClientVersion")] $client_version, [Alias("Group")] $device_group, [Alias("DeviceStatus")] [ValidateSet("SECURE", "AT_RISK", "COMPROMISED", "NOT_COMPUTED")] $device_status, [Alias("DeviceType")] [ValidateSet("WORKSTATION", "SERVER", "MOBILE")] $device_type, [Alias("IPv4")] $ipv4_address, [Alias("computername")] $name, [switch] $is_virtual, $offset ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.devices.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination $offset = $result.devices.count $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.devices += $nextResult.devices } until ($result.devices.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudDevice.ps1' 126 #Region '.\Public\Get-SEPCloudDeviceDetails.ps1' -1 function Get-SEPCloudDeviceDetails { <# .SYNOPSIS Gathers device details from the SEP Cloud console .DESCRIPTION Gathers device details from the SEP Cloud console .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER device_id id used to lookup a unique computer .OUTPUTS PSObject .EXAMPLE Get-SepCloudDeviceDetails -id wduiKXDDSr2CVrRaqrFKNx #> [CmdletBinding()] Param( [Parameter( ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] [Alias("id")] [string] $device_id ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $device_id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudDeviceDetails.ps1' 57 #Region '.\Public\Get-SEPCloudEDRDumpsList.ps1' -1 function Get-SEPCloudEDRDumpsList { <# .SYNOPSIS Gets a list of the SEP Cloud Commands .DESCRIPTION Gets a list of the SEP Cloud Commands. All commands are returned by default. .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER query Query to be used in the search Uses Lucene syntax. Is optional. If not used returns all commands by default .PARAMETER next The next page of results. Used for pagination .PARAMETER limit The maximum number of results returned. Used for pagination default is 25 .EXAMPLE Get-SEPCloudCommand Gets a list of the SEP Cloud Commands #> [CmdletBinding()] Param( $next, $limit = 25, $query ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.commands.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset/next query param for pagination $next = $result.next $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.commands += $nextResult.commands } until ($result.commands.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudEDRDumpsList.ps1' 77 #Region '.\Public\Get-SEPCloudEvents.ps1' -1 function Get-SEPCloudEvents { <# .SYNOPSIS Get list of SEP Cloud Events. By default it will gather data for past 30 days .DESCRIPTION Get list of SEP Cloud Events. You can use the following parameters to filter the results: FileDetection, FullScan, or a custom Lucene query .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER feature_name Filters events based on a product feature. [NOTE] ==== You can add a comma separated list of feature_name values (i.e. Agent Framework, Deception, Firewall) to define a unique set of events to search. ==== .PARAMETER product The value is SAEP. This represents Symantec Endpoint Security events. [NOTE] ==== SAEP is the only available product value. ==== .PARAMETER query A custom Lucene query to filter the results e.g. type_id:8001 .PARAMETER start_date This value identifies the beginning date to filter events. .PARAMETER end_date This value identifies the ending date to filter events. .PARAMETER next represents the starting index of the record in a given set.This is used for pagination. .PARAMETER limit This value identifies batch size.This is also used for pagination. .EXAMPLE Get-SepCloudEvents Gather all possible events. ** very slow approach & limited to 10k events ** .EXAMPLE Get-SepCloudEvents -Query "type_id:8031 OR type_id:8032 OR type_id:8033" Runs a custom Lucene query #> [CmdletBinding(DefaultParameterSetName = 'Query')] param ( $feature_name = "ALL", $product = "SAEP", $query, $start_date = ((Get-Date).AddDays(-29) | Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK"), # Default is 29 days ago $end_date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK"), # Default is today $next, # for pagination $limit = 1000 # Maximum number of results per page (API default = 100) ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.events.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination (called next) $next = $next + $result.next $uri = New-URIString -endpoint ($resources.URI) $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.events += $nextResult.events } until ($result.events.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudEvents.ps1' 94 #Region '.\Public\Get-SepCloudFeatureList.ps1' -1 function Get-SepCloudFeatureList { <# .SYNOPSIS retrieve SES enumeration details for your devices like feature names, security status and reason codes. .DESCRIPTION retrieve SES enumeration details for your devices like feature names, security status and reason codes. .PARAMETER None .INPUTS None .OUTPUTS PSObject .EXAMPLE Get-SepCloudFeatureList Gathers all possible feature name, content name, security status and reason codes the API can provide and its related IDs #> [CmdletBinding()] Param() begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $incidentId $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SepCloudFeatureList.ps1' 54 #Region '.\Public\Get-SEPCloudFileHashDetails.ps1' -1 function Get-SEPCloudFileHashDetails { <# .SYNOPSIS Returns information whether a given file has been blocked by any Symantec technologies .DESCRIPTION Returns information whether a given file has been blocked by any Symantec technologies .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER file_hash required hash to lookup .EXAMPLE Get-SEPCloudFileHashDetails -file_hash "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d" #> [CmdletBinding()] Param( [Alias('hash')] $file_hash ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $file_hash $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudFileHashDetails.ps1' 50 #Region '.\Public\Get-SEPCloudGroup.ps1' -1 function Get-SEPCloudGroup { <# .SYNOPSIS Gathers list of device groups from SEP Cloud .DESCRIPTION Gathers list of device groups from SEP Cloud. Does not contains device information .PARAMETER offset Page number to query. Defaults to 0. If pagination is required, this parameter is used to specify the page number .EXAMPLE Get-SEPCloudGroup Gets the full list of groups #> [CmdletBinding()] param ( # Query [Alias('api_page')] $offset ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.device_groups.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination $offset = $result.device_groups.count $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys $resources.query -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.device_groups += $nextResult.device_groups } until ($result.device_groups.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # Add custom property fullPathName Write-Verbose -Message "Adding new property fullPathName for each group" $result | ForEach-Object { $fullPathName = Get-SEPCloudGroupFullPath -CurrentGroup $_ -AllGroups $result -Chain "" $_ | Add-Member -NotePropertyName "fullPathName" -NotePropertyValue $fullPathName.TrimEnd(" > ") } return $result } } #EndRegion '.\Public\Get-SEPCloudGroup.ps1' 77 #Region '.\Public\Get-SEPCloudGroupPolicies.ps1' -1 function Get-SEPCloudGroupPolicies { <# .SYNOPSIS Gathers list of policies applied for a device group .DESCRIPTION Gathers list of policies applied for a device group .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER group_id id of device group .EXAMPLE Get-SEPCloudGroupPolicies -GroupID "Fmp5838YRsyElHM27PdZxx" Gets the list of every policies applied to a device group #> [CmdletBinding()] param ( # Group ID [Parameter( ValueFromPipelineByPropertyName = $true )] [Alias('groupID')] [String] $group_id ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $group_id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudGroupPolicies.ps1' 59 #Region '.\Public\Get-SEPCloudIncidentDetails.ps1' -1 function Get-SEPCloudIncidentDetails { <# .SYNOPSIS Gathers details about an open incident .DESCRIPTION Gathers details about an open incident .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER incidentId ID of incident .EXAMPLE Get-SEPCloudIncidentDetails -incident_ID "21b23af2-ea44-479c-a235-9540082da98f" #> [CmdletBinding()] Param( # Query [Alias('incident_id')] [String]$incidentId ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $incidentId $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudIncidentDetails.ps1' 56 #Region '.\Public\Get-SEPCloudIncidents.ps1' -1 function Get-SEPCloudIncidents { <# .SYNOPSIS Get list of SEP Cloud incidents .DESCRIPTION Get list of SEP Cloud incidents. Using the LUCENE query syntax, you can customize which incidents to gather. .PARAMETER start_date This value identifies the beginning date to filter incidents. The value should follow ISO 8601 date stamp standard format: yyyy-MM-dd’T’HH:mm:ss.SSSZ. Start date cannot be older than 30 days .PARAMETER end_date This value identifies the end date to filter incidents By default is thee time of the query (Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK") The value should follow ISO 8601 date stamp standard format: yyyy-MM-dd’T’HH:mm:ss.SSSZ. .PARAMETER limit Maximum number of results per page (default is 15) Maximum allowed page size is 2000 .PARAMETER next This value represents the starting index of the record in a given set.This is used for pagination If used, first request should always start with 0. If the response has next parameter set, request should be repeated with that next value .PARAMETER Include_events Includes every events that both are part of the context & triggered incident events .PARAMETER Query Custom Lucene query to pass to the API example: (state_id: 1 OR state_id: 4 ) Details on syntax : https://techdocs.broadcom.com/us/en/symantec-security-software/endpoint-security-and-management/endpoint-security/sescloud/Alerts-and-Events/investigation-page-overview-v134374740-d38e87486/query-and-filter-operators-by-data-type-v134689952-d38e88796.html .INPUTS None .OUTPUTS PSObject containing all SEP incidents .EXAMPLE Get-SEPCloudIncidents -Include_Events .EXAMPLE Get-SEPCloudIncidents -Include_events -Query "state_id: [0 TO 3]" This query a list of every possible incidents (opened, closed and with "Unknown" status) .EXAMPLE $startDate = (Get-Date).AddDays(-7).ToString("yyyy-MM-ddTHH:mm:ss.fffK") Get-SEPCloudIncidents -start_date $startDate Get last 7 days incidents #> #> [CmdletBinding()] param ( # Include events switch [switch] $Include_events, # Custom query to run [string] $Query, # pagination size [string] $limit, # next [string]$next, [string]$start_date, [string]$end_date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffK") ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCloudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.incidents.count) { do { # Update next query param for pagination $next = $result.incidents.count $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.incidents += $nextResult.incidents } until ( ($result.incidents.count -ge $result.total) ) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudIncidents.ps1' 115 #Region '.\Public\Get-SEPCloudPolicesSummary.ps1' -1 function Get-SEPCloudPolicesSummary { <# .SYNOPSIS Provides a list of all SEP Cloud policies .DESCRIPTION Provides a list of all SEP Cloud policies .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER limit The number of records fetched in a given request . [NOTE] The maximum number of records supported per request is 1000 .PARAMETER offset When this field is not present, it returns the first page .PARAMETER name The name of the policy you want to search for .PARAMETER type The type of policy you want to search for .EXAMPLE Get-SEPCloudPolicesSummary Gathers all possible policies in your SEP Cloud account .EXAMPLE Get-SEPCloudPolicesSummary -name "My Exploit Protection Policy" name : My Exploit Protection Policy author : Imported from SEPM policy_uid : abcdef123-abcd-5678-1234-123456789012 policy_version : 1 policy_type : Exploit Protection is_imported : True locked : True created : 28/06/2024 11:33:45 modified : 28/06/2024 11:33:45 Gathers a summary of your specific policy .EXAMPLE Get-SEPCloudPolicesSummary -type "Exploit Protection" Gathers all Exploit Protection policies from your tenant #> [CmdletBinding()] param ( $limit, # Defaults maximum limit is 1000 $offset, $name, $type ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.policies.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination $offset = $result.policies.count $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.policies += $nextResult.policies } until ($result.policies.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudPolicesSummary.ps1' 97 #Region '.\Public\Get-SEPCloudPolicyDetails.ps1' -1 function Get-SepCloudPolicyDetails { <# .SYNOPSIS Gathers detailed information on SEP Cloud policy .DESCRIPTION Gathers detailed information on SEP Cloud policy .PARAMETER policy_uid policy_uid .PARAMETER policyVersion Policy version .OUTPUTS PSObject .EXAMPLE Get-SepCloudPolicyDetails -policy_uid "12677e90-3909-4e8a-9f4a-327242269a13" -version 1 #> [CmdletBinding()] Param( # {param details} [String]$policy_uid, # {param details} [String]$version ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { # adding accept json header otherwise binary stream $script:SEPCloudConnection.header += @{ 'Accept' = 'application/json' } $uri = New-URIString -endpoint ($resources.URI) -id @($policy_uid, $version) $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # Removing "Content-Type: application/json" header $script:SEPCloudConnection.header.remove('Accept') return $result } } #EndRegion '.\Public\Get-SEPCloudPolicyDetails.ps1' 61 #Region '.\Public\Get-SEPCloudTargetRules.ps1' -1 function Get-SEPCloudTargetRules { <# .SYNOPSIS Provides a list of all target rules in your SEP Cloud account .DESCRIPTION Provides a list of all target rules in your SEP Cloud account. Formely known as SEP Location awareness .PARAMETER None .OUTPUTS PSObject .EXAMPLE Get-SEPCloudTargetRules Gathers all possible target rules #> [CmdletBinding()] param ( # Query [Alias('api_page')] $offset ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body # Test if pagination required if ($result.total -gt $result.target_rules.count) { Write-Verbose -Message "Result limits hit. Retrieving remaining data based on pagination" do { # Update offset query param for pagination $offset = $result.target_rules.count $uri = Test-QueryParam -querykeys $resources.query -parameters ((Get-Command $function).Parameters.Values) -uri $uri $nextResult = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result.target_rules += $nextResult.target_rules } until ($result.target_rules.count -ge $result.total) } $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudTargetRules.ps1' 70 #Region '.\Public\Get-SEPCloudThreatIntelCveProtection.ps1' -1 function Get-SEPCloudThreatIntelCveProtection { <# .SYNOPSIS Provide information whether a given CVE has been blocked by any of Symantec technologies .DESCRIPTION Provide information whether a given URL/domain has been blocked by any of Symantec technologies. These technologies include Antivirus (AV), Intrusion Prevention System (IPS) and Behavioral Analysis & System Heuristics (BASH) .PARAMETER cve Specify one or many CVE to check .LINK https://github.com/Douda/PSSymantecCloud .EXAMPLE Get-SepThreatIntelCveProtection -cve CVE-2023-35311 Gathers information whether CVE-2023-35311 has been blocked by any of Symantec technologies .EXAMPLE "CVE-2023-35311","CVE-2023-35312" | Get-SepThreatIntelCveProtection Gathers cve from pipeline by value whether CVE-2023-35311 & CVE-2023-35312 have been blocked by any of Symantec technologies #> [CmdletBinding()] param ( # Mandatory cve [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('vuln', 'vulnerability')] [string[]] $cve ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $cve $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelCveProtection.ps1' 64 #Region '.\Public\Get-SEPCloudThreatIntelFileInsight.ps1' -1 function Get-SEPCloudThreatIntelFileInsight { <# .SYNOPSIS Provide file insight enrichments for a given file .DESCRIPTION Provide file insight enrichments for a given file .INPUTS sha256 .OUTPUTS PSObject .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER file_sha256 Specify one or many sha256 hash .EXAMPLE PS C:\PSSymantecCloud> Get-SepThreatIntelFileInsight -file_sha256 eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d file : eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d reputation : BAD prevalence : Hundreds firstSeen : 2018-04-13 lastSeen : 2023-09-03 targetOrgs : .EXAMPLE "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d" | Get-SepThreatIntelFileInsight #> [CmdletBinding()] param ( # Mandatory file sha256 [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('sha256')] $file_sha256 ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $file_sha256 $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelFileInsight.ps1' 71 #Region '.\Public\Get-SEPCloudThreatIntelFileProcessChain.ps1' -1 function Get-SEPCloudThreatIntelFileProcessChain { <# .SYNOPSIS Provide topK process lineage enrichment for the provided file sha256. .DESCRIPTION Provide topK process lineage enrichment for the provided file sha256. .INPUTS sha256 .LINK https://github.com/Douda/PSSymantecCloud .OUTPUTS PSObject .PARAMETER file_sha256 Specify one or many sha256 hash .EXAMPLE PS C:\PSSymantecCloud> $ProcessChain = Get-SEPCloudThreatIntelFileProcessChain -file_sha256 eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d file chain ---- ----- eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d {@{parent=}} PS C:\PSSymantecCloud> $ProcessChain.chain parent ------ @{parent=; file=18bba9ff311154415404e2fb16f3784e4c82b57ad110092ea5f9b76ed549e7cb; processName=fe392ea0a9f14s4dfeda8d9u0233a6ioq6e47a5n3.exe} .EXAMPLE "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d" | Get-SEPCloudThreatIntelFileProcessChain #> [CmdletBinding()] Param( # Mandatory file sha256 [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('sha256')] $file_sha256 ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $file_sha256 $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelFileProcessChain.ps1' 75 #Region '.\Public\Get-SEPCloudThreatIntelFileProtection.ps1' -1 function Get-SEPCloudThreatIntelFileProtection { <# .SYNOPSIS Provide information whether a given file has been blocked by any of Symantec technologies .DESCRIPTION Provide information whether a given file has been blocked by any of Symantec technologies. These technologies include Antivirus (AV), Intrusion Prevention System (IPS) and Behavioral Analysis & System Heuristics (BASH) .INPUTS sha256 .OUTPUTS PSObject .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER file_sha256 Specify one or many sha256 hash .EXAMPLE Get-SepThreatIntelFileProtection -file_sha256 eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d Gathers information whether the file with sha256 has been blocked by any of Symantec technologies .EXAMPLE "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d","eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8e" | Get-SepThreatIntelFileProtection Gathers sha from pipeline by value whether the files with sha256 have been blocked by any of Symantec technologies #> [CmdletBinding()] Param( # Mandatory file sha256 [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('sha256')] $file_sha256 ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $file_sha256 $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelFileProtection.ps1' 67 #Region '.\Public\Get-SEPCloudThreatIntelFileRelated.ps1' -1 function Get-SEPCloudThreatIntelFileRelated { <# .SYNOPSIS Provide related file for a given file .DESCRIPTION Provide related file for a given file .INPUTS sha256 .OUTPUTS PSObject .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER file_sha256 Specify one or many sha256 hash .EXAMPLE PS C:\PSSymantecCloud> "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d" | Get-SepThreatIntelFileRelated file related ---- ------- eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d {@{iocType=File; iocValues=System.Object[]; relation=byProcessChain}, @{iocType=File; iocValues=System.Object[]; relation=bySignature}} #> [CmdletBinding()] Param( # Mandatory file sha256 [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('sha256')] $file_sha256 ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $file_sha256 $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelFileRelated.ps1' 66 #Region '.\Public\Get-SEPCloudThreatIntelNetworkInsight.ps1' -1 function Get-SEPCloudThreatIntelNetworkInsight { <# .SYNOPSIS Provide domain insight enrichments for a given domain .DESCRIPTION Provide domain insight enrichments for a given domain .INPUTS domain .OUTPUTS PSObject .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER domain Specify one or many domain .EXAMPLE PS C:\PSSymantecCloud> Get-SepThreatIntelNetworkInsight -domain "elblogdeloscachanillas.com.mx/s3sy8rq10/ophn.png" network : elblogdeloscachanillas.com.mx/s3sy8rq10/ophn.png threatRiskLevel : @{level=10} categorization : @{categories=System.Object[]} reputation : BAD targetOrgs : @{topCountries=System.Object[]; topIndustries=System.Object[]} .EXAMPLE "elblogdeloscachanillas.com.mx/s3sy8rq10/ophn.png" | Get-SepThreatIntelNetworkInsight #> [CmdletBinding()] Param( # Mandatory domain [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('URL')] $domain ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $domain $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelNetworkInsight.ps1' 70 #Region '.\Public\Get-SEPCloudThreatIntelNetworkProtection.ps1' -1 function Get-SEPCloudThreatIntelNetworkProtection { <# .SYNOPSIS Provide information whether a given URL/domain has been blocked by any of Symantec technologies .DESCRIPTION Provide information whether a given URL/domain has been blocked by any of Symantec technologies. These technologies include Antivirus (AV), Intrusion Prevention System (IPS) and Behavioral Analysis & System Heuristics (BASH) .PARAMETER domain Specify one or many URL/domain to check .LINK https://github.com/Douda/PSSymantecCloud .OUTPUTS PSObject .EXAMPLE Get-SepThreatIntelNetworkProtection -domain nicolascoolman.eu Gathers information whether the URL/domain has been blocked by any of Symantec technologies .EXAMPLE "nicolascoolman.eu" | Get-SepThreatIntelNetworkProtection Gathers somains from pipeline by value whether the URLs/domains have been blocked by any of Symantec technologies #> [CmdletBinding()] param ( # Mandatory domain name [Parameter( Mandatory, ValueFromPipeline = $true)] [Alias('domain', 'url')] $network ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $network $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) Write-Verbose -Message "Body is $(ConvertTo-Json -InputObject $body)" $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Get-SEPCloudThreatIntelNetworkProtection.ps1' 65 #Region '.\Public\Get-SEPCloudToken.ps1' -1 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 .PARAMETER cacheOnly if set to $true, will only lookup for in-memory or local cache of token/credentials. Will not prompt for credentials or generate a new token. Usefful for automation. .INPUTS [string] clientId [string] secret .OUTPUTS [PSCustomObject] Token .EXAMPLE Get-SEPCloudToken .EXAMPLE Get-SEPCloudToken(clientId,secret) .EXAMPLE Get-SEPCloudToken -clientId "myclientid" -secret "mysecret" .NOTES Function logic - Test if token is already loaded in memory (and verify its validity) - Test locally stored encrypted token (and verify its validity) - Test if credentials is already loaded in memory to generate a token - Test locally stored encrypted Client/secret to generate a token - Requests Client/secret to generate token #> [CmdletBinding(DefaultParameterSetName = 'ClientIdSecret')] param ( # clientId from SEP Cloud Connection App [Parameter( ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ClientIdSecret' )] [string] $clientId, # secret from SEP Cloud Connection App [Parameter( ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ClientIdSecret' )] [string] $secret, # Unattended [switch] [Alias("unattended")] $cacheOnly ) # If -cacheOnly do not attempt to prompt for credentials for unattended mode if ($cacheOnly) { return $null } # Test if clientId and secret are provided to generate a token without testing for locally stored encrypted token/credentials if ($clientId -and $secret) { Write-Verbose -Message "clientId & secret provided - testing to generate a token" $encodedCreds = [convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($clientId + ':' + $secret))) try { $params = @{ Uri = 'https://' + $script:SEPCloudConnection.baseURL + '/v1/oauth2/tokens' Method = 'POST' Headers = @{ Host = $script:SEPCloudConnection.baseURL Accept = "application/json" Authorization = "Basic " + $encodedCreds } useBasicParsing = $true } $Response = Invoke-RestMethod @params if ($null -ne $response) { # Cache the credentials Write-Verbose -Message "credentials valid - caching credentials : $($script:configuration.SEPCloudCredsPath)" $credentialsDirectory = Split-Path -Path $script:configuration.SEPCloudCredsPath -Parent if (-not (Test-Path -Path $credentialsDirectory)) { New-Item -ItemType Directory -Path $credentialsDirectory | Out-Null } $encodedCreds | Export-Clixml -Path $script:configuration.SEPCloudCredsPath $script:SEPCloudConnection.Credential = $encodedCreds # Cache the token Write-Verbose "credentials valid - returning valid Bearer token" $cachedToken = [PSCustomObject]@{ Token = $response.access_token Token_Type = $response.token_type Token_Bearer = $response.token_type.ToString() + " " + $response.access_token Expiration = (Get-Date).AddSeconds($response.expires_in) # token expiration is 3600s } $script:SEPCloudConnection.AccessToken = $cachedToken $tokenDirectory = Split-Path -Path $script:configuration.cachedTokenPath -Parent if (-not (Test-Path -Path $tokenDirectory)) { New-Item -ItemType Directory -Path $tokenDirectory | Out-Null } $cachedToken | Export-Clixml -Path $script:configuration.cachedTokenPath Write-Verbose -Message "stored valid token : $($script:configuration.cachedTokenPath)" return $cachedToken } } catch { $message = "Authentication error - Failed to gather token from locally stored credentials" $message = $message + "`n" + "Expected HTTP 200, got $($_.Exception.Response.StatusCode)" + "`n" $message = $message + "delete cached credentials" $message = $message + "`n" + "Error : $($_.Exception.Response.StatusCode) : $($_.Exception.Response.StatusDescription)" Write-Verbose -Message $message } } # Test if token already in memory if ($null -ne $script:SEPCloudConnection.AccessToken.access_token) { # Check if still valid if (Test-SEPCloudToken) { Write-Verbose -Message "Token in-memory is still valid" return $script:SEPCloudConnection.AccessToken } else { try { Remove-Item -Path $script:configuration.cachedTokenPath -ErrorAction SilentlyContinue } catch {} $script:SEPCloudConnection.AccessToken = $null } } # Test if token present on the disk if (Test-Path -Path $script:configuration.cachedTokenPath) { $cachedToken = Import-Clixml -Path $script:configuration.cachedTokenPath # Check if still valid if (Test-SEPCloudToken -token $cachedToken) { Write-Verbose "Token from disk is still valid" return $cachedToken } else { Write-Verbose -Message "Token from disk expired - deleting" try { Remove-Item -Path $script:configuration.cachedTokenPath -ErrorAction SilentlyContinue } catch {} $script:SEPCloudConnection.AccessToken = $null } } # Test if OAuth cred present in memory if ($script:SEPCloudConnection.Credential) { Write-Verbose -Message "credentials in-memory available - testing" try { $params = @{ Uri = 'https://' + $script:SEPCloudConnection.baseURL + '/v1/oauth2/tokens' Method = 'POST' Headers = @{ Host = $script:SEPCloudConnection.baseURL Accept = "application/json" Authorization = "Basic " + $script:SEPCloudConnection.Credential } } $response = Invoke-RestMethod @params if ($null -ne $response) { # Get the auth token from the response. Store it locally & in memory Write-Verbose -Message "credentials in-memory valid - returning valid token" $cachedToken = [PSCustomObject]@{ Token = $response.access_token Token_Type = $response.token_type Token_Bearer = $response.token_type + " " + $response.access_token Expiration = (Get-Date).AddSeconds($response.expires_in) # token expiration is 3600s } $cachedToken | Export-Clixml -Path $script:configuration.cachedTokenPath $script:SEPCloudConnection.AccessToken = $cachedToken Write-Verbose -Message "stored valid token : $($script:configuration.cachedTokenPath)" return $cachedToken } } catch { $message = "Authentication error - Failed to gather token from locally stored credentials" $message = $message + "`n" + "Expected HTTP 200, got $($_.Exception.Response.StatusCode)" + "`n" $message = $message + "delete cached credentials" $message = $message + "`n" + "Error : $($_.Exception.Response.StatusCode) : $($_.Exception.Response.StatusDescription)" Write-Verbose -Message $message $script:SEPCloudConnection.Credential = $null } } # Test if OAuth cred present on the disk if ((Test-Path -Path $script:configuration.SEPCloudCredsPath)) { Write-Verbose "credentials on disk available - testing" try { $params = @{ Uri = 'https://' + $script:SEPCloudConnection.baseURL + '/v1/oauth2/tokens' Method = 'POST' Headers = @{ Host = $script:SEPCloudConnection.baseURL Accept = "application/json" Authorization = "Basic " + (Import-Clixml -Path $script:configuration.SEPCloudCredsPath) } } $response = Invoke-RestMethod @params if ($null -ne $response) { # Get the auth token from the response. Store it locally & in memory Write-Verbose "credentials valid - returning valid token" $cachedToken = [PSCustomObject]@{ Token = $response.access_token Token_Type = $response.token_type Token_Bearer = $response.token_type + " " + $response.access_token Expiration = (Get-Date).AddSeconds($response.expires_in) # token expiration is 3600s } $cachedToken | Export-Clixml -Path $script:configuration.cachedTokenPath Write-Verbose -Message "stored valid token : $($script:configuration.cachedTokenPath)" $script:SEPCloudConnection.AccessToken = $cachedToken return $cachedToken } } catch { $message = "Authentication error - Failed to gather token from locally stored credentials" $message = $message + "`n" + "Expected HTTP 200, got $($_.Exception.Response.StatusCode)" + "`n" $message = $message + "delete cached credentials" $message = $message + "`n" + "Error : $($_.Exception.Response.StatusCode) : $($_.Exception.Response.StatusDescription)" Write-Verbose -Message $message } } # 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" Write-Verbose -Message "testing authentication with client/secret provided" if ($clientID -eq "" -or $secret -eq "") { Write-Output "No local credentials found. Please provide clientId and secret to generate a token" $clientId = Read-Host -Prompt "Enter clientId" $secret = Read-Host -Prompt "Enter secret" # -MaskInput TODO removed maskedInput. Not working with PS 5.1 } $encodedCreds = [convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($clientId + ':' + $secret))) try { $params = @{ Uri = 'https://' + $script:SEPCloudConnection.baseURL + '/v1/oauth2/tokens' Method = 'POST' Headers = @{ Host = $script:SEPCloudConnection.baseURL Accept = "application/json" Authorization = "Basic " + $encodedCreds } useBasicParsing = $true } $Response = Invoke-RestMethod @params if ($null -ne $response) { # Cache the credentials Write-Verbose -Message "credentials valid. caching credentials : $($script:configuration.SEPCloudCredsPath)" $credentialsDirectory = Split-Path -Path $script:configuration.SEPCloudCredsPath -Parent if (-not (Test-Path -Path $credentialsDirectory)) { New-Item -ItemType Directory -Path $credentialsDirectory | Out-Null } $encodedCreds | Export-Clixml -Path $script:configuration.SEPCloudCredsPath $script:SEPCloudConnection.Credential = $encodedCreds # Cache the token Write-Verbose "credentials valid - returning valid Bearer token" $cachedToken = [PSCustomObject]@{ Token = $response.access_token Token_Type = $response.token_type Token_Bearer = $response.token_type.ToString() + " " + $response.access_token Expiration = (Get-Date).AddSeconds($response.expires_in) # token expiration is 3600s } $script:SEPCloudConnection.AccessToken = $cachedToken $tokenDirectory = Split-Path -Path $script:configuration.cachedTokenPath -Parent if (-not (Test-Path -Path $tokenDirectory)) { New-Item -ItemType Directory -Path $tokenDirectory | Out-Null } $cachedToken | Export-Clixml -Path $script:configuration.cachedTokenPath Write-Verbose -Message "stored valid token : $($script:configuration.cachedTokenPath)" return $cachedToken } } catch { $message = "Authentication error - Failed to gather token from locally stored credentials" $message = $message + "`n" + "Expected HTTP 200, got $($_.Exception.Response.StatusCode)" + "`n" $message = $message + "delete cached credentials" $message = $message + "`n" + "Error : $($_.Exception.Response.StatusCode) : $($_.Exception.Response.StatusDescription)" Write-Verbose -Message $message } } #EndRegion '.\Public\Get-SEPCloudToken.ps1' 294 #Region '.\Public\Get-Something.ps1' -1 function Get-Something { <# .SYNOPSIS Sample Function to return input string. .DESCRIPTION This function is only a sample Advanced function that returns the Data given via parameter Data. .EXAMPLE Get-Something -Data 'Get me this text' .PARAMETER Data The Data parameter is the data that will be returned without transformation. #> [cmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'Low' )] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [String] $Data ) process { if ($pscmdlet.ShouldProcess($Data)) { Write-Verbose ('Returning the data: {0}' -f $Data) Get-PrivateFunction -PrivateData $Data } else { Write-Verbose 'oh dear' } } } #EndRegion '.\Public\Get-Something.ps1' 42 #Region '.\Public\Move-SEPCloudDevice.ps1' -1 function Move-SEPCloudDevice { <# .SYNOPSIS Moves one or many devices to a different group .DESCRIPTION Moves one or many devices to a different group. Requires group ID and device ID. does not support device name or group name. You can use : Get-SEPCloudDevice to get the device ID Get-SEPCloudGroup to get the group ID .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER GroupID The group ID to move the device to .PARAMETER deviceId The device ID to move can be an array of device ID's [NOTE] maximum of 200 devices per call None .EXAMPLE Move-SEPCloudDevice -GroupID "tqrSman3RyqFFd1EqLlZZA" -DeviceID "f3teVmApQlya8XJvEf-wpw" Move-SEPCloudDevice -GroupID "tqrSman3RyqFFd1EqLlZZA" -DeviceID "f3teVmApQlya8XJvEf-wpw" device_uid message status ---------- ------- ------ f3teVmApQlya8XJvEf-wpw Moved successfully MOVED Moves a device to a different group, returns the status of the move. .EXAMPLE $list = @('123', '456', '789') Move-SEPCloudDevice -groupId "I5tExK6hQfC-cnUXk1Siug" -deviceId $list Moves all devices from their identifier (here 123,456,789) to a group from a single API call #> [CmdletBinding()] Param( # Group ID [Parameter( ValueFromPipelineByPropertyName = $true )] $groupId, # Device ID [Parameter( ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true )] [Alias('device_uids')] [ValidateCount(1, 200)] [ValidateNotNullOrEmpty()] [String[]] $deviceId ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $groupId $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Move-SEPCloudDevice.ps1' 86 #Region '.\Public\Remove-SEPCloudPolicy.ps1' -1 function Remove-SEPCloudPolicy { <# .SYNOPSIS Removes a SEP Cloud policy from a device group .DESCRIPTION Removes a SEP Cloud policy from a device group. Must include a specific location (also called policy target rule) .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER policyName Name of the policy to apply .PARAMETER policyVersion Version of the policy to apply. If not provided, the latest version will be used .PARAMETER targetRules Alias: location Location (policy target rule) to apply the policy to If not provided, the default location will be used .PARAMETER deviceGroupId Device group ID to apply the policy to .OUTPUTS None .EXAMPLE Remove-SEPCloudPolicy -policyName "My Policy" -location "Default" -deviceGroupId "123456" Removes the latest version of the SEP Cloud policy named "My Policy" to the device group with ID "123456" at the location "Default" #> [CmdletBinding()] param ( $policyName, [Alias("version")] $policyVersion, [Alias("policy_uid")] $policyId, [Parameter(Mandatory = $true)] [Alias("target_rules")] [Alias("location")] [string[]] $targetRule = "Default", [Parameter(Mandatory = $true)] [Alias("device_group_ids")] [string[]] $deviceGroupId ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { # changing "Content-Type" header specifically for this query, otherwise 415 : unsupported media type # $script:SEPCloudConnection.header += @{ 'Accept' = 'application/json' } if ($policyName -and ($null -eq $policyId)) { Write-Verbose -Message "Searching ID for $policyName" $policyId = (Get-SEPCloudPolicesSummary | Where-Object { $_.name -eq "$policyName" }).policy_uid } if ($null -eq $policyVersion ) { Write-Verbose -Message "No policy version provided, retrieving the latest version of $policyName" # By default the API returns the latest version of a policy $policyVersion = (Get-SEPCloudPolicesSummary | Where-Object { $_.name -eq "$policyName" }).policy_version } $id = @($policyId, $policyVersion) $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # Removing "Content-Type: application/json" header # $script:SEPCloudConnection.header.remove('Content-Type') return $result } } #EndRegion '.\Public\Remove-SEPCloudPolicy.ps1' 98 #Region '.\Public\Set-SEPCloudPolicy.ps1' -1 function Set-SEPCloudPolicy { <# .SYNOPSIS Apply a SEP Cloud policy to a device group .DESCRIPTION Apply a SEP Cloud policy to a device group. Must include a specific location (also called policy target rule) .LINK https://github.com/Douda/PSSymantecCloud .PARAMETER policyName Name of the policy to apply .PARAMETER policyId Id of the policy to apply If not provided, Id will be pulled from the policy name .PARAMETER policyVersion Version of the policy to apply. If not provided, the latest version will be used by default .PARAMETER target_rules Alias: location Location (policy target rule) to apply the policy to. If not provided, the default location will be used .PARAMETER device_group_ids Device group ID to apply the policy to .EXAMPLE Set-SEPCloudPolicy -policyName "My Policy" -location "Default" -deviceGroupID "123456" Apply the latest version of the SEP Cloud policy named "My Policy" to the device group with ID "123456" at the location "Default" .EXAMPLE Set-SEPCloudPolicy -policyName "My Policy" -location "Default" -deviceGroupID "123456" -version 2 Apply the version 2 of the SEP Cloud policy named "My Policy" to the device group with ID 123456 at the location Default #> [CmdletBinding(DefaultParameterSetName = "byName")] Param( [Parameter(ParameterSetName = "byName")] $policyName, [Alias("policy_uid")] $policyId, [Parameter(ParameterSetName = "byId")] [Alias("version")] $policyVersion, [Alias("location")] [Alias("targetRule")] [string[]] $target_rules = "Default", [Alias("deviceGroupId")] [string[]] $device_group_ids, $override = $true ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { if ($policyName -and ($null -eq $policyId)) { Write-Verbose -Message "Searching ID for $policyName" $policyId = (Get-SEPCloudPolicesSummary | Where-Object { $_.name -eq "$policyName" }).policy_uid } if ($null -eq $policyVersion ) { Write-Verbose -Message "No policy version provided, retrieving the latest version of $policyName" # By default the API returns the latest version of a policy $policyVersion = (Get-SEPCloudPolicesSummary | Where-Object { $_.name -eq "$policyName" }).policy_version } $uri = New-URIString -endpoint ($resources.URI) -id @($policyId, $policyVersion) $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Set-SEPCloudPolicy.ps1' 97 #Region '.\Public\Start-SEPCloudDefinitionUpdate.ps1' -1 function Start-SEPCloudDefinitionUpdate { <# .SYNOPSIS Initiate a definition update request command on SEP Cloud managed devices .DESCRIPTION Initiate a definition update request command on SEP Cloud managed devices .PARAMETER device_ids Array of device ids for which to initiate a definition update request .EXAMPLE Start-SepCloudDefinitionUpdate -deviceId "u7IcxqPvQKmH47MPinPsFw" .LINK https://github.com/Douda/PSSymantecCloud #> [CmdletBinding()] Param( [Alias('deviceId')] [string[]] $device_ids, [string[]] [Alias('orgId')] $org_unit_ids, [Alias('recursive')] [switch] $is_recursive ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { # TODO function is not working (500 error response) # changing "Content-Type" header specifically for this query, otherwise 415 : unsupported media type # $script:SEPCloudConnection.header += @{ 'Content-Type' = 'application/json' } $script:SEPCloudConnection.header += @{ 'Accept' = 'application/json' } $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result # Removing "Content-Type: application/json" header $script:SEPCloudConnection.header.remove('Accept') return $result } } #EndRegion '.\Public\Start-SEPCloudDefinitionUpdate.ps1' 68 #Region '.\Public\Start-SEPCloudFullScan.ps1' -1 function Start-SEPCloudFullScan { <# .SYNOPSIS Initiate a full scan command on SEP Cloud managed devices .DESCRIPTION Initiate a full scan command on SEP Cloud managed devices Currently only takes a device_id as parameter device ID can be gathered from Get-SEPCloudDevice .EXAMPLE Start-SEPCloudFullScan -device_ids "u7IcxqPvQKmH47MPinPsFw" #> [CmdletBinding()] Param( [Alias('deviceId')] [string[]] $device_ids, [string[]] [Alias('orgId')] $org_unit_ids, [Alias('recursive')] [switch] $is_recursive ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Start-SEPCloudFullScan.ps1' 57 #Region '.\Public\Start-SEPCloudQuickScan.ps1' -1 function Start-SepCloudQuickScan { <# .SYNOPSIS Initiate a quick scan command on SEP Cloud managed devices .DESCRIPTION Initiate a quick scan command on SEP Cloud managed devices .EXAMPLE Start-SepCloudQuickScan -ComputerName MyComputer Initiate a quick scan command on a specific computer .EXAMPLE Start-SepCloudQuickScan -device_ids "u7IcxqPvQKmH47MPinPsFk" #> [CmdletBinding()] Param( [Alias('deviceId')] [string[]] $device_ids, [string[]] [Alias('orgId')] $org_unit_ids, [Alias('recursive')] [switch] $is_recursive ) begin { # Check to ensure that a session to the SaaS exists and load the needed header data for authentication Test-SEPCloudConnection | Out-Null # API data references the name of the function # For convenience, that name is saved here to $function $function = $MyInvocation.MyCommand.Name # Retrieve all of the URI, method, body, query, result, and success details for the API endpoint Write-Verbose -Message "Gather API Data for $function" $resources = Get-SEPCLoudAPIData -endpoint $function Write-Verbose -Message "Load API data for $($resources.Function)" Write-Verbose -Message "Description: $($resources.Description)" } process { $uri = New-URIString -endpoint ($resources.URI) -id $id $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) $result = Submit-Request -uri $uri -header $script:SEPCloudConnection.header -method $($resources.Method) -body $body $result = Test-ReturnFormat -result $result -location $resources.Result $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result return $result } } #EndRegion '.\Public\Start-SEPCloudQuickScan.ps1' 59 |