GCenter

This integration allows, via about twenty commands, to interact with the GCenter appliance via its API.

Network Security · Gatewatcher AionIQ

Details

IDGCenter
ProviderGatewatcher
CategoryNetwork Security
From Version6.2.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM

README

This integration allows, via about twenty commands, to interact with the GCenter appliance via its API.
This integration was integrated and tested with version v2.5.3.102 of GCenter.
To simplify GCenter v2.5.3.102 is called GCenter in the Pack.

Configure GCenter in Cortex

Parameter Description Required
GCenter IP address   True
GCenter Version   False
GCenter API token You must provide either an API token or a username and a password. False
GCenter username   False
GCenter password   False
Check the TLS certificate   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.

gw-get-alert


Get an alert by it’s uid

Base Command

gw-get-alert

Input

Argument Name Description Required
uid Alert identifier. Required

Context Output

Path Type Description
GCenter.Alert.Single.sha256 String The 256 Shasum Of The File
GCenter.Alert.Single.id String The Id Of The Inspectra Alert
GCenter.Alert.Single.flow_id Number The Flow Id Of The Alert
GCenter.Alert.Single.severity Number The Severity Of The Alert
GCenter.Alert.Single.src_ip String The Ip Address Of The Alert’S Source
GCenter.Alert.Single.dest_ip String The Ip Address Of The Alert’S Target
GCenter.Alert.Single.src_port Number The Port Of The Alert’S Source
GCenter.Alert.Single.dest_port Number The Port Of The Alert’S Target
GCenter.Alert.Single.gcap String The Gcap That Raised The Alert
GCenter.Alert.Single.type String Which Type Of Alert (Sigflow, Codebreaker…)
GCenter.Alert.Single.proto String The Protocol Used
GCenter.Alert.Single.host String The Host Where The Alert Was Found
GCenter.Alert.Single.app_proto String The Malware Application Prototype
GCenter.Alert.Single.alert_type String Which Event It Is ?
GCenter.Alert.Single.state String The State Of The Alert
GCenter.Alert.Single.matched_event String Value Of The Id Of An Other Alert That Matched (Allows The Correlation Between Alerts)
GCenter.Alert.Single.domain_name String For Dga Alerts Only
GCenter.Alert.Single.probability Number The Severity Probability
GCenter.Alert.Single.timestamp_detected Date When The Alert Was Detected
GCenter.Alert.Single.timestamp_analyzed Date When The Alert Was Analysed
GCenter.Alert.Single.retrohunt.timestamp_package String Utc Date When The Ioc Was Added To The Lastinfosec Update Package
GCenter.Alert.Single.retrohunt.ioc_creation_date Date The Ioc Creation Date
GCenter.Alert.Single.retrohunt.ioc_updated_date Date The Ioc Updated Date
GCenter.Alert.Single.retrohunt.description String The Alert Description
GCenter.Alert.Single.retrohunt.ioc_type String Host, Md5, Sha1, Sha256, Url
GCenter.Alert.Single.retrohunt.ioc_value String Characteristic Value Of The Ioc
GCenter.Alert.Single.retrohunt.matched_app_proto String The Sigflow Protocol That Contains This Ioc
GCenter.Alert.Single.retrohunt.matched_event_type String The Sigflow Event Type That Contains This Ioc
GCenter.Alert.Single.retrohunt.case_id String Uuid Of The Box To Which The Ioc Belongs
GCenter.Alert.Single.retrohunt.ioc_id String Uuid Of The Ioc
GCenter.Alert.Single.retrohunt.risk String Suspicious, High Suspicious, Malicious
GCenter.Alert.Single.retrohunt.usage_mode String Usage Mode
GCenter.Alert.Single.retrohunt.tlp String Tlp
GCenter.Alert.Single.powershell.file_id String The File Id
GCenter.Alert.Single.powershell.scores.proba_obfuscated Number The Probability It Is Obfuscated
GCenter.Alert.Single.powershell.scores.analysis Number The Powershell Analysis Score
GCenter.Alert.Single.shellcode.file_id String The File Id
GCenter.Alert.Single.shellcode.encodings.name String The Name Of The Encoding
GCenter.Alert.Single.shellcode.encodings.count Number The Number Of The Encoding Elements
GCenter.Alert.Single.shellcode.calls.call String The Name Of The Call Of The Alert
GCenter.Alert.Single.shellcode.calls.args String The Argument Used For The Call
GCenter.Alert.Single.shellcode.calls.ret String The Retention Of The Call
GCenter.Alert.Single.shellcode.calls.index Number The Call Index
GCenter.Alert.Single.malware.analyzed_clean Number Number Of Engines That Returned A Clean Status
GCenter.Alert.Single.malware.analyzed_infected Number Number Of Engines That Returned An Infected Status
GCenter.Alert.Single.malware.analyzed_suspicious Number Number Of Engines That Returned A Suspicious Status
GCenter.Alert.Single.malware.analyzed_other Number Number Of Engines That Returned Other Statuses
GCenter.Alert.Single.malware.analyzed_error Number Number Of Engines That Failed To Analyze The File
GCenter.Alert.Single.malware.code Number The Global Code Result
GCenter.Alert.Single.malware.def_time Date When The Last Engines Have Ended The Scan
GCenter.Alert.Single.malware.scan_time Number The Scan Time In Ms.
GCenter.Alert.Single.malware.threats_found String The Threats Found By The Engines
GCenter.Alert.Single.malware.reporting_token String The Reporting Token Returned By The Gbox.
GCenter.Alert.Single.malware.engines_report.0.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.0.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.0.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.1.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.1.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.1.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.2.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.2.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.2.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.3.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.3.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.3.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.4.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.4.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.4.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.5.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.5.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.5.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.6.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.6.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.6.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.7.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.7.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.7.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.8.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.8.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.8.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.9.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.9.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.9.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.10.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.10.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.10.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.11.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.11.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.11.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.12.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.12.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.12.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.13.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.13.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.13.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.14.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.14.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.14.scan_result String Analysis Result
GCenter.Alert.Single.malware.engines_report.15.id String The Hash Pf The Engine
GCenter.Alert.Single.malware.engines_report.15.threat_details String The Threat Found By The Engine
GCenter.Alert.Single.malware.engines_report.15.scan_result String Analysis Result
GCenter.Alert.Single.malware.magic_details String The File Magic
GCenter.Alert.Single.malware.total_found String The Malcore Number Of Engines That Found The File Suspicious / The Total Number Of Engines
GCenter.Alert.Single.sigflow.alert.action String Action
GCenter.Alert.Single.sigflow.alert.signature_id String Signature Id
GCenter.Alert.Single.sigflow.alert.gid String Gid
GCenter.Alert.Single.sigflow.alert.category String Category
GCenter.Alert.Single.sigflow.packet String Packet
GCenter.Alert.Single.sigflow.in_iface String In Which Interface The Alert Occurred
GCenter.Alert.Single.sigflow.stream Number Is It Streaming (!= 0)
GCenter.Alert.Single.sigflow.payload String Payload
GCenter.Alert.Single.sigflow.payload_printable String Payload Printable
Command Example

!gw-get-alert uid="d7e612cb-567a-431b-a14b-9f9f4e88c9a4"

Context Example
{
    "sha256": "f16d19ac9697d9892b0f910601a61d041d64",
    "id": "45e6ed3c-1082-4d33-9514-162748d7d41f",
    "flow_id": 1544096072809159,
    "severity": 1,
    "src_ip": "192.168.0.2",
    "dest_ip": "192.168.0.1",
    "src_port": 80,
    "dest_port": 35168,
    "gcap": "test.domain.com",
    "type": "malcore",
    "proto": "TCP",
    "host": "test.domain.com",
    "app_proto": "http",
    "alert_type": "malware",
    "state": "Infected",
    "matched_event": "3d35e491-cfc8-4271-815b-ff018a036c7c",
    "domain_name": "nzpzxcox.com",
    "probability": 0.55555555,
    "timestamp_detected": "2022-03-21T11:34:47.000Z",
    "timestamp_analyzed": "2022-03-21T13:58:42.742Z",
    "dest_geoip": {},
    "src_geoip": {},
    "retrohunt": {
        "timestamp_package": "2022-06-06T22:00:01.632829+0000",
        "ioc_creation_date": "2022-05-27T18:37:30+00:00",
        "ioc_updated_date": "2022-06-06T21:05:12+00:00",
        "description": "'test.domain.com' is a Suspicious Host.",
        "ioc_type": "Host",
        "ioc_value": "test.domain.com",
        "matched_app_proto": "http",
        "matched_event_type": "http",
        "meta_data": {},
        "targeted_organizations": [],
        "targeted_platforms": [],
        "targeted_sectors": [],
        "threat_actor": [],
        "external_links": [],
        "relations": [],
        "campaigns": [],
        "categories": [],
        "families": [],
        "vulnerabilities": [],
        "ttp": [],
        "case_id": "1746d38d-58f3-4b43-b4ee-6f0b43527d49",
        "ioc_id": "183abf8e-b0a5-4ed0-a93f-e5d7927648b8",
        "risk": "Suspicious",
        "usage_mode": "hunting",
        "tlp": "green"
    },
    "powershell": {
        "file_id": "06-08-2022T11:37:11_1348935773_gcap-dean.org",
        "scores": {
            "proba_obfuscated": 0.2,
            "analysis": 241,
            "analysis_detailed": {}
        }
    },
    "shellcode": {
        "file_id": "file_id",
        "encodings": [
            {
                "name": "Bloxor",
                "count": 2
            }
        ],
        "calls": [
            {
                "call": "ws2_32_recv",
                "args": "{'sockfd': 'Socket_1-bind (4)', 'backlog': 19103712}",
                "ret": "90137289",
                "index": 0
            }
        ]
    },
    "malware": {
        "analyzed_clean": 11,
        "analyzed_infected": 5,
        "analyzed_suspicious": 0,
        "analyzed_other": 0,
        "analyzed_error": 0,
        "code": 1,
        "def_time": "2022-05-31T21:45:33Z",
        "scan_time": 3785,
        "threats_found": "Infected : Gen:Variant.Ulise.315566 (B)",
        "reporting_token": "No GBOX",
        "engines_report": {
            "0": {
                "id": "XXX",
                "threat_details": "Gen:Variant.Ulise.315566 (B)",
                "scan_result": "INFECTED"
            },
            "1": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "2": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "3": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "4": {
                "id": "XXX",
                "threat_details": "WinGo/TrojanDownloader.Agent.BD trojan",
                "scan_result": "INFECTED"
            },
            "5": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "6": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "7": {
                "id": "XXX",
                "threat_details": "Trojan.Donut.Win64.545",
                "scan_result": "INFECTED"
            },
            "8": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "9": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "10": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "11": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "12": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "13": {
                "id": "XXX",
                "threat_details": "",
                "scan_result": "CLEAN"
            },
            "14": {
                "id": "XXX",
                "threat_details": "W64/Donut.B.gen!Eldorado",
                "scan_result": "INFECTED"
            },
            "15": {
                "id": "XXX",
                "threat_details": "Trojan.Win64.Crypt",
                "scan_result": "INFECTED"
            }
        },
        "magic_details": "PE32+ executable (DLL) (GUI) x86-64, for MS Windows",
        "total_found": "5/16"
    },
    "sigflow": {
        "alert": {
            "action": "allowed",
            "signature_id": "202",
            "gid": "1",
            "category": "A Network Trojan was detected"
        },
        "packet": "XXXXXXXXXXXXXXXXXX",
        "in_iface": "mon5",
        "stream": 0,
        "payload": "XXXXXXXXXXXXXXXXXX",
        "payload_printable": "XXXXXXXXXXXXXXXXXX",
        "extra_keys": {}
    }
}
Human Readable Output

