Skyhigh Secure Web Gateway (On Prem)

Manages the block and allow lists within Skyhigh Secure Web Gateway.

Network Security · McAfee Web Gateway

Details

IDSkyhigh Secure Web Gateway (On Prem)
ProviderSkyhigh Security
CategoryNetwork Security
From Version6.8.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Manages the block and allow lists within Skyhigh Secure Web Gateway.
This integration was integrated and tested with version 11.2.9 of Skyhigh Secure Web Gateway (On Prem)

Configure Skyhigh Secure Web Gateway (On Prem) in Cortex

Parameter Required
Server URL (e.g. https://192.168.100.55:4712) True
Password True
Trust any certificate (not secure) False
Use system proxy settings False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

swg-get-available-lists


Get all available lists.

Base Command

swg-get-available-lists

Input

Argument Name Description Required
name Filter to be applied on a list name. Optional
type Filter to be applied on a list type. Optional

Context Output

Path Type Description
SWG.List.ID Unknown List ID.
SWG.List.Title Unknown List title.
SWG.List.Type Unknown List type.

Command example

!swg-get-available-lists name=blocklist

Context Example

{
    "SWG": {
        "List": {
            "ID": "com.scur.type.regex.386",
            "Title": "blocklist",
            "Type": "regex"
        }
    }
}

Human Readable Output

Lists

Title ID Type
blocklist com.scur.type.regex.386 regex
Category Blocklist 5145 category
Upload Media Type Blocklist 5146 mediatype

swg-get-list


Retrieve a specific list.

Base Command

swg-get-list

Input

Argument Name Description Required
list_id List ID. Required

Context Output

Path Type Description
SWG.List.ListEntries.ListID Unknown List ID of the entry’s list.
SWG.List.ListEntries.Name Unknown Entry name.
SWG.List.ListEntries.Description Unknown Entry description.
SWG.List.ListEntries.Position Unknown Entry position in list.
SWG.List.ID Unknown List ID.
SWG.List.Title Unknown List title.
SWG.List.Type Unknown List Type
SWG.List.Description Unknown List description.

Command example

!swg-get-list list_id=com.scur.type.regex.386

Context Example

{
    "SWG": {
        "List": {
            "Description": "blocklist",
            "ID": "com.scur.type.regex.386",
            "Title": "blocklist",
            "Type": "regex",
            "ListEntries": [
                {
                    "Description": "this is really evil",
                    "ListID": "com.scur.type.regex.386",
                    "Name": "http*://test.evil/*",
                    "Position": 0
                },
                {
                    "Description": "this is really evil",
                    "ListID": "com.scur.type.regex.386",
                    "Name": "http*://test-more.evil/*",
                    "Position": 1
                }
            ]
        }
    }
}

Human Readable Output

List Properties

Title ID Description Type
blocklist com.scur.type.regex.386 blocklist regex

blocklist

Position Name Description
0 http://test.evil/ this is really evil
1 http://test-more.evil/ this is really evil

swg-get-list-entry


Retrieve a specific entry from a list.

Base Command

swg-get-list-entry

Input

Argument Name Description Required
list_id List ID. Required
entry_pos Entry position in the table. Required

Context Output

Path Type Description
SWG.List.ID Unknown List ID of the entry’s list.
SWG.List.ListEntries.ListID Unknown List ID of the entry’s list.
SWG.List.ListEntries.Name Unknown Entry name.
SWG.List.ListEntries.Position Unknown Entry position in the list.
SWG.List.ListEntries.Description Unknown Entry description.

Command example

!swg-get-list-entry list_id=com.scur.type.regex.386 entry_pos=0

Context Example

{
    "SWG": {
        "List": {
            "ID": "com.scur.type.regex.386",
            "ListEntries": {
                "Description": "this is really evil",
                "ListID": "com.scur.type.regex.386",
                "Name": "http*://test.evil/*",
                "Position": "0"
            }
        }
    }
}

Human Readable Output

List entry at position 0

ListID Position Name Description
com.scur.type.regex.386 0 http://test.evil/ this is really evil

swg-insert-entry


Insert a new entry to a list.

Base Command

swg-insert-entry

Input

Argument Name Description Required
list_id List ID. Required
entry_pos Entry position in the table. Required
description Entry description. Optional
name Entry name. Required

Context Output

Path Type Description
SWG.List.ID Unknown List ID of the entry’s list.
SWG.List.ListEntries.ListID Unknown List ID of the entry’s list.
SWG.List.ListEntries.Name Unknown Entry name.
SWG.List.ListEntries.Position Unknown Entry position in the list.
SWG.List.ListEntries.Description Unknown Entry description.

Command example

!swg-insert-entry list_id=com.scur.type.regex.386 entry_pos=0 name="http*://evil.corp/*" description="ticket #1: This is an evil domain"

Context Example

{
    "SWG": {
        "List": {
            "ID": "com.scur.type.regex.386",
            "ListEntries": {
                "Description": "ticket #1: This is an evil domain",
                "ListID": "com.scur.type.regex.386",
                "Name": "http*://evil.corp/*",
                "Position": "0"
            }
        }
    }
}

Human Readable Output

Added List entry at position 0

ListID Position Name Description
com.scur.type.regex.386 0 http://evil.corp/ ticket #1: This is an evil domain

swg-delete-entry


Insert a new entry to a list.

Base Command

swg-delete-entry

Input

Argument Name Description Required
list_id List ID. Required
entry_pos Entry position in the table. Required

Context Output

There is no context output for this command.

Command example

!swg-delete-entry list_id=com.scur.type.regex.386 entry_pos=0

Human Readable Output

Deleted List entry at position 0

ListID Position Name Description
com.scur.type.regex.386 0 http://evil.corp ticket #1: This is an evil domain

swg-modify-list


Overwrites the complete XML configuration of a list.

Base Command

swg-modify-list

Input

Argument Name Description Required
list_id List ID. Required
config XML configuration to write to the list. Required

Context Output

Path Type Description
SWG.List.ListEntries.ListID Unknown List ID of the entry’s list.
SWG.List.ListEntries.Name Unknown Entry name.
SWG.List.ListEntries.Description Unknown Entry description.
SWG.List.ListEntries.Position Unknown Entry position in list.
SWG.List.ID Unknown List ID.
SWG.List.Title Unknown List title.
SWG.List.Type Unknown List type.
SWG.List.Description Unknown List description.

Command example

!swg-modify-list list_id=com.scur.type.regex.386 config=`<list version="1.0.3.46" mwg-version="11.2.9-44482" name="blocklist" id="com.scur.type.regex.386" typeId="com.scur.type.regex" classifier="Other" systemList="false" structuralList="false" defaultRights="2"><description>blocklist</description><content><listEntry><entry>http*://evil.corp/*</entry><description>ticket #1: This is an evil domain</description></listEntry></content></list>`

Context Example

{
    "SWG": {
        "List": {
            "Description": "blocklist",
            "ID": "com.scur.type.regex.386",
            "Title": "blocklist",
            "Type": "regex",
            "ListEntries": [
                {
                    "Description": "ticket #1: This is an evil domain",
                    "ListID": "com.scur.type.regex.386",
                    "Name": "http*://evil.corp/*",
                    "Position": 0
                }
            ]
        }
    }
}

Human Readable Output

Modified blocklist

Title ID Description Type
blocklist com.scur.type.regex.386 blocklist regex

swg-create-list


Create a new list.

Base Command

swg-create-list

Input

Argument Name Description Required
name Name for the list to be created. Required
type Type for the list to be created. Possible values are: category, ip, iprange, mediatype, number, regex, string. Default is string. Required

Context Output

Path Type Description
SWG.List.ID Unknown List ID.
SWG.List.Title Unknown List title.
SWG.List.Type Unknown List type.
SWG.List.Description Unknown List description.

Command example

!swg-create-list name="blocklist" type=regex

Context Example

{
    "SWG": {
        "List": {
            "Description": "",
            "ID": "com.scur.type.regex.460",
            "Title": "blocklist",
            "Type": "regex"
        }
    }
}

Human Readable Output

Created List Properties

Title ID Description Type
blocklist com.scur.type.regex.460   regex

swg-delete-list


Delete a list.

Base Command

swg-delete-list

Input

Argument Name Description Required
list_id List ID. Required

Context Output

There is no context output for this command.

Command example

!swg-delete-list list_id=com.scur.type.regex.460

Human Readable Output

Deleted List Properties

Title ID Description Type
blocklist com.scur.type.regex.460   regex

Configuration parameters

  • url — Server URL (e.g., https://192.168.100.55:4712) (required)
  • credentials — Username (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (8)

  • swg-create-list

    Create a new list.

  • swg-delete-entry

    Delete entry to from a list.

  • swg-delete-list

    Delete a list.

  • swg-get-available-lists

    Get all available lists.

  • swg-get-list

    Retrieve a specific list.

  • swg-get-list-entry

    Retrieve a specific entry from a list.

  • swg-insert-entry

    Insert a new entry to a list.

  • swg-modify-list

    Overwrites the complete XML configuration of a list.

import json

import demistomock as demisto
from SkyhighSecureWebGatewayOnPrem import Client

client = Client(
    username="user",
    password="password",
    base_url="base_url",
    verify=False,
    headers={"Content-Type": "application/mwg+xml"},
    proxy=False,
)


def util_load_file(path):
    with open(path, encoding="utf-8") as f:
        return f.read()


def test_get_lists_command(mocker):
    """
    Given
    - valid arguments for get lists command

    When
    - running get_lists_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import get_lists_command

    args = {"name": "blocklist"}
    raw_response = util_load_file("test_data/get_lists/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/get_lists/parsed_result.json"))

    mocker.patch.object(client, "get_lists", return_value=raw_response)
    command_result = get_lists_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_get_list(mocker):
    """
    Given
    - valid arguments for get list command

    When
    - running get_list_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import get_list_command

    args = {"list_id": "com.scur.type.regex.386"}
    raw_response = util_load_file("test_data/get_list/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/get_list/parsed_result.json"))

    mocker.patch.object(client, "get_list", return_value=raw_response)
    command_result = get_list_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_get_list_entry(mocker):
    """
    Given
    - valid arguments for get list entry command

    When
    - running get_list_entry_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import get_list_entry_command

    args = {"list_id": "com.scur.type.regex.386", "entry_pos": "0"}
    raw_response = util_load_file("test_data/get_list_entry/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/get_list_entry/parsed_result.json"))

    mocker.patch.object(client, "get_list_entry", return_value=raw_response)
    command_result = get_list_entry_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_insert_entry(mocker):
    """
    Given
    - valid arguments for insert entry command

    When
    - running insert_entry_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import insert_entry_command

    args = {
        "list_id": "com.scur.type.regex.386",
        "entry_pos": "0",
        "name": "http*://evil.corp/*",
        "description": "ticket #1: This is an evil domain",
    }
    raw_response = util_load_file("test_data/insert_entry/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/insert_entry/parsed_result.json"))

    mocker.patch.object(client, "insert_entry", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    command_result = insert_entry_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_delete_entry(mocker):
    """
    Given
    - valid arguments for delete entry command

    When
    - running delete_entry_command in XSOAR

    Then
    - the expected human readable is returned
    """
    from SkyhighSecureWebGatewayOnPrem import delete_entry_command

    args = {"list_id": "com.scur.type.regex.386", "entry_pos": "0"}
    raw_response = util_load_file("test_data/delete_entry/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/delete_entry/parsed_result.json"))

    mocker.patch.object(client, "delete_entry", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    command_result = delete_entry_command(client, args)

    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_modify_list(mocker):
    """
    Given
    - valid arguments for modify list command

    When
    - running modify_list_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import modify_list_command

    args = {
        "list_id": "com.scur.type.regex.386",
        "config": "<list><description>blocklist</description><content><listEntry><entry>http*://evil.corp/*</entry>"
        + "<description>ticket #1: This is an evil domain</description></listEntry></content></list>",
    }
    raw_response = util_load_file("test_data/modify_list/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/modify_list/parsed_result.json"))

    mocker.patch.object(client, "put_list", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    command_result = modify_list_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_create_list(mocker):
    """
    Given
    - valid arguments for create list command

    When
    - running create_list_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import create_list_command

    args = {"name": "blocklist", "type": "regex"}
    raw_response = util_load_file("test_data/create_list/raw_response.xml")
    expected_results = json.loads(util_load_file("test_data/create_list/parsed_result.json"))

    mocker.patch.object(client, "create_list", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    command_result = create_list_command(client, args)

    assert expected_results["EntryContext"] == command_result.to_context().get("EntryContext")
    assert expected_results["HumanReadable"] == command_result.to_context().get("HumanReadable")


def test_delete_list(mocker):
    """
    Given
    - valid arguments for delete list command

    When
    - running delete_list_command in XSOAR

    Then
    - the expected human readable and entry context are returned
    """
    from SkyhighSecureWebGatewayOnPrem import delete_list_command

    args = {"list_id": "com.scur.type.regex.460"}
    raw_response = util_load_file("test_data/delete_list/raw_response.xml")
    json.loads(util_load_file("test_data/delete_list/parsed_result.json"))

    mocker.patch.object(client, "delete_list", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    delete_list_command(client, args)


def test_insert_entry_command_new_list(mocker):
    """
    Given
    - valid arguments for insert entry command
    - list does not exist in context data

    When
    - running insert_entry_command function

    Then
    - the expected entry context is returned with new list format
    """
    from SkyhighSecureWebGatewayOnPrem import insert_entry_command

    mock_args = {
        "list_id": "com.scur.type.regex.999",
        "entry_pos": "0",
        "name": "http*://new.evil.com/*",
        "description": "New evil domain",
    }
    mock_raw_response = (
        "<entry><title>Added Entry</title><content><listEntry><entry>http*://new.evil.com/*</entry><description>"
        "New evil domain</description></listEntry></content></entry>"
    )

    mocker.patch.object(client, "insert_entry", return_value=mock_raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    mocker.patch.object(demisto, "context", return_value={})

    mock_command_result = insert_entry_command(client, mock_args)

    assert mock_command_result.outputs_prefix == "SWG.List"
    assert mock_command_result.outputs_key_field == "ID"
    assert mock_command_result.outputs == {
        "ID": "com.scur.type.regex.999",
        "ListEntries": [
            {
                "ListID": "com.scur.type.regex.999",
                "Position": "0",
                "Name": "http*://new.evil.com/*",
                "Description": "New evil domain",
            }
        ],
    }


def test_insert_entry_command_existing_list(mocker):
    """
    Given
    - valid arguments for insert entry command
    - list with the same ID already exists in context data

    When
    - running insert_entry_command function

    Then
    - the expected entry context is returned with existing list format
    """
    from SkyhighSecureWebGatewayOnPrem import insert_entry_command

    mock_args = {
        "list_id": "com.scur.type.regex.386",
        "entry_pos": "1",
        "name": "http*://another.evil.com/*",
        "description": "Another evil domain",
    }
    mock_raw_response = (
        "<entry><title>Added Entry</title><content><listEntry><entry>http*://another.evil.com/*</entry>"
        "<description>Another evil domain</description></listEntry></content></entry>"
    )

    mocker.patch.object(client, "insert_entry", return_value=mock_raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    mocker.patch.object(demisto, "context", return_value={"SWG": {"List": {"ID": "com.scur.type.regex.386"}}})

    command_result = insert_entry_command(client, mock_args)

    assert command_result.outputs_prefix == 'SWG.List(val.ID && val.ID == "com.scur.type.regex.386").ListEntries'
    assert command_result.outputs_key_field == "Name"
    assert command_result.outputs == {
        "ListID": "com.scur.type.regex.386",
        "Position": "1",
        "Name": "http*://another.evil.com/*",
        "Description": "Another evil domain",
    }


def test_insert_entry_command_multiple_existing_lists(mocker):
    """
    Given
    - valid arguments for insert entry command
    - multiple lists already exists in context data

    When
    - running insert_entry_command function

    Then
    - the expected entry context is returned with existing list format
    """
    from SkyhighSecureWebGatewayOnPrem import insert_entry_command

    args = {
        "list_id": "com.scur.type.regex.777",
        "entry_pos": "0",
        "name": "http*://multiple.lists.com/*",
        "description": "Entry for multiple lists test",
    }
    raw_response = (
        "<entry><title>Added Entry</title><content><listEntry><entry>http*://multiple.lists.com/*</entry>"
        "<description>Entry for multiple lists test</description></listEntry></content></entry>"
    )

    mocker.patch.object(client, "insert_entry", return_value=raw_response)
    mocker.patch.object(client, "commit", return_value=True)
    mocker.patch.object(
        demisto, "context", return_value={"SWG": {"List": [{"ID": "com.scur.type.regex.111"}, {"ID": "com.scur.type.regex.222"}]}}
    )

    command_result = insert_entry_command(client, args)

    assert command_result.outputs_prefix == "SWG.List"
    assert command_result.outputs_key_field == "ID"
    assert command_result.outputs["ID"] == "com.scur.type.regex.777"