PSSymantecCloud.psm1

#Region '.\Private\GetConfigurationPath.ps1' 0
function GetConfigurationPath {
    <#
        .SYNOPSIS
            returns an object with the BaseURL, SepCloudCreds, SepCloudToken full path
    #>


    @{
        BaseUrl       = "api.sep.securitycloud.symantec.com"
        SepCloudCreds = "$env:TEMP\SepCloudOAuthCredentials.xml"
        SepCloudToken = "$env:TEMP\SepCloudToken.xml"
    }

}
#EndRegion '.\Private\GetConfigurationPath.ps1' 14
#Region '.\Public\Export-SepCloudPolicyToExcel.ps1' 0
function Export-SepCloudPolicyToExcel {
    <# TODO fill description
    .SYNOPSIS
        Export an Allow List policy object to excel
    .DESCRIPTION
        Takes an allow list policy object as input and exports it to an Excel file, with one tab per allow type (filename/file hash/directory etc...)
    .EXAMPLE
        Get-SepCloudPolicyDetails -Policy_UUID "5e867f84-5e23-421c-adfd-XXXXXXXXXXXX" -Policy_version 5 | Export-SepCloudPolicyToExcel -Path "allow_list.xlsx"
        Gathers policy in an object, pipes the output to Export-SepCloudPolicyToExcel
    #>


    param (
        # Path of Export
        [Parameter()]
        [string]
        $Path,

        # Policy Obj to work with
        [Parameter(
            ValueFromPipeline,
            Mandatory
        )]
        [pscustomobject]
        $obj_policy
    )
    <#
    Using as a template the following command
    $allow_list | ConvertTo-Json -Depth 100 | Out-File -FilePath "C:\Users\Douda\Documents\Amcor\Servers - Amcor Core Allow List Policy_v69.json"
    Get-SepCloudPolicyDetails -Policy_UUID "5e867f84-5e23-421c-adfd-503511811b51" -Policy_version 69 | Convert-SepCloudPolicyToExcel -Path "C:\Amcor_local\test5.xlsx"
    Parsing the custom object to get the list of
    $obj_policy.features.configuration.applications
    $obj_policy.features.configuration.applications.processfile
    $obj_policy.features.configuration.applications.processfile.name
    $obj_policy.features.configuration.applications.processfile.sha2
    $obj_policy.features.configuration.certificates
    $obj_policy.features.configuration.webdomains
    $obj_policy.features.configuration.ips_hosts
    $obj_policy.features.configuration.extensions
    $obj_policy.features.configuration.extensions.names
    $obj_policy.features.configuration.windows.files
    $obj_policy.features.configuration.windows.directories
    #>

    $Applications = $obj_policy.features.configuration.applications.processfile
    $Certificates = $obj_policy.features.configuration.certificates
    $Webdomains = $obj_policy.features.configuration.webdomains
    $Ips_Hosts = $obj_policy.features.configuration.ips_hosts
    $Extensions = $obj_policy.features.configuration.extensions.names
    $Files = $obj_policy.features.configuration.windows.files
    $Directories = $obj_policy.features.configuration.windows.directories

    Import-Module -Name ImportExcel
    $Applications | Export-Excel $Path -WorksheetName "Applications" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Certificates | Export-Excel $Path -WorksheetName "Certificates" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Webdomains | Export-Excel $Path -WorksheetName "Webdomains" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Ips_Hosts | Export-Excel $Path -WorksheetName "Ips_Hosts" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Extensions | Export-Excel $Path -WorksheetName "Extensions" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Files | Export-Excel $Path -WorksheetName "Files" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
    $Directories | Export-Excel $Path -WorksheetName "Directories" -ClearSheet -BoldTopRow -AutoSize -FreezeTopRow -AutoFilter
}
#EndRegion '.\Public\Export-SepCloudPolicyToExcel.ps1' 60
#Region '.\Public\Get-SepCloudDeviceInfo.ps1' 0
function Get-SepCloudDeviceInfo {
    param (
        # Mandatory device_ID parameter
        [Parameter(mandatory)]
        [string]
        $Device_ID
    )

    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/devices/$Device_ID"
    # Get token
    $Token = Get-SEPCloudToken  

    if ($null -ne $Token) {
        # HTTP body content containing all the queries
        $Body = @{}
        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $Token
            Body          = $Body
        }
        $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing 
        return $Response
    }
}
#EndRegion '.\Public\Get-SepCloudDeviceInfo.ps1' 28
#Region '.\Public\Get-SepCloudDeviceList.ps1' 0
function Get-SepCloudDeviceList {
    <# TODO fill up description
    .SYNOPSIS
        Gathers list of devices from the SEP Cloud console
    .DESCRIPTION
        A longer description of the function, its purpose, common use cases, etc.
 
    .PARAMETER Computername
    Specify one or many computer names. Accepts pipeline (up to 10 devices per query)
    Supports partial match
 
    .PARAMETER is_online
    Switch to lookup only online machines
 
    .PARAMETER Device_status
    Lookup devices per security status. Accepts only "SECURE", "AT_RISK", "COMPROMISED", "NOT_COMPUTED"
 
    .EXAMPLE
    Get-SepCloudDeviceList
 
    .EXAMPLE
    Get-SepCloudDeviceList -Computername MyComputer
     
    .EXAMPLE
    Get-SepCloudDeviceList -is_online -Device_status AT_RISK
        #>


    [CmdletBinding()]
    param (
        <# Optional ComputerName parameter
        TODO work to allow multiple values from Computername
        More info https://apidocs.securitycloud.symantec.com/#
        name query name of the device. [NOTE] Provide comma seperated values in case of multiple name search
        Note : seems to be limited to 10 values max
        #>

        [Parameter(
            ValueFromPipeline = $true
        )]
        [string]
        $Computername,

        # Optional Is_Online parameter
        [Parameter()]
        [Alias("Online")]
        [switch]
        $is_online,

        # Optional include_details parameter
        [Parameter()]
        [Alias("Details")]
        [switch]
        $include_details,

        # Device Group
        [Parameter()]
        [Alias("Group")]
        [string]
        $Device_group,

        # Optional Device_Status parameter
        [Parameter()]
        [Alias("DeviceStatus")]
        [ValidateSet("SECURE", "AT_RISK", "COMPROMISED", "NOT_COMPUTED")]
        $Device_status
    )
        
    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/devices"
    # Get token
    $Token = Get-SEPCloudToken  
        
    if ($null -ne $Token ) {
        # HTTP body content containing all the queries
        $Body = @{}
        
        # Iterating through all parameter and add them to the HTTP body
        if ($Computername -ne "") {
            $Body.Add("name", "$Computername") 
        }
        if ($is_online -eq $true ) {
            $body.add("is_online", "true")
        }
        if ($include_details -eq $true) {
            $Body.Add("include_details", "true")
        }
        if ($Device_status -ne "") {
            $Body.Add("device_status", "$Device_status")
        }
        if ($Device_group -ne "") {
            $Body.Add("device_group", "$Device_group")
        }

        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $Token
            Body          = $Body
        }

        try {
            $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing 
            return $Response
        } catch {
            $StatusCode = $_.Exception.Response.StatusCode
            Write-Warning "Query error - Expected HTTP 200, got $([int]$StatusCode)"
        }
    }
}
#EndRegion '.\Public\Get-SepCloudDeviceList.ps1' 110
#Region '.\Public\Get-SepCloudEvents.ps1' 0
function Get-SepCloudEvents {
    param (
        # file Detection
        [Parameter()]
        [switch]
        $FileDetection,

        # Custom query to run
        [Parameter()]
        [string]
        $Query,

        # Query date range Past 30 days
        [Parameter()]
        [switch]
        $Past_30_Days,

        # Query date range Past 7 days
        [Parameter()]
        [switch]
        $Past_7_Days
    )
    
    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/event-search"

    # Get token
    $Token = Get-SEPCloudToken

    if ($null -ne $Token) {
        # HTTP body content containing all the queries
        $Body = @{
            "product"      = "SAEP"
            "feature_name" = "ALL"
        }
        <#
        Setting dates for the query
        Date Format required : -UFormat "%Y-%m-%dT%T.000+00:00"
        Example :
        "start_date": "2022-10-16T00:00:00.000+00:00",
        "end_date": "2022-11-16T00:00:00.000+00:00"
        Set correct date formats to query the past 30 days
        End date = today
        Start date = X days ago (30 days maximum)
        #>

        $obj_end_date = Get-Date -AsUTC
        if ($past_30_Days -eq $true) {
            $obj_start_date = $obj_end_date.AddDays(-30)
        }
        if ($past_7_Days -eq $true) {
            $obj_start_date = $obj_end_date.AddDays(-7)
        }
        $end_date = Get-Date $obj_end_date -UFormat "%Y-%m-%dT%T.000+00:00"
        $start_date = Get-Date $obj_start_date -UFormat "%Y-%m-%dT%T.000+00:00"
        $Body.Add("start_date", $start_date)
        $Body.Add("end_date", $end_date)

        # Iterating through all parameter and adding them to the HTTP body
        if ($FileDetection -eq $true) {
            # Testing hardcoded query (file detection)
            $Body.Add("query", '( feature_name:MALWARE_PROTECTION AND ( type_id:8031 OR type_id:8032 OR type_id:8033 OR type_id:8027 OR type_id:8028 ) AND ( id:12 OR id:11 AND type_id:8031 ) )')
        }

        if ($Query -ne "") {
            $Body.Add("query", "$Query")
        }


        $Body_Json = ConvertTo-Json $Body

        $Headers = @{
            Host           = $BaseURL
            Accept         = "application/json"
            "Content-Type" = "application/json"
            Authorization  = $Token
        }

        try {
            $Response = Invoke-RestMethod -Method POST -FollowRelLink -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing 
            return $Response
        } catch {
            $StatusCode = $_.Exception.Response.StatusCode
            $StatusCode
        }
    }
}
#EndRegion '.\Public\Get-SepCloudEvents.ps1' 88
#Region '.\Public\Get-SepCloudFeatureList.ps1' 0
function Get-SepCloudFeatureList {
    <# TODO : fill in description Get-SepCloudFeatureList
    .SYNOPSIS
        A short one-line action-based description, e.g. 'Tests if a function is valid'
    .DESCRIPTION
        A longer description of the function, its purpose, common use cases, etc.
    .NOTES
        Information or caveats about the function e.g. 'This function is not supported in Linux'
    .LINK
        Specify a URI to a help page, this will show when Get-Help -Online is used.
    .EXAMPLE
        Test-MyTestFunction -Verbose
        Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
    #>

    
    param (
    )
    
    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/devices/enums"
    # Get token
    $Token = Get-SEPCloudToken  

    if ($null -ne $Token) {
        # HTTP body content containing all the queries
        $Body = @{}
        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $Token
            Body          = $Body
        }
        $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing 
        return $Response
    }
}
#EndRegion '.\Public\Get-SepCloudFeatureList.ps1' 38
#Region '.\Public\Get-SepCloudIncidents.ps1' 0
function Get-SepCloudIncidents {

    <# TODO fill description for Get-SepCloudIncidents
    .SYNOPSIS
        A short one-line action-based description, e.g. 'Tests if a function is valid'
    .DESCRIPTION
        A longer description of the function, its purpose, common use cases, etc.
    .NOTES
        Information or caveats about the function e.g. 'This function is not supported in Linux'
    .LINK
        Specify a URI to a help page, this will show when Get-Help -Online is used.
    .EXAMPLE
        Test-MyTestFunction -Verbose
        Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
    #>



    param (
        # Opened incidents
        [Parameter()]
        [switch]
        $Open,

        # Include events
        [Parameter()]
        [switch]
        $Include_events,

        # Custom query to run
        [Parameter()]
        [string]
        $Query,

        # Max limit of Incidents per query. Max 2000
        [Parameter()]
        [ValidateRange(1, 2000)]
        [int]
        $limit,

        # Query date range Past 30 days
        [Parameter()]
        [switch]
        $Past_30_Days,

        # Query date range Past 7 days
        [Parameter()]
        [switch]
        $Past_7_Days
    )

    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/incidents"

    # Get token
    $Token = Get-SEPCloudToken

    if ($null -ne $Token) {
        # HTTP body content containing all the queries
        $Body = @{}

        # Setting dates format
        $obj_end_date = Get-Date -AsUTC
        if ($past_30_Days -eq $true) {
            $obj_start_date = $obj_end_date.AddDays(-30)
        }
        if ($past_7_Days -eq $true) {
            $obj_start_date = $obj_end_date.AddDays(-7)
        }
        $end_date = Get-Date $obj_end_date -UFormat "%Y-%m-%dT%T.000+00:00"
        $start_date = Get-Date $obj_start_date -UFormat "%Y-%m-%dT%T.000+00:00"
        $Body.Add("start_date", $start_date)
        $Body.Add("end_date", $end_date)


        # Iterating through all parameter and adding them to the HTTP body
        if ($Query -ne "") {
            $Body.Add("query", "$Query")
        }
        if ($limit -ne $null) {
            $Body.Add("limit", $limit)
        }
        if ($open -eq $true) {
            $Body.Add("status", "open")
        }
        if ($Include_events -eq $true ) {
            $Body.Add("include_events", "true")
        }
        $Body_Json = ConvertTo-Json $Body

        $Headers = @{
            Host           = $BaseURL
            Accept         = "application/json"
            "Content-Type" = "application/json"
            Authorization  = $Token
        }

        try {
            $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -Body $Body_Json -UseBasicParsing
            return $Response
        } catch {
            $StatusCode = $_.Exception.Response.StatusCode
            $StatusCode
        }

    }
}
#EndRegion '.\Public\Get-SepCloudIncidents.ps1' 108
#Region '.\Public\Get-SepCloudPolices.ps1' 0
function Get-SepCloudPolices {
    # TODO to finish; test cmd-let
    param (   
        # Policy UUID
        [Parameter()]
        [string]
        $Policy_UUID
    
    )

    # Init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $URI_Tokens = 'https://' + $BaseURL + "/v1/policies"
    # Get token
    $Token = Get-SEPCloudToken  

    if ($null -ne $Token) {
        # HTTP body content containing all the queries
        $Body = @{}
        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $Token
            Body          = $Body
        }
        $Response = Invoke-RestMethod -Method GET -Uri $URI_Tokens -Headers $Headers -Body $Body -UseBasicParsing 
        return $Response
    }
    
}
#EndRegion '.\Public\Get-SepCloudPolices.ps1' 31
#Region '.\Public\Get-SepCloudPolicyDetails.ps1' 0
function Get-SepCloudPolicyDetails {
    
    <# TODO finish Get-SepCloudPolicyDetails description
    .SYNOPSIS
        A short one-line action-based description, e.g. 'Tests if a function is valid'
    .DESCRIPTION
        A longer description of the function, its purpose, common use cases, etc.
    .NOTES
        Information or caveats about the function e.g. 'This function is not supported in Linux'
    .LINK
        Specify a URI to a help page, this will show when Get-Help -Online is used.
    .EXAMPLE
        Test-MyTestFunction -Verbose
        Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
    #>

    
    
    param (   
        # Policy UUID
        [Parameter()]
        [string]
        $Policy_UUID,

        # Policy version
        [Parameter()]
        [string]
        $Policy_Version,

        # Exact policy name
        [Parameter(
            ValueFromPipeline,
            Mandatory
        )]
        [string[]]
        [Alias("Name")]
        $Policy_Name
    )

    begin {
        # Init
        $array_resp = @()
    }

    process {
        # iterating through policy_name list if more than one obj
        foreach ($p in $Policy_Name) {
            # Get list of all SEP Cloud policies
            $obj_policies = (Get-SepCloudPolices).policies 
            $obj_policy = ($obj_policies | Where-Object { $_.name -eq "$p" })

            # Use specific version or by default latest
            if ($Policy_version -ne "") {
                $obj_policy = $obj_policy | Where-Object {
                    $_.name -eq "$p" -and $_.policy_version -eq $Policy_Version
                }
            } else {
                $obj_policy = ($obj_policy | Sort-Object -Property policy_version -Descending | Select-Object -First 1)
            }

            $Policy_UUID = ($obj_policy).policy_uid
            $Policy_Version = ($obj_policy).policy_version
            $BaseURL = (GetConfigurationPath).BaseUrl
            $URI = 'https://' + $BaseURL + "/v1/policies/$Policy_UUID/versions/$Policy_Version"
            # Get token
            $Token = Get-SEPCloudToken  

            if ($null -ne $Token) {
                $Body = @{}
                $Headers = @{
                    Host          = $BaseURL
                    Accept        = "application/json"
                    Authorization = $Token
                    Body          = $Body
                }
                $Resp = Invoke-RestMethod -Method GET -Uri $URI -Headers $Headers -Body $Body -UseBasicParsing 
                $array_resp += $Resp
            }
        }
    }

    end {
        return $array_resp
    }
}
#EndRegion '.\Public\Get-SepCloudPolicyDetails.ps1' 85
#Region '.\Public\Get-SEPCloudToken.ps1' 0
function Get-SEPCloudToken {
    <#
    .SYNOPSIS
    Generates an authenticated Token from the SEP Cloud API
 
    .DESCRIPTION
    Gathers Bearer Token from the SEP Cloud console to interact with the authenticated API
    Securely stores credentials or valid token locally (By default on TEMP location)
    Connection information available here : https://sep.securitycloud.symantec.com/v2/integration/client-applications
 
    .PARAMETER ClientID
    ClientID parameter required to generate a token
 
    .PARAMETER Secret
    Secret parameter required in combinaison to ClientID to generate a token
 
    .EXAMPLE
    Get-SEPCloudToken
 
    .EXAMPLE
    Get-SEPCloudToken(ClientID,Secret)
 
    .NOTES
    Function logic
    1. Test locally stored encrypted token
    2. Test locally stored encrypted Client/Secret to generate a token
    3. Requests Client/Secret to generate token
    #>


    [CmdletBinding()]
    param (
        # ClientID from SEP Cloud Connection App
        [Parameter()]
        [string]
        $ClientID,

        # Secret from SEP Cloud Connection App
        [Parameter()]
        [string]
        $Secret
    )

    # init
    $BaseURL = (GetConfigurationPath).BaseUrl
    $SepCloudCreds = (GetConfigurationPath).SepCloudCreds
    $SepCloudToken = (GetConfigurationPath).SepCloudToken
    $URI_Tokens = 'https://' + $BaseURL + '/v1/oauth2/tokens'
    $URI_Features = 'https://' + $BaseURL + '/v1/devices/enums'

    # Test if we have a token locally stored
    if (Test-Path -Path $SepCloudToken) {
        <# If true, test it against the API #>
        $Token = Import-Clixml -Path $SepCloudToken
        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $Token
        }

        try {
            $response = Invoke-RestMethod -Method POST -Uri $URI_Features -Headers $Headers
            # Valid token, returning it
            Write-Verbose "Local token - valid"
            return $Token
        } catch {
            $StatusCode = $_.Exception.Response.StatusCode
            Write-Verbose "Authentication error - From locally stored token - Expected HTTP 200, got $([int]$StatusCode) - Continue ..."
            # Invalid token, deleting local token file
            Remove-Item $SepCloudToken
        }
    }

    # Test if OAuth cred present on the disk
    if (Test-Path -Path "$SepCloudCreds") {
        <# If true, Attempt to get a token #>
        $OAuth = Import-Clixml -Path $SepCloudCreds
        $OAuth_Basic = "Basic " + $OAuth
        $Headers = @{
            Host          = $BaseURL
            Accept        = "application/json"
            Authorization = $OAuth_Basic
        }

        try {
            $response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers

            # Get the auth token from the response & store it locally
            Write-Verbose "Valid credentials - returning valid token"
            $null = $Bearer_Token = "Bearer " + $response.access_token
            $Bearer_Token | Export-Clixml -Path $SepCloudToken
            return $Bearer_Token

        } catch {
            $StatusCode = $_.Exception.Response.StatusCode
            Write-Verbose "Authentication error - From locally stored credentials - Expected HTTP 200, got $([int]$StatusCode) - Continue..."
            # Invalid Credentials, deleting local credentials file
            Remove-Item $SepCloudCreds
        }
    }


    <# If no token nor OAuth creds available locally
    # Encode ClientID and Secret to create Basic Auth string
    # Authentication requires the following "Basic + encoded CliendID:ClientSecret" #>

    if ($clientID -eq "" -or $Secret -eq "") {
        Write-Host "No local credentials found"
        $ClientID = Read-Host -Prompt "Enter ClientID"
        $Secret = Read-Host -Prompt "Enter Secret"
    }
    $Encoded_Creds = [convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($ClientID + ':' + $Secret)))
    $Encoded_Creds | Export-Clixml -Path $SepCloudCreds

    # Create Basic Auth string
    $BasicAuth = "Basic " + $Encoded_Creds
    $Headers = @{
        Host          = $BaseURL
        Accept        = "application/json"
        Authorization = $BasicAuth
    }
    $Response = Invoke-RestMethod -Method POST -Uri $URI_Tokens -Headers $Headers -UseBasicParsing

    # Get the auth token from the response and store it
    $Bearer_Token = "Bearer " + $Response.access_token
    $Bearer_Token | Export-Clixml -Path $SepCloudToken
    return $Bearer_Token
}
#EndRegion '.\Public\Get-SEPCloudToken.ps1' 127
#Region '.\Public\Test-SepCloudConnectivity.ps1' 0
function Test-SepCloudConnectivity {
    param (

    )
    if (Get-SEPCloudToken) {
        Write-Host "Authentication OK"
        return $true
        else {
            Write-Host "Authentication failed"
            return false
        }
    }
}
#EndRegion '.\Public\Test-SepCloudConnectivity.ps1' 14