Elasticsearch alert entry

alert_type app_proto dest_geoip dest_ip dest_port domain_name flow_id gcap host id malware matched_event powershell probability proto retrohunt severity sha256 shellcode sigflow src_geoip src_ip src_port state timestamp_analyzed timestamp_detected type
malware http   192.168.0.1 35168 nzpzxcox.com 1544096072809159 test.domain.com test.domain.com 45e6ed3c-1082-4d33-9514-162748d7d41f analyzed_clean: 11
analyzed_infected: 5
analyzed_suspicious: 0
analyzed_other: 0
analyzed_error: 0
code: 1
def_time: 2022-05-31T21:45:33Z
scan_time: 3785
threats_found: Infected : Gen:Variant.Ulise.315566 (B)
reporting_token: No GBOX
engines_report: {“0”: {“id”: “XXX”, “threat_details”: “Gen:Variant.Ulise.315566 (B)”, “scan_result”: “INFECTED”}, “1”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “2”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “3”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “4”: {“id”: “XXX”, “threat_details”: “WinGo/TrojanDownloader.Agent.BD trojan”, “scan_result”: “INFECTED”}, “5”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “6”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “7”: {“id”: “XXX”, “threat_details”: “Trojan.Donut.Win64.545”, “scan_result”: “INFECTED”}, “8”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “9”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “10”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “11”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “12”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “13”: {“id”: “XXX”, “threat_details”: “”, “scan_result”: “CLEAN”}, “14”: {“id”: “XXX”, “threat_details”: “W64/Donut.B.gen!Eldorado”, “scan_result”: “INFECTED”}, “15”: {“id”: “XXX”, “threat_details”: “Trojan.Win64.Crypt”, “scan_result”: “INFECTED”}}
magic_details: PE32+ executable (DLL) (GUI) x86-64, for MS Windows
total_found: 5/16
3d35e491-cfc8-4271-815b-ff018a036c7c file_id: 06-08-2022T11:37:11_1348935773_gcap-dean.org
scores: {“proba_obfuscated”: 0.2, “analysis”: 241, “analysis_detailed”: {}}
0.55555555 TCP timestamp_package: 2022-06-06T22:00:01.632829+0000
ioc_creation_date: 2022-05-27T18:37:30+00:00
ioc_updated_date: 2022-06-06T21:05:12+00:00
description: ‘test.domain.com’ is a Suspicious Host.
ioc_type: Host
ioc_value: test.domain.com
matched_app_proto: http
matched_event_type: http
meta_data: {}
targeted_organizations:
targeted_platforms:
targeted_sectors:
threat_actor:
external_links:
relations:
campaigns:
categories:
families:
vulnerabilities:
ttp:
case_id: 1746d38d-58f3-4b43-b4ee-6f0b43527d49
ioc_id: 183abf8e-b0a5-4ed0-a93f-e5d7927648b8
risk: Suspicious
usage_mode: hunting
tlp: green
1 f16d19ac9697d9892b0f910601a61d041d64 file_id: file_id
encodings: {‘name’: ‘Bloxor’, ‘count’: 2}
calls: {‘call’: ‘ws2_32_recv’, ‘args’: “{‘sockfd’: ‘Socket_1-bind (4)’, ‘backlog’: 19103712}”, ‘ret’: ‘90137289’, ‘index’: 0}
alert: {“action”: “allowed”, “signature_id”: “202”, “gid”: “1”, “category”: “A Network Trojan was detected”}
packet: XXXXXXXXXXXXXXXXXX
in_iface: mon5
stream: 0
payload: XXXXXXXXXXXXXXXXXX
payload_printable: XXXXXXXXXXXXXXXXXX
extra_keys: {}
  192.168.0.2 80 Infected 2022-03-21T13:58:42.742Z 2022-03-21T11:34:47.000Z malcore

gw-es-query


Get Elasticsearch data

Base Command

gw-es-query

Input

Argument Name Description Required
index Index to be queried. Possible values are: suricata, malware, codebreaker, netdata, syslog, machine_learning, retrohunt, iocs. Default is suricata. Optional
query Elaticsearch query. Default is {}. Optional

Context Output

There is no context output for this command.

Command Example

!gw-es-query index="suricata" query="{}"

gw-add-malcore-list-entry


Add malcore whitelist/blacklist entry

Base Command

gw-add-malcore-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required
sha256 SHA256 to be added. Required
comment Comment to be added. Optional
threat Comment to be added. Optional

Context Output

Path Type Description
GCenter.Malcore.sha256 String Sha256
GCenter.Malcore.created Date Created
GCenter.Malcore.comment String Comment
GCenter.Malcore.threat String Name Of Threat For Reference
Command Example

!gw-add-malcore-list-entry type="white" sha256="d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e"

Context Example
{
    "sha256": "d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e",
    "created": "2022-03-21T16:36:58.957178Z",
    "comment": "test",
    "threat": "undefined"
}
Human Readable Output

Malcore whitelist/blacklist entry

comment created sha256 threat
test 2022-03-21T16:36:58.957178Z d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e undefined

gw-del-malcore-list-entry


Delete malcore whitelist/blacklist entry

Base Command

gw-del-malcore-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required
sha256 SHA256 to be deleted. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-malcore-list-entry type="white" sha256="d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e"

gw-add-dga-list-entry


Add dga whitelist/blacklist entry

Base Command

gw-add-dga-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required
domain Domain name to be added. Required
comment Comment to be added. Optional

Context Output

Path Type Description
GCenter.Dga.domain_name String Domain Name
GCenter.Dga.created Date Created
GCenter.Dga.comment String Comment
GCenter.Dga.is_wildcard Boolean Is Wildcard
Command Example

!gw-add-dga-list-entry type="white" domain="test.domain.com"

Context Example
{
    "domain_name": "test.domain.com",
    "created": "2022-03-21T16:30:20.012035Z",
    "comment": "test",
    "is_wildcard": false
}
Human Readable Output

DGA whitelist/blacklist entry

comment created domain_name is_wildcard
test 2022-03-21T16:30:20.012035Z test.domain.com false

gw-del-dga-list-entry


Delete dga whitelist/blacklist entry

Base Command

gw-del-dga-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required
domain Domain name to be deleted. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-dga-list-entry type="white" domain="test.domain.com"

gw-add-ignore-asset-name


Ignore asset name

Base Command

gw-add-ignore-asset-name

Input

Argument Name Description Required
name Name to be ignored. Required
start Will be ignored if they start with this name. Required
end Will be ignored if they end with this name. Required

Context Output

Path Type Description
GCenter.Ignore.AssetName.id String Id
GCenter.Ignore.AssetName.created_at Date Created At
GCenter.Ignore.AssetName.created_by String Created By
GCenter.Ignore.AssetName.name String Ignored Name For The Assets (Hostnames). Case Insensitive.
GCenter.Ignore.AssetName.is_startswith_pattern Boolean Should The Assets (Hostnames) Be Ignored If They Start With This Name ?
GCenter.Ignore.AssetName.is_endswith_pattern Boolean Should The Assets (Hostnames) Be Ignored If They End With This Name ?
Command Example

!gw-add-ignore-asset-name name="test_asset"

Context Example
{
    "id": "1",
    "created_at": "2022-03-21T16:37:54.657263Z",
    "created_by": "admin",
    "name": "test_asset",
    "is_startswith_pattern": true,
    "is_endswith_pattern": false
}
Human Readable Output

Asset name entry

created_at created_by id is_endswith_pattern is_startswith_pattern name
2022-03-21T16:37:54.657263Z admin 1 false true test_asset

gw-add-ignore-kuser-ip


Ignore kuser IP

Base Command

gw-add-ignore-kuser-ip

Input

Argument Name Description Required
ip IP to be ignored. Required

Context Output

Path Type Description
GCenter.Ignore.KuserIP.id String Id
GCenter.Ignore.KuserIP.created_at Date Created At
GCenter.Ignore.KuserIP.created_by String Created By
GCenter.Ignore.KuserIP.ip String Ignored Ip For The Kerberos Users
Command Example

!gw-add-ignore-kuser-ip ip="10.10.10.0"

Context Example
{
    "id": "2",
    "created_at": "2022-03-21T16:38:35.484082Z",
    "created_by": "admin",
    "ip": "10.10.10.0"
}
Human Readable Output

Kuser IP entry

created_at created_by id ip
2022-03-21T16:38:35.484082Z admin 2 10.10.10.0

gw-add-ignore-kuser-name


Ignore kuser name

Base Command

gw-add-ignore-kuser-name

Input

Argument Name Description Required
name Name to be ignored. Required
start Will be ignored if they start with this name. Required
end Will be ignored if they end with this name. Required

Context Output

Path Type Description
GCenter.Ignore.KuserName.id String Id
GCenter.Ignore.KuserName.created_at Date Created At
GCenter.Ignore.KuserName.created_by String Created By
GCenter.Ignore.KuserName.name String Ignored Name For The Kerberos Users. Case Insensitive.
GCenter.Ignore.KuserName.is_startswith_pattern Boolean Should The Kerberos Users Be Ignored If They Start With This Name ?
GCenter.Ignore.KuserName.is_endswith_pattern Boolean Should The Kerberos Users Be Ignored If They End With This Name ?
Command Example

!gw-add-ignore-kuser-name name="test_kuser"

Context Example
{
    "id": "1",
    "created_at": "2022-03-21T16:39:18.435420Z",
    "created_by": "admin",
    "name": "test_kuser",
    "is_startswith_pattern": true,
    "is_endswith_pattern": false
}
Human Readable Output

Kuser name entry

