Skyhigh Secure Web Gateway (On Prem)
Manages the block and allow lists within Skyhigh Secure Web Gateway.
Network Security · McAfee Web Gateway
Details
| ID | Skyhigh Secure Web Gateway (On Prem) |
|---|---|
| Provider | Skyhigh Security |
| Category | Network Security |
| From Version | 6.8.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix 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-listCreate a new list.
-
swg-delete-entryDelete entry to from a list.
-
swg-delete-listDelete a list.
-
swg-get-available-listsGet all available lists.
-
swg-get-listRetrieve a specific list.
-
swg-get-list-entryRetrieve a specific entry from a list.
-
swg-insert-entryInsert a new entry to a list.
-
swg-modify-listOverwrites the complete XML configuration of a list.
import demistomock as demisto from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import from CommonServerUserPython import * # noqa """ IMPORTS """ import urllib from typing import Any import urllib3 # Disable insecure warnings urllib3.disable_warnings() """ CLIENT CLASS """ class Client(BaseClient): """Client class to interact with the service API""" def __init__(self, username, password, *args, **kwargs): super().__init__(*args, **kwargs) self.username = username self.password = password def __enter__(self): self.connect() return self def __exit__(self, _type: Any, *args: Any): self.close() def connect(self): """User login""" self._http_request( method="POST", url_suffix=f"/login?{urllib.parse.urlencode({'userName':self.username,'pass':self.password})}", resp_type="xml", ) def close(self): """User logout""" self._http_request(method="POST", url_suffix="/logout", resp_type="text") def get_lists(self, list_name: str | None = None, list_type: str | None = None) -> str: """Gets all available lists using the '/list' API endpoint""" url_suffix = "/list" list_filter = [] if list_name: list_filter.append(f"name={list_name}") if list_type: list_filter.append(f"type={list_type}") if list_filter: url_suffix += f"?{'&'.join(list_filter)}" return self._http_request(method="GET", url_suffix=url_suffix, resp_type="text") def get_list(self, list_id: str): return self._http_request(method="GET", url_suffix=f"/list/{list_id}", resp_type="text") def get_list_entry(self, list_id: str, entry_pos: str): return self._http_request( method="GET", url_suffix=f"/list/{list_id}/entry/{entry_pos}", resp_type="text", ok_codes=(200, 202, 203, 404), ) def commit(self): return self._http_request(method="POST", url_suffix="/commit", resp_type="text") def put_list(self, list_id: str, config: bytes): return self._http_request(method="PUT", url_suffix=f"/list/{list_id}", data=config, resp_type="text") def insert_entry(self, list_id: str, entry_pos: str, data: str): return self._http_request( method="POST", url_suffix=f"/list/{list_id}/entry/{entry_pos}/insert", data=data, resp_type="text", ) def delete_entry(self, list_id: str, entry_pos: str): return self._http_request( method="DELETE", url_suffix=f"/list/{list_id}/entry/{entry_pos}", resp_type="text", ) def create_list(self, data: str): return self._http_request(method="POST", url_suffix="/list", resp_type="text", data=data) def delete_list(self, list_id: str): return self._http_request(method="Delete", url_suffix=f"/list/{list_id}", resp_type="text") """ COMMAND FUNCTIONS """ def test_module(client: Client, args: dict[str, Any]) -> str: """Tests API connectivity and authentication' Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Raises exceptions if something goes wrong. Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. Returns: str: 'ok' if test passed, anything else will raise an exception and will fail the test. """ client.get_lists() return "ok" def get_lists_command(client: Client, args: dict[str, Any]) -> CommandResults: """ get lists command: Returns available lists for matching pattern Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['name']`` is used to filter lists by name. ``args['type']`` is used to filter lists by type. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains available lists. """ list_name = args.get("name", "") list_type = args.get("type", "") res = [] result = client.get_lists(list_name, list_type) data = json.loads(xml2json(result)) title = demisto.get(data, "feed.title") entries = demisto.get(data, "feed.entry", []) if isinstance(entries, dict): entries = [entries] for entry in entries: res.append( { "Title": entry.get("title", ""), "ID": entry.get("id", ""), "Type": entry.get("listType", ""), } ) return CommandResults( readable_output=tableToMarkdown(title, res, headers=["Title", "ID", "Type"]), outputs_prefix="SWG.List", outputs_key_field="ID", outputs=res, raw_response=result, ) def get_list_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ get list command: Returns list details and content Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to query. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list details and content. """ resEntries = [] list_id: str = args.get("list_id", "") result = client.get_list(list_id) data = json.loads(xml2json(result)) config = json2xml(demisto.get(data, "entry.content", data)).decode("utf-8") title = demisto.get(data, "entry.title") res = { "ID": list_id, "Title": title, "Type": demisto.get(data, "entry.listType", ""), "Description": demisto.get(data, "entry.content.list.description"), } entries = demisto.get(data, "entry.content.list.content.listEntry", []) if isinstance(entries, dict): entries = [entries] for pos, entry in enumerate(entries): description = entry.get("description") if not description: description = "" resEntries.append( { "ListID": list_id, "Position": str(pos), "Name": entry.get("entry", ""), "Description": description, } ) hr = tableToMarkdown("List Properties", res, headers=["Title", "ID", "Description", "Type"]) res["ListEntries"] = resEntries return CommandResults( readable_output=hr + tableToMarkdown(title, resEntries, headers=["Position", "Name", "Description"]), outputs_prefix="SWG.List", outputs_key_field=["ID"], outputs=res, raw_response=config, ) def get_list_entry_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ get list entry command: Returns a single entry form a list Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to query. ``args['entry_pos']`` the entry position to query. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list entry. """ list_id: str = args.get("list_id", "") entry_pos: str = args.get("entry_pos", "") result = client.get_list_entry(list_id, entry_pos) data = json.loads(xml2json(result)) title = demisto.get(data, "entry.title") entry = demisto.get(data, "entry.content.listEntry", {}) description = entry.get("description") if not description: description = "" res = { "ID": list_id, "ListEntries": [ { "ListID": list_id, "Position": entry_pos, "Name": entry.get("entry", ""), "Description": description, } ], } return CommandResults( readable_output=tableToMarkdown(title, res["ListEntries"], headers=["ListID", "Position", "Name", "Description"]), outputs_prefix="SWG.List", outputs_key_field=["ID"], outputs=res, raw_response=result, ) def modify_list_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ modify list command: Modify the list content Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to be modified. ``args['config']`` the config that should be modified to. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list details and content. """ resEntries = [] list_id: str = args.get("list_id", "") conf: str = args.get("config", "") result = client.put_list(list_id, conf.encode("utf-8")) client.commit() data = json.loads(xml2json(result)) config = json2xml(demisto.get(data, "entry.content", data)).decode("utf-8") title = demisto.get(data, "entry.title", "") description = demisto.get(data, "entry.content.list.description") if not description: description = "" res = { "ID": list_id, "Title": title, "Type": demisto.get(data, "entry.listType", ""), "Description": description, } entries = demisto.get(data, "entry.content.list.content.listEntry", []) if isinstance(entries, dict): entries = [entries] for pos, entry in enumerate(entries): description = entry.get("description") if not description: description = "" resEntries.append( { "ListID": list_id, "Position": str(pos), "Name": entry.get("entry", ""), "Description": description, } ) hr = tableToMarkdown("List Properties", res, headers=["Title", "ID", "Description", "Type"]) res["ListEntries"] = resEntries return CommandResults( readable_output=hr + tableToMarkdown(title, resEntries, headers=["Position", "Name", "Description"]), outputs_prefix="SWG.List", outputs_key_field=["ID"], outputs=res, raw_response=config, ) def insert_entry_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ insert entry command: Insert an entry to the list Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to be modified. ``args['entry_pos']`` the entry position to insert at. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the inserted list entry. """ list_id: str = args.get("list_id", "") entry_pos: str = args.get("entry_pos", "") name: str = args.get("name", "") description: str = args.get("description", "") entry = f"<listEntry><entry>{name}</entry><description>{description}</description></listEntry>" result = client.insert_entry(list_id, entry_pos, entry) client.commit() data = json.loads(xml2json(result)) title = f'Added {demisto.get(data, "entry.title")}' entry = demisto.get(data, "entry.content.listEntry", {}) description = entry.get("description") if not description: description = "" entry_name = entry.get("entry", "") list_entry = { "ListID": list_id, "Position": entry_pos, "Name": entry_name, "Description": description, } swg_lists = demisto.get(demisto.context(), "SWG.List", []) if isinstance(swg_lists, dict): swg_lists = [swg_lists] if any(item["ID"] == list_id for item in swg_lists): outputs_prefix = f'SWG.List(val.ID && val.ID == "{list_id}").ListEntries' outputs_key_field = "Name" res = list_entry else: outputs_prefix = "SWG.List" outputs_key_field = "ID" res = {"ID": list_id, "ListEntries": [list_entry]} return CommandResults( readable_output=tableToMarkdown(title, list_entry, headers=["ListID", "Position", "Name", "Description"]), outputs_prefix=outputs_prefix, outputs_key_field=outputs_key_field, outputs=res, raw_response=result, ) def delete_entry_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ delete entry command: Delete the list entry Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to be modified. ``args['entry_pos']`` the entry position to be deleted. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list entry. """ list_id: str = args.get("list_id", "") entry_pos: str = args.get("entry_pos", "") result = client.delete_entry(list_id, entry_pos) client.commit() data = json.loads(xml2json(result)) title = f'Deleted {demisto.get(data, "entry.title")}' entry = demisto.get(data, "entry.content.listEntry", {}) description = entry.get("description") if not description: description = "" res = { "ID": list_id, "ListEntries": [ { "ListID": list_id, "Position": entry_pos, "Name": entry.get("entry", ""), "Description": description, } ], } return CommandResults( readable_output=tableToMarkdown(title, res["ListEntries"], headers=["ListID", "Position", "Name", "Description"]), raw_response=result, ) def create_list_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ create list command: Create an empty list Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['name']`` the list name to be added. ``args['type']`` the list type to be added. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list entry. """ list_name: str = args.get("name", "") list_type: str = args.get("type", "") list_data = ( f'<list name="{list_name}" typeId="com.scur.type.{list_type}" classifier="Other" systemList="false" ' + 'structuralList="false" defaultRights="2"><description /><content /></list>' ) result = client.create_list(list_data) client.commit() data = json.loads(xml2json(result)) config = json2xml(demisto.get(data, "entry.content", data)).decode("utf-8") title = demisto.get(data, "entry.title") description = demisto.get(data, "entry.content.list.description") if not description: description = "" res = { "ID": demisto.get(data, "entry.id"), "Title": title, "Type": demisto.get(data, "entry.listType"), "Description": description, } hr = tableToMarkdown("Created List Properties", res, headers=["Title", "ID", "Description", "Type"]) return CommandResults( readable_output=hr, outputs_prefix="SWG.List", outputs_key_field=["ID"], outputs=res, raw_response=config ) def delete_list_command(client: Client, args: dict[str, Any]) -> CommandResults | str: """ create list command: Create an empty list Args: client (Client): API client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['list_id']`` the list id to be deleted. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the list entry. """ list_id: str = args.get("list_id", "") result = client.delete_list(list_id) client.commit() data = json.loads(xml2json(result)) title = demisto.get(data, "entry.title") description = demisto.get(data, "entry.content.list.description") if not description: description = "" res = { "ID": demisto.get(data, "entry.id"), "Title": title, "Type": demisto.get(data, "entry.listType"), "Description": description, } hr = tableToMarkdown("Deleted List Properties", res, headers=["Title", "ID", "Description", "Type"]) return CommandResults(readable_output=hr, raw_response=result) """ MAIN FUNCTION """ def main() -> None: """ main function, parses params and runs command functions """ user = demisto.params().get("credentials", {}).get("identifier") password = demisto.params().get("credentials", {}).get("password") base_url = urljoin(demisto.params()["url"], "/Konfigurator/REST") verify_certificate = not demisto.params().get("insecure", False) proxy = demisto.params().get("proxy", False) headers = {"Content-Type": "application/mwg+xml"} command = demisto.command() demisto.debug(f"Command being called is {command}") try: with Client( username=user, password=password, base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy, ) as client: commands = { "test-module": test_module, "swg-get-available-lists": get_lists_command, "swg-get-list": get_list_command, "swg-get-list-entry": get_list_entry_command, "swg-modify-list": modify_list_command, "swg-insert-entry": insert_entry_command, "swg-delete-entry": delete_entry_command, "swg-create-list": create_list_command, "swg-delete-list": delete_list_command, } if command not in commands: raise NotImplementedError(f"Command {command} was not implemented.") return_results(commands[command](client, demisto.args())) except Exception as e: return_error(f"Failed to execute {command} command.\nError:\n{e!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()