created_at created_by id is_endswith_pattern is_startswith_pattern name
2022-03-21T16:39:18.435420Z admin 1 false true test_kuser

gw-add-ignore-mac-address


Ignore mac address

Base Command

gw-add-ignore-mac-address

Input

Argument Name Description Required
mac MAC address to be ignored. Required
start Will be ignored if they start with this name. Required

Context Output

Path Type Description
GCenter.Ignore.MacAddress.id String Id
GCenter.Ignore.MacAddress.created_at Date Created At
GCenter.Ignore.MacAddress.created_by String Created By
GCenter.Ignore.MacAddress.address String Address
GCenter.Ignore.MacAddress.is_startswith_pattern Boolean Should The Mac Addresses Be Ignored If They Start With This Address Value ?
Command Example

!gw-add-ignore-mac-address mac="50:50:50:50:50:50"

Context Example
{
    "id": "1",
    "created_at": "2022-03-21T16:39:48.363094Z",
    "created_by": "admin",
    "address": "00:50:50:50:50:50",
    "is_startswith_pattern": true
}
Human Readable Output

MAC adrress entry

address created_at created_by id is_startswith_pattern
00:50:50:50:50:50 2022-03-21T16:39:48.363094Z admin 1 true

gw-del-ignore-asset-name


Delete an ignore asset ID

Base Command

gw-del-ignore-asset-name

Input

Argument Name Description Required
ignore_id Ignore asset ID. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-ignore-asset-name ignore_id=1

gw-del-ignore-kuser-ip


Delete an ignore kuser IP ID

Base Command

gw-del-ignore-kuser-ip

Input

Argument Name Description Required
ignore_id Ignore kuser IP ID. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-ignore-kuser-ip ignore_id=1

gw-del-ignore-kuser-name


Delete an ignore kuser name ID

Base Command

gw-del-ignore-kuser-name

Input

Argument Name Description Required
ignore_id Ignore kuser name ID. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-ignore-kuser-name ignore_id=1

gw-del-ignore-mac-address


Delete an ignore mac address ID

Base Command

gw-del-ignore-mac-address

Input

Argument Name Description Required
ignore_id Ignore mac address ID. Required

Context Output

There is no context output for this command.

Command Example

!gw-del-ignore-mac-address ignore_id=1

gw-send-malware


Send malware

Base Command

gw-send-malware

Input

Argument Name Description Required
filename Filename. Required
file_id File entry id. Required

Context Output

Path Type Description
GCenter.Gscan.Malware.id String The Id Of The Gscan History Message
GCenter.Gscan.Malware.created Date Date Of Creation
GCenter.Gscan.Malware.username String The User’S Username Who Uploaded The File
GCenter.Gscan.Malware.user_agent String The Client’S User-Agent
GCenter.Gscan.Malware.ip_address String The Ip Address Of The User Who Uploaded The File
GCenter.Gscan.Malware.file_name String Original File Name
GCenter.Gscan.Malware.sha256 String Sha256
GCenter.Gscan.Malware.is_clean Unknown Clean
GCenter.Gscan.Malware.is_analysis_successful Boolean Scan Succes
GCenter.Gscan.Malware.malcore_code_result String Malcore Code Result
GCenter.Gscan.Malware.threat_name String Threat Name
GCenter.Gscan.Malware.nb_alerts Number Number Or Malcore Alerts
GCenter.Gscan.Malware.nb_engines Number Number Or Malcore Engines
GCenter.Gscan.Malware.is_whiteblack_listed Boolean Is White Or Black Listed?
GCenter.Gscan.Malware.malcore_code_result_name String Malcore Code Result Name
GCenter.Gscan.Malware.status String The Malcore Status
Command Example

!gw-send-malware filename="test" file_id="331@dfca9ea2-5198-4d64-8c36-5282ac3b2dc5"

Context Example
{
    "id": "1",
    "created": "2022-03-21T16:42:11.996076Z",
    "username": "admin",
    "user_agent": "Mozilla/5.0",
    "ip_address": "10.10.10.10",
    "file_name": "Arch.jpg",
    "sha256": "1a9487d49d842ebdee5ad870065eb74dc7044",
    "is_clean": null,
    "is_analysis_successful": false,
    "malcore_code_result": "5",
    "threat_name": "",
    "nb_alerts": 0,
    "nb_engines": 0,
    "is_whiteblack_listed": false,
    "malcore_code_result_name": "Unknown",
    "status": "Unknown"
}
Human Readable Output

Malcore analysis result

created file_name id ip_address is_analysis_successful is_clean is_whiteblack_listed malcore_code_result malcore_code_result_name nb_alerts nb_engines sha256 status threat_name user_agent username
2022-03-21T16:42:11.996076Z Arch.jpg 1 10.10.10.10 false   false 5 Unknown 0 0 1a9487d49d842ebdee5ad870065eb74dc7044 Unknown   Mozilla/5.0 admin

gw-send-powershell


Send powershell

Base Command

gw-send-powershell

Input

Argument Name Description Required
filename Filename. Required
file_id File entry id. Required

Context Output

Path Type Description
GCenter.Gscan.Powershell.id String The Id Of The Gscan History Message
GCenter.Gscan.Powershell.created Date Date Of Creation
GCenter.Gscan.Powershell.username String The User’S Username Who Uploaded The File
GCenter.Gscan.Powershell.user_agent String The Client’S User-Agent
GCenter.Gscan.Powershell.ip_address String The Ip Address Of The User Who Uploaded The File
GCenter.Gscan.Powershell.file_name String Original File Name
GCenter.Gscan.Powershell.sha256 String Sha256
GCenter.Gscan.Powershell.is_clean Boolean Clean
GCenter.Gscan.Powershell.is_analysis_successful Boolean Scan Succes
GCenter.Gscan.Powershell.status String Status
GCenter.Gscan.Powershell.proba_obfuscated Number Proba_Obfuscated
GCenter.Gscan.Powershell.analysis_score Number Analysis_Score
GCenter.Gscan.Powershell.is_whiteblack_listed Boolean Is White Or Black Listed?
Command Example

!gw-send-powershell filename="test" file_id="331@dfca9ea2-5198-4d64-8c36-5282ac3b2dc5"

Context Example
{
    "id": "2",
    "created": "2022-03-21T16:43:35.591406Z",
    "username": "admin",
    "user_agent": "Mozilla/5.0",
    "ip_address": "10.10.10.10",
    "file_name": "Arch.jpg",
    "sha256": "1a9487d49d842ebdee5ad870065eb74dc7044",
    "is_clean": true,
    "is_analysis_successful": true,
    "status": "Clean",
    "proba_obfuscated": 0,
    "analysis_score": 0,
    "is_whiteblack_listed": false
}
Human Readable Output

Powershell analysis result

analysis_score created file_name id ip_address is_analysis_successful is_clean is_whiteblack_listed proba_obfuscated sha256 status user_agent username
0 2022-03-21T16:43:35.591406Z Arch.jpg 2 10.10.10.10 true true false 0 1a9487d49d842ebdee5ad870065eb74dc7044 Clean Mozilla/5.0 admin

gw-send-shellcode


Send shellcode

Base Command

gw-send-shellcode

Input

Argument Name Description Required
filename Filename. Required
file_id File entry id. Required
deep Deep scan. Optional
timeout Deep scan timeout. Default is 120. Optional

Context Output

Path Type Description
GCenter.Gscan.Shellcode.id String The Id Of The Gscan History Message
GCenter.Gscan.Shellcode.created Date Date Of Creation
GCenter.Gscan.Shellcode.username String The User’S Username Who Uploaded The File
GCenter.Gscan.Shellcode.user_agent String The Client’S User-Agent
GCenter.Gscan.Shellcode.ip_address String The Ip Address Of The User Who Uploaded The File
GCenter.Gscan.Shellcode.file_name String Original File Name
GCenter.Gscan.Shellcode.sha256 String Sha256
GCenter.Gscan.Shellcode.is_clean Boolean Clean
GCenter.Gscan.Shellcode.is_analysis_successful Boolean Scan Succes
GCenter.Gscan.Shellcode.status String Status
GCenter.Gscan.Shellcode.architecture Unknown Architecture
GCenter.Gscan.Shellcode.is_whiteblack_listed Boolean Is White Or Black Listed?
Command Example

!gw-send-shellcode filename="test" file_id="331@dfca9ea2-5198-4d64-8c36-5282ac3b2dc5" deep=false timeout=120

Context Example
{
    "id": "3",
    "created": "2022-03-21T16:44:26.214241Z",
    "username": "admin",
    "user_agent": "Mozilla/5.0",
    "ip_address": "10.10.10.10",
    "file_name": "Arch.jpg",
    "sha256": "1a9487d49d842ebdee5ad870065eb74dc7044",
    "is_clean": true,
    "is_analysis_successful": true,
    "status": "Clean",
    "architecture": null,
    "encodings": [],
    "is_whiteblack_listed": false
}
Human Readable Output

Shellcode analysis result

architecture created encodings file_name id ip_address is_analysis_successful is_clean is_whiteblack_listed sha256 status user_agent username
  2022-03-21T16:44:26.214241Z   Arch.jpg 3 10.10.10.10 true true false 1a9487d49d842ebdee5ad870065eb74dc7044 Clean Mozilla/5.0 admin

gw-es-wrapper


Get Elasticsearch data using a wrapper

Base Command

gw-es-wrapper

Input

Argument Name Description Required
index index. Possible values are: suricata, codebreaker, malware, netdata, syslog, machine_learning, retrohunt, iocs. Required
aggs_term List and count each distinct values of a document field using the terms aggregation
If aggs_term is empty list hits value
Exemple : “src_ip,dest_ip”. Possible values are: src_ip, dest_ip, http.hostname, tls.sni, SHA256.
Optional
must_match Filter document that match the value using the term query
Exemple : “alert.severity=1,app_proto=http”.
Optional
must_exists Filter document with existing key using the exists query
Exemple : “http.hostname,http.url”.
Optional
timerange Set the lower timerange in hour based on the now keyword. Default is 24. Optional
formatted True to get the list of aggregation value False to get entire response. Possible values are: True, False. Default is True. Optional
size Set the number of aggregate or hits value that can be returned. Default is 100. Optional

Context Output

There is no context output for this command.

Command Example

!gw-es-wrapper index="malware" aggs_term="src_ip" must_match="state=Infected" timerange="240" formatted="True"

Context Example
{
    "src_ip": [
        "10.10.10.10"
    ]
}
Human Readable Output

Elasticsearch wrapper result

src_ip
10.10.10.10

gw-get-malcore-list-entry


Get the malcore whitelist/blacklist

Base Command

gw-get-malcore-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required

Context Output

Path Type Description
GCenter.Malcore.List.sha256 String Sha256
GCenter.Malcore.List.created Date Created
GCenter.Malcore.List.comment String Comment
GCenter.Malcore.List.threat String Name Of Threat For Reference
Command Example

!gw-get-malcore-list-entry type=black

Context Example
[
    {
        "sha256": "d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351f",
        "created": "2022-09-13T08:16:21.400100Z",
        "comment": "added by cortex",
        "threat": "undefined"
    },
    {
        "sha256": "d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e",
        "created": "2022-09-13T08:16:09.880381Z",
        "comment": "added by cortex",
        "threat": "undefined"
    }
]
Human Readable Output

Malcore whitelist/blacklist entry

comment created sha256 threat
added by cortex 2022-09-13T08:16:21.400100Z d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351f undefined
added by cortex 2022-09-13T08:16:09.880381Z d955e262d7a05fc436e65c2a312593e4c7031482d90cebd29e69059053b1351e undefined

gw-get-dga-list-entry


Get the dga whitelist/blacklist

Base Command

gw-get-dga-list-entry

Input

Argument Name Description Required
type List type. Possible values are: white, black. Required

Context Output

Path Type Description
GCenter.Dga.List.domain_name String Domain Name
GCenter.Dga.List.created Date Created
GCenter.Dga.List.comment String Comment
GCenter.Dga.List.is_wildcard Boolean Is Wildcard
Command Example

!gw-get-dga-list-entry type=black

Context Example
[
    {
        "domain_name": "test.domain.com",
        "created": "2022-03-21T16:30:20.012035Z",
        "comment": "added by cortex",
        "is_wildcard": false
    }
]
Human Readable Output

DGA whitelist/blacklist entry

comment created domain_name is_wildcard
added by cortex 2022-03-21T16:30:20.012035Z test.domain.com false

gw-get-ignore-asset-name


Get all the ignored asset names

Base Command

gw-get-ignore-asset-name

Input

There are no input arguments for this command.

Context Output

Path Type Description
GCenter.Ignore.AssetName.List.id String Id
GCenter.Ignore.AssetName.List.created_at Date Created At
GCenter.Ignore.AssetName.List.created_by String Created By
GCenter.Ignore.AssetName.List.name String Ignored Name For The Assets (Hostnames). Case Insensitive.
GCenter.Ignore.AssetName.List.is_startswith_pattern Boolean Should The Assets (Hostnames) Be Ignored If They Start With This Name ?
GCenter.Ignore.AssetName.List.is_endswith_pattern Boolean Should The Assets (Hostnames) Be Ignored If They End With This Name ?
Command Example

##### Context Example

```json
[
    {
        "id": "1",
        "created_at": "2022-09-13T13:31:18.427519Z",
        "created_by": "admin",
        "name": "test",
        "is_startswith_pattern": false,
        "is_endswith_pattern": true
    },
    {
        "id": "2",
        "created_at": "2022-09-13T13:31:31.049593Z",
        "created_by": "admin",
        "name": "test2",
        "is_startswith_pattern": true,
        "is_endswith_pattern": false
    }
]
Human Readable Output

Asset name entry

created_at created_by id is_endswith_pattern is_startswith_pattern name
2022-09-13T13:31:18.427519Z admin 1 true false test
2022-09-13T13:31:31.049593Z admin 2 false true test2

gw-get-ignore-kuser-ip


Get all the ignored kuser IP

Base Command

gw-get-ignore-kuser-ip

Input

There are no input arguments for this command.

Context Output

Path Type Description
GCenter.Ignore.KuserIP.List.id String Id
GCenter.Ignore.KuserIP.List.created_at Date Created At
GCenter.Ignore.KuserIP.List.created_by String Created By
GCenter.Ignore.KuserIP.List.ip String Ignored Ip For The Kerberos Users
Command Example

##### Context Example

```json
[
    {
        "id": "1",
        "created_at": "2022-09-13T12:06:29.575735Z",
        "created_by": "admin",
        "ip": "10.10.10.0"
    },
    {
        "id": "2",
        "created_at": "2022-09-13T13:30:26.791512Z",
        "created_by": "admin",
        "ip": "10.10.10.0"
    }
]
Human Readable Output

Kuser IP entry

created_at created_by id ip
2022-09-13T12:06:29.575735Z admin 1 10.10.10.0
2022-09-13T13:30:26.791512Z admin 2 10.10.10.0

gw-get-ignore-kuser-name


Get all the ignored kuser name

Base Command

gw-get-ignore-kuser-name

Input

There are no input arguments for this command.

Context Output

Path Type Description
GCenter.Ignore.KuserName.List.id String Id
GCenter.Ignore.KuserName.List.created_at Date Created At
GCenter.Ignore.KuserName.List.created_by String Created By
GCenter.Ignore.KuserName.List.name String Ignored Name For The Kerberos Users. Case Insensitive.
GCenter.Ignore.KuserName.List.is_startswith_pattern Boolean Should The Kerberos Users Be Ignored If They Start With This Name ?
GCenter.Ignore.KuserName.List.is_endswith_pattern Boolean Should The Kerberos Users Be Ignored If They End With This Name ?
Command Example

##### Context Example

```json
[
    {
        "id": "1",
        "created_at": "2022-09-13T13:27:50.136561Z",
        "created_by": "admin",
        "name": "test",
        "is_startswith_pattern": true,
        "is_endswith_pattern": false
    },
    {
        "id": "2",
        "created_at": "2022-09-13T13:28:02.072013Z",
        "created_by": "admin",
        "name": "test2",
        "is_startswith_pattern": false,
        "is_endswith_pattern": true
    }
]
Human Readable Output

Kuser name entry

created_at created_by id is_endswith_pattern is_startswith_pattern name
2022-09-13T13:27:50.136561Z admin 1 false true test
2022-09-13T13:28:02.072013Z admin 2 true false test2

gw-get-ignore-mac-address


Get all the ignored mac addresses

Base Command

gw-get-ignore-mac-address

Input

There are no input arguments for this command.

Context Output

Path Type Description
GCenter.Ignore.MacAddress.List.id String Id
GCenter.Ignore.MacAddress.List.created_at Date Created At
GCenter.Ignore.MacAddress.List.created_by String Created By
GCenter.Ignore.MacAddress.List.address String Address
GCenter.Ignore.MacAddress.List.is_startswith_pattern Boolean Should The Mac Addresses Be Ignored If They Start With This Address Value ?
Command Example

##### Context Example

```json
[
    {
        "id": "1",
        "created_at": "2022-09-13T13:25:55.679624Z",
        "created_by": "admin",
        "address": "00:50:50:50:50:50",
        "is_startswith_pattern": true
    },
    {
        "id": "2",
        "created_at": "2022-09-13T13:26:11.338296Z",
        "created_by": "admin",
        "address": "00:40:40:40:40:40",
        "is_startswith_pattern": true
    }
]
Human Readable Output

MAC adrress entry

address created_at created_by id is_startswith_pattern
00:50:50:50:50:50 2022-09-13T13:25:55.679624Z admin 1 true
00:40:40:40:40:40 2022-09-13T13:26:11.338296Z admin 2 true

gw-get-file-infected


Get a file from an uuid.
If there is no uuid, get all the files infected from a time interval.

Base Command

gw-get-file-infected

Input

Argument Name Description Required
timerange Set the lower timerange in minute based on the now keyword when uuid is not given
Default value to 60 minutes.
Optional
size Set the number of aggregate value that can be returned when uuid is not given
Get all the values by default.
Optional
uuid The uuid of the file to get. Optional
state The state of the files to get, in list, when uuid is not given
Default value to Infected,Suspicious. Possible values are: .
Optional

Context Output

Path Type Description
Gcenter.File.Infected String File infected
Command Example

!gw-get-file-infected timerange="1440"

Context Example
[
    {
        "Content": "",
        "ContentFormat": "text",
        "File": "malcore_b34fc6de9763e3640f93dda3f7a97470af6f009089bca588272a03807ae9f5bf_2022-12-12_18-21-40.zip",
        "FileID": "f956f5cd-bad2-4f9c-ab75-cc6b16e58873",
        "Type": "3"
    }
]
Human Readable Output

Files infected entry

Contents ContentsFormat File FileID Type
  text malcore_b34fc6de9763e3640f93dda3f7a97470af6f009089bca588272a03807ae9f5bf_2022-12-12_18-21-40.zip f956f5cd-bad2-4f9c-ab75-cc6b16e58873 3

Configuration parameters

  • ip — GCenter IP address (required)
  • version — GCenter Version
  • token — GCenter API token
  • credentials — GCenter username
  • check_cert — Check the TLS certificate

Commands (26)

  • gw-add-dga-list-entry

    Add dga whitelist/blacklist entry.

  • gw-add-ignore-asset-name

    Ignore asset name.

  • gw-add-ignore-kuser-ip

    Ignore kuser IP.

  • gw-add-ignore-kuser-name

    Ignore kuser name.

  • gw-add-ignore-mac-address

    Ignore mac address.

  • gw-add-malcore-list-entry

    Add malcore whitelist/blacklist entry.

  • gw-del-dga-list-entry

    Delete dga whitelist/blacklist entry.

  • gw-del-ignore-asset-name

    Delete an ignore asset ID.

  • gw-del-ignore-kuser-ip

    Delete an ignore kuser IP ID.

  • gw-del-ignore-kuser-name

    Delete an ignore kuser name ID.

  • gw-del-ignore-mac-address

    Delete an ignore mac address ID.

  • gw-del-malcore-list-entry

    Delete malcore whitelist/blacklist entry.

  • gw-es-query

    Get Elasticsearch data.

  • gw-es-wrapper

    Get Elasticsearch data using a wrapper.

  • gw-get-alert

    Get an alert by it's uid.

  • gw-get-dga-list-entry

    Get the dga whitelist/blacklist.

  • gw-get-file-infected

    Get a file from an uuid. If there is no uuid, get all the files infected from a time interval.

  • gw-get-ignore-asset-name

    Get all the ignored asset names.

  • gw-get-ignore-kuser-ip

    Get all the ignored kuser IP.

  • gw-get-ignore-kuser-name

    Get all the ignored kuser name.

  • gw-get-ignore-mac-address

    Get all the ignored mac addresses.

  • gw-get-malcore-list-entry

    Get the malcore whitelist/blacklist.

  • gw-list-alerts Deprecated

    List all alerts (Deprecated. use gw-es-wrapper command instead).

  • gw-send-malware

    Send malware.

  • gw-send-powershell

    Send powershell.

  • gw-send-shellcode

    Send shellcode.

"""Base Integration for Cortex XSOAR (aka Demisto)"""

from typing import Any

import urllib3
from CommonServerPython import *  # noqa # pylint: disable=unused-wildcard-import

from CommonServerUserPython import *  # noqa

# Disable insecure warnings
urllib3.disable_warnings()  # pylint: disable=no-member


class GwElasticQueryBuilder:
    """Represent an Elasticsearch query.

    Query is built using boolean clauses filter and must_not. Allows you to answer these questions:
      - List of files reconstructed by the Gcap over a 24H period.
      - List of files not reconstructed by the Gcap over a 24H period.
      - List of malcore alerts that does not have the flow_id field.
      - List of Sigflow alerts with a certain signature and originating from a certain interface.

    Aggregation query summarizes data as metrics, statistics, or other analytics. Allows you to answer these questions:
      - How many distinct files have been reconstructed by the Gcap.
      - List of distinct values of a field.
      - Count malcore alerts by interval of 1 hour.

    Class features:
      - Filter field exact value or value in list.
      - Filter existing/non existing field.
      - Filter timerange.
      - Filter document number.
      - Filter document field.
      - Date histogram aggregation.
      - Field cardinality aggregation.
      - Field terms aggregation.
    """

    def __init__(self):
        """Init class."""
        self.query = {"query": {}}  # type: ignore
        self.query["query"]["bool"] = {}
        self.query["query"]["bool"]["must_not"] = []
        self.query["query"]["bool"]["filter"] = []
        self.query["query"]["bool"]["filter"].append({})
        self.query["query"]["bool"]["filter"][0]["range"] = {}
        self.query["query"]["bool"]["filter"][0]["range"]["@timestamp"] = {}
        self.query["query"]["bool"]["filter"][0]["range"]["@timestamp"]["gte"] = "now-1d/d"
        self.query["query"]["bool"]["filter"][0]["range"]["@timestamp"]["lte"] = "now"

    def dumps(self, pretty: bool = False):
        """Get the query in json format.

        Args:
            pretty: True to indent the json string and False instead.

        Returns:
            Json string with indentation if pretty is True and without indentation if pretty is False.
        """
        if pretty:
            return json.dumps(self.query, indent=4)
        else:
            return json.dumps(self.query)

    def set_must_match(self, field: str, value: str) -> None:
        """Filter document that match the value using the term query.

        Args:
            field: Document key with format key1.key2.key3 for nested keys.
            value: Document key value that must match.
        """
        terms = {"term": {field: value}}
        self.query["query"]["bool"]["filter"].append(terms)

    def set_must_match_in_list(self, field: str, values: list) -> None:
        """Filter document that match one or more values provided in list using the terms query.

        Args:
            field: Document key with format key1.key2.key3 for nested keys.
            values: Document key values that must match.
        """
        terms = {"terms": {field: values}}
        self.query["query"]["bool"]["filter"].append(terms)

    def set_must_exists(self, field: str) -> None:
        """Filter document with existing key using the exists query.

        Args:
            field: Document key with format key1.key2.key3 for nested keys.
        """
        terms = {"exists": {"field": field}}
        self.query["query"]["bool"]["filter"].append(terms)

    def set_must_not_match(self, field: str, value: Union[str, list]) -> None:
        """Filter document that does not match the value or values using the term query.

        Args:
            field: Document key with format key1.key2.key3 for nested keys.
            value: Document key value that must not match, as a string or a list of strings.
        """
        if isinstance(value, str):
            value = [value]
        terms = {"terms": {field: value}}
        self.query["query"]["bool"]["must_not"].append(terms)

    def set_aggs_terms(self, field: str, size: int) -> None:
        """List and count each distinct values of a document field using the terms aggregation.

        Args:
            field: Document key with format key1.key2.key3 for nested keys.
            size: Number of distinct values to return. By default it will return the top ten values.

        Examples:
            List and count each event_type values::

                >>> query = GwElasticQueryBuilder()
                >>> query.set_size(0)
                >>> query.set_aggs_terms(field="event_type", size=10000)
                {
                    "event_type": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {
                                "key": "alert",
                                "doc_count": 176305
                            },
                            {
                                "key": "dns",
                                "doc_count": 14550
                            },
                            {
                                "key": "fileinfo",
                                "doc_count": 144
                            }
                        ]
                    }
                }
        """
        terms = {field: {"terms": {"field": field, "size": size}}}
        if "aggs" not in self.query:
            self.query["aggs"] = {}
        self.query["aggs"].update(terms)

    def set_size(self, size: int) -> None:
        """Filter the number of returned documents.

        It does not affect aggregation query.
        Set it to 0 when using aggregation query to avoid getting the query results
        in adition to the aggregation results.

        Args:
            size: Maximum number of returned documents. By default all documents are returned.
        """
        self.query["size"] = size  # type: ignore[assignment]

    def set_timerange(self, lower: Optional[Union[str, datetime]] = None, upper: Optional[Union[str, datetime]] = None) -> None:
        """Set the lower and upper timerange based on the now keyword.

        The unit for upper and lower relative timestamp are:
          - y: Years
          - M: Months
          - w: Weeks
          - d: Days
          - h: Hours
          - H: Hours
          - m: Minutes
          - s: Seconds

        Args:
            lower: Set the lower relative timestamp based on now or absolute timestamp based on datetime.
                    If set without the upper argument, the query lte field will be deleted.
                    Format: "(-/+)Xunit" ("+1h" to add an hour or "-1d" to substract 1 day) or datetime.utcnow().
            upper: Set the upper relative timestamp based on now or absolute timestamp based on datetime.
                    If set without the lower argument, the query gte field will be deleted.
                    Format: "(-/+)Xunit" ("+1h" to add an hour or "-1d" to substract 1 day) or datetime.utcnow().

        """
        if lower is None and upper is None:
            raise AttributeError("set_timerange take at least one argument between lower and upper: [ERROR]")
        timerange = self.query["query"]["bool"]["filter"][0]["range"]
        if isinstance(upper, str):
            timerange["@timestamp"]["lte"] = f"now{upper}"
        elif isinstance(upper, datetime):
            timerange["@timestamp"]["lte"] = upper.strftime("%Y-%m-%dT%H:%M:%S")
        elif upper is not None:
            raise TypeError("set_timerange upper argument only support str and datetime: [ERROR]")
        if isinstance(lower, str):
            timerange["@timestamp"]["gte"] = f"now{lower}"
        elif isinstance(lower, datetime):
            timerange["@timestamp"]["gte"] = lower.strftime("%Y-%m-%dT%H:%M:%S")
        elif lower is not None:
            raise TypeError("set_timerange lower argument only support str and datetime: [ERROR]")
        if lower is not None and upper is None:
            timerange["@timestamp"].pop("lte", None)
        elif upper is not None and lower is None:
            timerange["@timestamp"].pop("gte", None)


class GwAPIException(Exception):
    """A base class from which all other exceptions inherit.

    If you want to catch all errors that the gwapi_benedictine package might raise,
    catch this base exception.
    """


class GwRequests:
    """Allows to easily interact with HTTP server.

    Class features:
      - Get requests package wrapper.
      - Put requests package wrapper.
      - Post requests package wrapper.
      - Delete requests package wrapper.
    """

    PROXIES = {"http": "", "https": ""}

    def __init__(self, ip: str, headers: dict = {}, check_cert: bool = False, proxies: dict = None) -> None:
        """Init.

        Disable urllib3 warning. Allow unsecure ciphers.

        Args:
            ip: IP address of the HTTP server.
            check_cert: True to validate server certificate and False instead.
            proxies: Requests proxies. Default to no proxies.
        """
        self.index_values = ["suricata", "codebreaker", "malware", "netdata", "syslog", "machine_learning", "retrohunt", "iocs"]
        self.ip = ip
        self.headers = headers
        self.check_cert = check_cert
        if proxies is not None:
            self.PROXIES = proxies

    def _gen_request_kwargs(
        self,
        endpoint: str,
        data: dict,
        json_data: dict,
        params: dict,
        headers: dict,
        cookies: dict,
        redirects: bool,
        files: dict = None,
    ) -> dict:
        """Generate requests arguments.

        Args:
            endpoint: URL endpoint in format /XX/YY/ZZ.
            data: request data.
            json_data: Set to True if data is in json_data format and False instead.
            params: Set to True if data need to be send with the url and False instead.
            headers: Set to True if redirection is allowed and False instead.
            cookies: Set to True if redirection is allowed and False instead.
            redirects: Set to True if redirection is allowed and False instead.
            files: files to upload in multipart/form-data

        Returns:
            Return requests arguments in dictionnary format.
        """
        kwargs = {
            "url": f"https://{self.ip}{endpoint}",
            "headers": headers if headers else self.headers,
            "cookies": cookies,
            "verify": self.check_cert,
            "proxies": self.PROXIES,
            "allow_redirects": redirects,
            "data": data,
            "json": json_data,
            "params": params,
            "files": files,
        }
        return kwargs

    def _get(
        self,
        endpoint: str,
        data: dict = None,
        json_data: dict = None,
        params: dict = None,
        headers: dict = None,
        cookies: dict = None,
        redirects: bool = True,
    ) -> requests.Response:
        """Wrap the get requests.

        Same arguments as _gen_request_kwargs functions.

        Returns:
            Return a requests object with properties:

            - status_code
            - reason
            - headers
            - text
        """
        kwargs = self._gen_request_kwargs(
            endpoint=endpoint,
            data=data,  # type: ignore
            json_data=json_data,  # type: ignore
            params=params,  # type: ignore
            headers=headers,  # type: ignore
            cookies=cookies,  # type: ignore
            redirects=redirects,
        )
        return requests.get(**kwargs)

    def _post(
        self,
        endpoint: str,
        data: dict = None,
        json_data: dict = None,
        params: dict = None,
        headers: dict = None,
        cookies: dict = None,
        redirects: bool = True,
        files: dict = None,
    ) -> requests.Response:
        """Wrap the post requests.

        Same arguments as _gen_request_kwargs functions.

        Returns:
            Return a requests object with properties:

            - status_code
            - reason
            - headers
            - text
        """
        kwargs = self._gen_request_kwargs(
            endpoint=endpoint,
            data=data,  # type: ignore
            json_data=json_data,  # type: ignore
            params=params,  # type: ignore
            headers=headers,  # type: ignore
            cookies=cookies,  # type: ignore
            redirects=redirects,
            files=files,
        )
        return requests.post(**kwargs)

    def _put(
        self,
        endpoint: str,
        data: dict = None,
        json_data: dict = None,
        params: dict = None,
        headers: dict = None,
        cookies: dict = None,
        redirects: bool = True,
        files: dict = None,
    ) -> requests.Response:
        """Wrap the put requests.

        Same arguments as _gen_request_kwargs functions.

        Returns:
            Return a requests object with properties:

            - status_code
            - reason
            - headers
            - text
        """
        kwargs = self._gen_request_kwargs(
            endpoint=endpoint,
            data=data,  # type: ignore
            json_data=json_data,  # type: ignore
            params=params,  # type: ignore
            headers=headers,  # type: ignore
            cookies=cookies,  # type: ignore
            redirects=redirects,
            files=files,
        )
        return requests.put(**kwargs)

    def _delete(
        self,
        endpoint: str,
        data: dict = None,
        json_data: dict = None,
        params: dict = None,
        headers: dict = None,
        cookies: dict = None,
        redirects: bool = True,
    ) -> requests.Response:
        """Wrap the delete requests.

        Same arguments as _gen_request_kwargs functions.

        Returns:
            Return a requests object with properties:

            - status_code
            - reason
            - headers
            - text
        """
        kwargs = self._gen_request_kwargs(
            endpoint=endpoint,
            data=data,  # type: ignore
            json_data=json_data,  # type: ignore
            params=params,  # type: ignore
            headers=headers,  # type: ignore
            cookies=cookies,  # type: ignore
            redirects=redirects,
        )
        return requests.delete(**kwargs)


class GwClient(GwRequests):
    """Client class to interact with the service API."""

    def auth(self, user: str = None, password: str = None, token: str = None) -> None:
        """Authentication through the GCenter API.

        Args:
            user: GCenter WEBui username.
            password: GCenter WEBui password.
            token: GCenter API token.

        Raises:
            GwAPIException: If status_code != 200.
        """
        if user is None and password is None and token is None:
            raise AttributeError("A user/password or an API token must be provided: [ERROR]")
        elif (user is None and password is not None) or (user is not None and password is None):
            raise AttributeError("A user and a password must be provided: [ERROR]")
        if user is not None and password is not None:
            response = self._post(endpoint="/api/auth/login", json_data={"username": user, "password": password})
            if response.status_code == 200:
                demisto.info(f"Authentication on GCenter {self.ip} with user {user}: [OK]")
                self.headers["API-KEY"] = response.json()["token"]
            else:
                raise GwAPIException(
                    f"Authentication on GCenter {self.ip} with user {user}: [FAILED]",
                    response.text,
                    response.status_code,
                    response.reason,
                )
        else:
            self.headers["API-KEY"] = token

    def is_authenticated(self) -> bool:
        """Return True if authenticated and False instead.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(endpoint="/api/status/healthchecks/")
        if response.status_code == 200:
            demisto.info(f"Get healthchecks on GCenter {self.ip}: [OK]")
            return True
        else:
            demisto.error(
                f"Get healthchecks on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )
            return False

    def list_alerts(self) -> dict:
        """Get the latest elasticsearch alerts sorted by date
        in descending order (most recent first in the list).

        Returns:
            Alerts lists.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(endpoint="/api/raw-alerts/")
        if response.status_code == 200:
            demisto.info(f"List alerts on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"List alerts on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def get_alert(self, uid: str) -> dict:
        """Get an elasticsearch alert by uid.

        Args:
            uid: An alert uuid.

        Returns:
            The alert document.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(endpoint=f"/api/raw-alerts/{uid}/")
        if response.status_code == 200:
            demisto.info(f"Get alert {uid} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Get alert {uid} on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def get_malcore_list_entry(self, ltype: str) -> list:
        """Get malcore whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.

        Returns:
            Malcore list

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(
            endpoint=f"/api/malcore/{ltype}-list/",
        )
        if response.status_code == 200:
            demisto.info(f"Get malcore {ltype}lists on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get malcore {ltype}lists on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def add_malcore_list_entry(self, ltype: str, sha256: str, comment: str = None, threat: str = None) -> dict:  # noqa: E501
        """Add malcore whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.
            sha256: Sha256 to be added.

        Returns:
            sha256 added to the whitelist/blacklist.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(
            endpoint=f"/api/malcore/{ltype}-list/", json_data={"sha256": sha256, "comment": comment, "threat": threat}
        )
        if response.status_code == 201:
            demisto.info(f"Add {ltype} list with sha256 {sha256} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Add {ltype} list with sha256 {sha256} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_malcore_list_entry(self, ltype: str, sha256: str) -> None:
        """Del malcore whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.
            sha256: Sha256 to be deleted.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/malcore/{ltype}-list/{sha256}")
        if response.status_code == 204:
            demisto.info(f"Delete {ltype} list with sha256 {sha256} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete {ltype} list with sha256 {sha256} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def get_dga_list_entry(self, ltype: str) -> list:  # noqa: E501
        """Get the domain name whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.

        Returns:
            Domain list whitelist/blacklist.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(
            endpoint=f"/api/dga-detection/{ltype}-list/",
        )
        if response.status_code == 200:
            demisto.info(f"Get dga {ltype}lists on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get dga {ltype}lists on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def add_dga_list_entry(self, ltype: str, domain: str, comment: str = None) -> dict:  # noqa: E501
        """Add malcore whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.
            domain: Domain name to be added.

        Returns:
            Domain added to the whitelist/blacklist.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(endpoint=f"/api/dga-detection/{ltype}-list/", json_data={"domain_name": domain, "comment": comment})
        if response.status_code == 201:
            demisto.info(f"Add {ltype} list with domain {domain} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Add {ltype} list with domain {domain} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_dga_list_entry(self, ltype: str, domain: str) -> None:
        """Del malcore whitelist/blacklist entry.

        Args:
            ltype: List type either white or black.
            domain: Domain name to be deleted.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/dga-detection/{ltype}-list/{domain}")
        if response.status_code == 204:
            demisto.info(f"Delete {ltype} list with domain {domain} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete {ltype} list with domain {domain} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def get_es_query(self, index: str, query: str) -> list:
        """Get results of an elasticsearch query.

        Args:
            index: Index name between suricata, codebreaker, malware,
                    netdata, syslog, machine_learning, retrohunt, iocs.
            query: Query in a dictionary format.

        Returns:
            The elacticsearch response.

        Raises:
            GwAPIException: If status_code != 200.
            TypeError: If index value doesn't exist.
        """

        if index not in self.index_values:
            raise TypeError(f"Index value must be between: {self.index_values}")
        response = self._post(endpoint=f"/api/data/es/search/?index={index}", json_data=json.loads(query))
        if response.status_code == 200:
            demisto.info(f"Get elasticsearch results for index {index} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Get elasticsearch results for index {index} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def get_es_wrapper(
        self,
        index: str,
        timerange: str,
        size: str,
        aggs_term: str = None,
        must_match: str = None,
        must_exists: str = None,
        formatted: str = None,
    ) -> dict:
        """Get results of an elasticsearch query.

        Args:
            index: Index name between suricata, codebreaker, malware,
                    netdata, syslog, machine_learning, retrohunt, iocs
            aggs_term: List and count each distinct values of a document field using the terms aggregation
                        If aggs_term is empty list hits value
            must_match: Filter document that match the value using the term query
            must_exists: Filter document with existing key using the exists query
            timerange: Set the lower timerange in hour based on the now keyword
            formatted: True to get the list of aggregation value False to get entire response
            size : Set the number of aggregate or hits value that can be returned

        Returns:
            The elacticsearch response.

        Raises:
            GwAPIException: If status_code != 200.
            TypeError: If index value doesn't exist.
        """

        aggs_term = aggs_term.replace(" ", "").split(",") if aggs_term else []
        must_exists = must_exists.replace(" ", "").split(",") if must_exists else []
        must_match = must_match.replace(" ", "").split(",") if must_match else {}
        must_match = dict(element.split("=") for element in must_match) if must_match else {}

        try:
            size_converted = int(size)
        except ValueError:
            raise ValueError("Size value must be a number")
        hits_size = 0 if aggs_term else size_converted
        query_builder = GwElasticQueryBuilder()
        query_builder.set_size(hits_size)

        for field in aggs_term:
            query_builder.set_aggs_terms(field=field, size=size_converted)
        for field in must_exists:
            query_builder.set_must_exists(field=field)
        for field in must_match:
            query_builder.set_must_match(field=field, value=must_match[field])
        if timerange:
            query_builder.set_timerange(lower=f"-{timerange}h")

        if index not in self.index_values:
            raise TypeError(f"Index value must be between: {self.index_values}")
        response = self._post(endpoint=f"/api/data/es/search/?index={index}", json_data=json.loads(query_builder.dumps()))

        if response.status_code == 200:
            demisto.info(f"Get elasticsearch results for index {index} on GCenter {self.ip}: [OK]")
            response_formatted = response.json()
            if formatted == "True" and aggs_term:
                response_formatted = {}
                for agg_term in aggs_term:
                    response_formatted[agg_term] = [
                        bucket["key"] for bucket in response.json()["aggregations"][agg_term]["buckets"]
                    ]
            return response_formatted
        else:
            raise GwAPIException(
                f"Get elasticsearch results for index {index} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def get_file_infected(self, timerange: str = None, size: str = None, state: str = None, uuid: str = None) -> list:  # noqa: E501
        """Get a file from an uuid.
            If there is no uuid, get all the files infected from a time interval.

        Args:
            uuid: The uuid of the file to get
            state: The state of the files to get, in list
            timerange: Set the lower timerange in minute based on the now keyword
            size: Set the number of aggregate value that can be returned

        Returns:
            Asset ignored.

        Raises:
            GwAPIException: If status_code != 200.
        """

        if uuid:
            uuids = [uuid]
        else:
            value_state = state.replace(" ", "").split(",") if state else ["Infected", "Suspicious"]
            try:
                size_converted = int(size) if size else 10000
            except ValueError:
                raise ValueError("Size value must be a number")
            if timerange is None:
                timerange = "60"
            query = GwElasticQueryBuilder()
            query.set_size(0)
            query.set_aggs_terms(field="uuid", size=size_converted)
            query.set_must_not_match(field="fileinfo.filename", value="/ls")
            query.set_must_match(field="state", value="Infected")
            query.set_must_match_in_list(field="state", values=value_state)
            query.set_must_match(field="event_type", value="malware")
            query.set_timerange(lower=f"-{timerange}m")
            response = self._post(endpoint="/api/data/es/search/?index=malware", json_data=json.loads(query.dumps()))
            if response.status_code == 200:
                demisto.info(f"Get ES uuid on GCenter {self.ip}: [OK]")
            else:
                raise GwAPIException(
                    f"Get alerts uuid on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
                )
            uuids = [bucket["key"] for bucket in response.json()["aggregations"]["uuid"]["buckets"]]
        files = []
        for uuid in uuids:
            response = self._get(
                endpoint=f"/api/raw-alerts/{uuid}/file",
            )
            if response.status_code == 200:
                filename = response.headers.get("Content-Disposition", "").split("filename=")[1]
                content = response.content
                files.append(fileResult(filename, content))
            else:
                raise GwAPIException(
                    f"Get file on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
                )

        demisto.info(f"Get files infected on GCenter {self.ip}: [OK]")
        return files

    def get_ignore_asset_name(self) -> list:  # noqa: E501
        """Get ignore asset name.

        Returns:
            Asset ignored.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(
            endpoint="/api/ignore-lists/asset-names/",
        )
        if response.status_code == 200:
            demisto.info(f"Get ignore asset on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get ignore asset on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def get_ignore_mac_address(self) -> list:
        """Get ignore mac address.

        Returns:
            Asset ignored.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(
            endpoint="/api/ignore-lists/mac-addresses/",
        )
        if response.status_code == 200:
            demisto.info(f"Get ignore mac address on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get ignore mac address on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def get_ignore_kuser_ip(self) -> list:
        """Get ignore Kerberos ip.

        Returns:
            Kerberos ip ignored.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(
            endpoint="/api/ignore-lists/kuser-ips/",
        )
        if response.status_code == 200:
            demisto.info(f"Get ignore kerberos ips on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get ignore kerberos ips on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def get_ignore_kuser_name(self) -> list:  # noqa: E501
        """Get ignore Kerberos username.

        Returns:
            Kerberos ignored.

        Raises:
            GwAPIException: If status_code != 200.
        """
        response = self._get(endpoint="/api/ignore-lists/kuser-names/")
        if response.status_code == 200:
            demisto.info(f"Get ignore kerberos username on GCenter {self.ip}: [OK]")
            return response.json()["results"]
        else:
            raise GwAPIException(
                f"Get ignore kerberos username on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def ignore_asset_name(self, name: str, start: bool = True, end: bool = True) -> dict:  # noqa: E501
        """Ignore asset name.

        Args:
            name: Asset name.
            start: Will be ignored if they start with this name.
            end: Will be ignored if they end with this name.

        Returns:
            Asset ignored.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(
            endpoint="/api/ignore-lists/asset-names/",
            json_data={"name": name, "is_startswith_pattern": start, "is_endswith_pattern": end},
        )
        if response.status_code == 201:
            demisto.info(f"Ignore asset {name} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Ignore asset {name} on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def ignore_mac_address(self, mac: str, start: bool = True) -> dict:
        """Ignore mac address.

        Args:
            mac: Mac address name.
            start: Will be ignored if they start with this name.

        Returns:
            Asset ignored.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(
            endpoint="/api/ignore-lists/mac-addresses/", json_data={"address": mac, "is_startswith_pattern": start}
        )
        if response.status_code == 201:
            demisto.info(f"Ignore mac address {mac} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Ignore mac address {mac} on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def ignore_kuser_ip(self, ip: str) -> dict:
        """Ignore Kerberos ip.

        Args:
            ip: Kerberos ip.

        Returns:
            Kerberos ip ignored.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(endpoint="/api/ignore-lists/kuser-ips/", json_data={"ip": ip})
        if response.status_code == 201:
            demisto.info(f"Ignore kerberos ip {ip} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Ignore kerberos ip {ip} on GCenter {self.ip}: [FAILED]", response.text, response.status_code, response.reason
            )

    def ignore_kuser_name(self, name: str, start: bool = True, end: bool = True) -> dict:  # noqa: E501
        """Ignore Kerberos username.

        Args:
            name: Kerberos username.
            start: Will be ignored if they start with this name.
            end: Will be ignored if they end with this name.

        Returns:
            Kerberos ignored.

        Raises:
            GwAPIException: If status_code != 201.
        """
        response = self._post(
            endpoint="/api/ignore-lists/kuser-names/",
            json_data={"name": name, "is_startswith_pattern": start, "is_endswith_pattern": end},
        )
        if response.status_code == 201:
            demisto.info(f"Ignore kerberos username {name} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Ignore kerberos username {name} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_ignore_asset_name(self, ignore_id: int) -> None:  # noqa: E501
        """Delete an ignore asset name.

        Args:
            ignore_id: Ignore list identifier.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/ignore-lists/asset-names/{ignore_id}/")
        if response.status_code == 204:
            demisto.info(f"Delete an ignore asset {ignore_id} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete an ignore asset {ignore_id} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_ignore_mac_address(self, ignore_id: int) -> None:
        """Delete an ignore mac address.

        Args:
            ignore_id: Ignore list identifier.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/ignore-lists/mac-addresses/{ignore_id}/")
        if response.status_code == 204:
            demisto.info(f"Delete an ignore mac address {ignore_id} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete an ignore mac address {ignore_id} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_ignore_kuser_ip(self, ignore_id: int) -> None:
        """Delete an ignore Kerberos ip.

        Args:
            ignore_id: Ignore list identifier.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/ignore-lists/kuser-ips/{ignore_id}/")
        if response.status_code == 204:
            demisto.info(f"Delete an ignore kerberos ip {ignore_id} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete an ignore kerberos ip {ignore_id} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def del_ignore_kuser_name(self, ignore_id: int) -> None:  # noqa: E501
        """Delete an ignore Kerberos username.

        Args:
            ignore_id: Ignore list identifier.

        Raises:
            GwAPIException: If status_code != 204.
        """
        response = self._delete(endpoint=f"/api/ignore-lists/kuser-names/{ignore_id}/")
        if response.status_code == 204:
            demisto.info(f"Delete an ignore kerberos username {ignore_id} on GCenter {self.ip}: [OK]")
        else:
            raise GwAPIException(
                f"Delete an ignore kerberos username {ignore_id} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def send_malware(self, filename: str, file_id: str) -> dict:
        """Send file to the GScan malcore analysis.

        Args:
            filename: Filename to be sent.
            file_id: The file entry id.

        Returns:
            Gscan analysis report.

        Raises:
            GwAPIException: If status_code != 201.
        """
        file = demisto.getFilePath(file_id)
        with open(file.get("path"), "rb") as fo:
            response = self._post(endpoint="/api/gscan/malcore/", files={"file": (filename, fo)})
        if response.status_code == 201:
            demisto.info(f"Send malcore file {filename} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Send malcore file {filename} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def send_shellcode(self, filename: str, file_id: str, deep: bool = False, timeout: int = None) -> dict:
        """Send file to the GScan shellcode analysis.

        Args:
            filename: Filename to be sent.
            file_id: The file entry id.
            deep: True to enabled deep scan and False instead.
            timeout: Deep scan timeout.

        Returns:
            Gscan analysis report.

        Raises:
            GwAPIException: If status_code != 201.
        """
        file = demisto.getFilePath(file_id)
        with open(file.get("path"), "rb") as fo:
            response = self._post(
                endpoint="/api/gscan/shellcode/", files={"file": (filename, fo), "deep": deep, "timeout": timeout}
            )
        if response.status_code == 201:
            demisto.info(f"Send shellcode file {filename} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Send shellcode file {filename} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )

    def send_powershell(self, filename: str, file_id: str) -> dict:
        """Send file to the GScan powershell analysis.

        Args:
            filename: Filename to be sent.
            file_id: The file entry id.

        Returns:
            Gscan analysis report.

        Raises:
            GwAPIException: If status_code != 201.
        """
        file = demisto.getFilePath(file_id)
        with open(file.get("path"), "rb") as fo:
            response = self._post(endpoint="/api/gscan/powershell/", files={"file": (filename, fo)})
        if response.status_code == 201:
            demisto.info(f"Send powershell file {filename} on GCenter {self.ip}: [OK]")
            return response.json()
        else:
            raise GwAPIException(
                f"Send powershell file {filename} on GCenter {self.ip}: [FAILED]",
                response.text,
                response.status_code,
                response.reason,
            )


def test_module(client: GwClient) -> str:  # noqa: E501
    """Tests API connectivity and authentication command.

    Args:
        client: Client to interact with the GCenter.

    Returns:
        'Authentication successful' when the GCenter connection works.
        'Authentication error' when the GCenter connection doesn't works.
    """
    if client.is_authenticated():
        return "ok"
    else:
        return "Authentication error, please check ip/user/password/token: [ERROR]"


def gw_list_alerts(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Get the latest elasticsearch alerts sorted by date in
    descending order (most recent first in the list) command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Alert.List" prefix.
    """
    result = client.list_alerts()
    readable_result = tableToMarkdown("Elasticsearch alerts list", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Alert.List",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_alert(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Get an elasticsearch alert by uid command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Alert.Single" prefix.
    """
    result = client.get_alert(
        uid=args.get("uid")  # type: ignore
    )
    readable_result = tableToMarkdown("Elasticsearch alert entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Alert.Single",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_malcore_list_entry(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get the malcore whitelist/blacklist

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Malcore.List" prefix.
    """
    result = client.get_malcore_list_entry(ltype=args.get("type"))  # type: ignore
    readable_result = tableToMarkdown("Malcore whitelist/blacklist entries", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Malcore.List",
        outputs_key_field="sha256",
        outputs=result,
        raw_response=result,
    )


def gw_add_malcore_list_entry(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Add malcore whitelist/blacklist entry command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Malcore" prefix.
    """
    ltype = args.get("type")
    result = client.add_malcore_list_entry(
        ltype=ltype,  # type: ignore
        sha256=args.get("sha256"),  # type: ignore
        comment=args.get("comment", "added by cortex"),  # type: ignore
        threat=args.get("threat", "unknown"),  # type: ignore
    )
    readable_result = tableToMarkdown(f"Malcore {ltype}list entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Malcore",
        outputs_key_field="sha256",
        outputs=result,
        raw_response=result,
    )


def gw_del_malcore_list_entry(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Del malcore whitelist/blacklist entry command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Malcore" prefix.
    """
    client.del_malcore_list_entry(
        ltype=args.get("type"),  # type: ignore
        sha256=args.get("sha256"),  # type: ignore
    )
    return CommandResults(
        readable_output=None, outputs_prefix="GCenter.Malcore", outputs_key_field=None, outputs=None, raw_response=None
    )


def gw_get_dga_list_entry(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get dga whitelist/blacklist
    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Dga.List" prefix.
    """
    result = client.get_dga_list_entry(
        ltype=args.get("type"),  # type: ignore
    )
    readable_result = tableToMarkdown("DGA whitelist/blacklist entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Dga.List",
        outputs_key_field="domain_name",
        outputs=result,
        raw_response=result,
    )


def gw_add_dga_list_entry(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Add dga whitelist/blacklist entry command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Dga" prefix.
    """
    result = client.add_dga_list_entry(
        ltype=args.get("type"),  # type: ignore
        domain=args.get("domain"),  # type: ignore
        comment=args.get("comment", "added by cortex"),  # type: ignore
    )
    readable_result = tableToMarkdown("DGA whitelist/blacklist entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Dga",
        outputs_key_field="domain_name",
        outputs=result,
        raw_response=result,
    )


def gw_del_dga_list_entry(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Del dga whitelist/blacklist entry command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Dga" prefix.
    """
    client.del_dga_list_entry(
        ltype=args.get("type"),  # type: ignore
        domain=args.get("domain"),  # type: ignore
    )
    return CommandResults(
        readable_output=None, outputs_prefix="GCenter.Dga", outputs_key_field=None, outputs=None, raw_response=None
    )


def gw_es_query(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Get results of an elasticsearch query command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Elastic" prefix.
    """
    result = client.get_es_query(
        index=args.get("index"),  # type: ignore
        query=args.get("query"),  # type: ignore
    )
    readable_result = tableToMarkdown("Elasticsearch query result", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Elastic",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_es_wrapper(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get results of an elasticsearch query command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Elastic.Wrapper" prefix.
    """
    result = client.get_es_wrapper(
        index=args.get("index"),  # type: ignore
        aggs_term=args.get("aggs_term"),  # type: ignore
        must_match=args.get("must_match"),  # type: ignore
        must_exists=args.get("must_exists"),  # type: ignore
        timerange=args.get("timerange"),  # type: ignore
        formatted=args.get("formatted"),  # type: ignore
        size=args.get("size"),  # type: ignore
    )
    readable_result = tableToMarkdown("Elasticsearch wrapper result", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Elastic.Wrapper",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_get_file_infected(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get a file from an uuid.
        If there is no uuid, get all the files infected from a time interval.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.FileInfected.List" prefix.
    """
    result = client.get_file_infected(
        uuid=args.get("uuid"),  # type: ignore
        state=args.get("state"),  # type: ignore
        timerange=args.get("timerange"),  # type: ignore
        size=args.get("size"),  # type: ignore
    )
    readable_result = tableToMarkdown("Files infected entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.File",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_ignore_asset_name(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get all the ignored assets name command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.AssetName.List" prefix.
    """
    result = client.get_ignore_asset_name()
    readable_result = tableToMarkdown("Asset name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.AssetName.List",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_ignore_kuser_ip(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get all the ignored Kerberos ips command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserIP.List" prefix.
    """
    result = client.get_ignore_kuser_ip()
    readable_result = tableToMarkdown("Kuser IP entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserIP.List",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_ignore_kuser_name(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get all the ignored Kerberos username command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserName.List" prefix.
    """
    result = client.get_ignore_kuser_name()
    readable_result = tableToMarkdown("Kuser name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserName.List",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_get_ignore_mac_address(client: GwClient, args: Optional[dict[Any, Any]]) -> CommandResults:  # noqa: E501
    """Get all the ignored mac addresses command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.MacAddress.List" prefix.
    """
    result = client.get_ignore_mac_address()
    readable_result = tableToMarkdown("MAC adrress entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.MacAddress.List",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_add_ignore_asset_name(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Ignore asset name command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.AssetName" prefix.
    """
    result = client.ignore_asset_name(
        name=args.get("name"),  # type: ignore
        start=args.get("start"),  # type: ignore
        end=args.get("end"),  # type: ignore
    )
    readable_result = tableToMarkdown("Asset name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.AssetName",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_add_ignore_kuser_ip(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Ignore Kerberos ip command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserIP" prefix.
    """
    result = client.ignore_kuser_ip(
        ip=args.get("ip")  # type: ignore
    )
    readable_result = tableToMarkdown("Kuser IP entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserIP",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_add_ignore_kuser_name(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Ignore Kerberos username command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserName" prefix.
    """
    result = client.ignore_kuser_name(
        name=args.get("name"),  # type: ignore
        start=args.get("start"),  # type: ignore
        end=args.get("end"),  # type: ignore
    )
    readable_result = tableToMarkdown("Kuser name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserName",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_add_ignore_mac_address(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Ignore mac address command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore" prefix.
    """
    result = client.ignore_mac_address(
        mac=args.get("mac"),  # type: ignore
        start=args.get("start"),  # type: ignore
    )
    readable_result = tableToMarkdown("MAC adrress entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.MacAddress",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_del_ignore_asset_name(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Delete ignore asset name command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.AssetName" prefix.
    """
    result = client.del_ignore_asset_name(
        ignore_id=int(args.get("ignore_id"))  # type: ignore
    )
    readable_result = tableToMarkdown("Asset name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.AssetName",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_del_ignore_kuser_ip(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Delete ignore Kerberos ip command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserIP" prefix.
    """
    result = client.del_ignore_kuser_ip(
        ignore_id=int(args.get("ignore_id"))  # type: ignore
    )
    readable_result = tableToMarkdown("Kuser IP entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserIP",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_del_ignore_kuser_name(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Delete ignore Kerberos username command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.KuserName" prefix.
    """
    result = client.del_ignore_kuser_name(
        ignore_id=int(args.get("ignore_id"))  # type: ignore
    )
    readable_result = tableToMarkdown("Kuser name entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.KuserName",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_del_ignore_mac_address(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Delete ignore mac address command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Ignore.MacAddress" prefix.
    """
    result = client.del_ignore_mac_address(
        ignore_id=int(args.get("ignore_id"))  # type: ignore
    )
    readable_result = tableToMarkdown("MAC address entry", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Ignore.MacAddress",
        outputs_key_field=None,
        outputs=result,
        raw_response=result,
    )


def gw_send_malware(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Send file to the GScan malcore analysis.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Gscan.Malware" prefix.
    """
    result = client.send_malware(
        filename=args.get("filename"),  # type: ignore
        file_id=args.get("file_id"),  # type: ignore
    )
    readable_result = tableToMarkdown("Malcore analysis result", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Gscan.Malware",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_send_powershell(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Send file to the GScan shellcode analysis command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Gscan.Powershell" prefix.
    """
    result = client.send_powershell(
        filename=args.get("filename"),  # type: ignore
        file_id=args.get("file_id"),  # type: ignore
    )
    readable_result = tableToMarkdown("Powershell analysis result", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Gscan.Powershell",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def gw_send_shellcode(client: GwClient, args: dict[str, Any]) -> CommandResults:  # noqa: E501
    """Send file to the GScan powershell analysis command.

    Args:
        client: Client to interact with the GCenter.
        args: Command arguments.

    Returns:
        CommandResults object with the "GCenter.Gscan.Shellcode" prefix.
    """
    result = client.send_shellcode(
        filename=args.get("filename"),  # type: ignore
        file_id=args.get("file_id"),  # type: ignore
        deep=args.get("deep"),  # type: ignore
        timeout=int(args.get("timeout")),  # type: ignore
    )
    readable_result = tableToMarkdown("Shellcode analysis result", result)
    return CommandResults(
        readable_output=readable_result,
        outputs_prefix="GCenter.Gscan.Shellcode",
        outputs_key_field="id",
        outputs=result,
        raw_response=result,
    )


def main() -> None:
    """Main function, parses params and runs command functions."""

    params = demisto.params()
    command = demisto.command()
    args = demisto.args()

    ip = params.get("ip")
    token = params.get("token", None)
    user = params.get("credentials", {}).get("identifier", None)
    password = params.get("credentials", {}).get("password", None)
    check_cert = params.get("check_cert", False)

    demisto.debug(f"Command being called is {command}")
    try:
        client = GwClient(ip=ip, check_cert=check_cert)
        client.auth(user=user if user != "" else None, password=password if password != "" else None, token=token)
        if command == "test-module":
            return_results(test_module(client=client))
        elif command == "gw-list-alerts":
            return_results(gw_list_alerts(client=client, args=args))
        elif command == "gw-get-alert":
            return_results(gw_get_alert(client=client, args=args))
        elif command == "gw-get-malcore-list-entry":
            return_results(gw_get_malcore_list_entry(client=client, args=args))
        elif command == "gw-add-malcore-list-entry":
            return_results(gw_add_malcore_list_entry(client=client, args=args))
        elif command == "gw-del-malcore-list-entry":
            return_results(gw_del_malcore_list_entry(client=client, args=args))
        elif command == "gw-get-dga-list-entry":
            return_results(gw_get_dga_list_entry(client=client, args=args))
        elif command == "gw-add-dga-list-entry":
            return_results(gw_add_dga_list_entry(client=client, args=args))
        elif command == "gw-del-dga-list-entry":
            return_results(gw_del_dga_list_entry(client=client, args=args))
        elif command == "gw-es-query":
            return_results(gw_es_query(client=client, args=args))
        elif command == "gw-es-wrapper":
            return_results(gw_es_wrapper(client=client, args=args))
        elif command == "gw-get-file-infected":
            return_results(gw_get_file_infected(client=client, args=args))
        elif command == "gw-get-ignore-asset-name":
            return_results(gw_get_ignore_asset_name(client=client, args=args))
        elif command == "gw-get-ignore-kuser-ip":
            return_results(gw_get_ignore_kuser_ip(client=client, args=args))
        elif command == "gw-get-ignore-kuser-name":
            return_results(gw_get_ignore_kuser_name(client=client, args=args))
        elif command == "gw-get-ignore-mac-address":
            return_results(gw_get_ignore_mac_address(client=client, args=args))
        elif command == "gw-add-ignore-asset-name":
            return_results(gw_add_ignore_asset_name(client=client, args=args))
        elif command == "gw-add-ignore-kuser-ip":
            return_results(gw_add_ignore_kuser_ip(client=client, args=args))
        elif command == "gw-add-ignore-kuser-name":
            return_results(gw_add_ignore_kuser_name(client=client, args=args))
        elif command == "gw-add-ignore-mac-address":
            return_results(gw_add_ignore_mac_address(client=client, args=args))
        elif command == "gw-del-ignore-asset-name":
            return_results(gw_del_ignore_asset_name(client=client, args=args))
        elif command == "gw-del-ignore-kuser-ip":
            return_results(gw_del_ignore_kuser_ip(client=client, args=args))
        elif command == "gw-del-ignore-kuser-name":
            return_results(gw_del_ignore_kuser_name(client=client, args=args))
        elif command == "gw-del-ignore-mac-address":
            return_results(gw_del_ignore_mac_address(client=client, args=args))
        elif command == "gw-send-malware":
            return_results(gw_send_malware(client=client, args=args))
        elif command == "gw-send-powershell":
            return_results(gw_send_powershell(client=client, args=args))
        elif command == "gw-send-shellcode":
            return_results(gw_send_shellcode(client=client, args=args))
    except Exception as e:
        return_error(f"Failed to execute {command} command.\nError: {e!s}")


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()