NetscoutArborSightline

DDoS protection and network visibility.

Network Security · Netscout Arbor Sightline

Details

IDNetscoutArborSightline
ProviderNetscout Systems
CategoryNetwork Security
From Version5.5.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

DDoS protection and network visibility.
This integration was integrated and tested with version 9.3 of Netscout Arbor Sightline.

Configure NetscoutArborSightline in Cortex

Parameter Description Required
Incident type   False
Server URL (e.g., https://….)   True
API Key If using 6.0.2 or lower version, put your API Key in the Password field, leave the User field empty. False
Fetch incidents   False
First fetch time First fetch query (<number> <time unit>, e.g., 12 hours, 7 days or ISO format 2020-01-01T10:00:00). Maximal number of past events to fetch is 10,000. False
Fetch Limit Maximum number of alerts per fetch. Default is 50, maximum is 100. False
Alert Class Alert class to filter by. Only one class can be configured at a time. If none is chosen, all classes will be fetched. False
Alert Type Alert type to filter by. Only one type can be configured at a time. If none is chosen, all types will be fetched. False
Minimal importance to fetch Minimal alert importance to filter by. If none or Low is chosen, all importances will be fetched. False
Event Status Alert status to filter by. If none is chosen, all statuses will be fetched. False
Trust any certificate (not secure)   False
Use system proxy settings   False

Commands

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

na-sightline-alert-annotation-list


Lists the collection of annotations for a given alert.

Base Command

na-sightline-alert-annotation-list

Input

Argument Name Description Required
alert_id Alert ID to list the annotation for. Can be obtained from the na-sightline-alert-list command. Required
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.AlertAnnotation.AlertID String The alert ID of the annotation.
NASightline.AlertAnnotation.Annotations.added Date Date and time the annotation was made.
NASightline.AlertAnnotation.Annotations.author String User ID of the annotation author.
NASightline.AlertAnnotation.Annotations.id String The ID of the annotation.
NASightline.AlertAnnotation.Annotations.text String Annotation text.
NASightline.AlertAnnotation.Annotations.type String Type of the returned object.
NASightline.AlertAnnotation.Annotations.relationships Unknown Relationships of the annotation (only visible when extending the data).

Command Example

!na-sightline-alert-annotation-list alert_id="2009" limit=2

Context Example

{
    "NASightline": {
        "AlertAnnotation": {
            "AlertID": "2009",
            "Annotations": [
                {
                    "added": "2021-03-29T18:18:13+00:00",
                    "author": "auto-annotation",
                    "id": "886",
                    "text": "Flowspec mitigation 'testMit2' started",
                    "type": "alert_annotation"
                },
                {
                    "added": "2021-03-07T19:09:05+00:00",
                    "author": "auto-annotation",
                    "id": "797",
                    "text": "Flowspec mitigation 'testMit' started",
                    "type": "alert_annotation"
                },
                {
                    "added": "2021-03-07T11:00:02+00:00",
                    "author": "auto-annotation",
                    "id": "795",
                    "text": "This alert was generated due to fast flood detection. The \"Total Traffic\" host alert signature has been triggered at router \"Traffic-PCAP-CentOS\". (expected rate: 5 bps/50.00 Kpps, observed rate: 11 bps/0 pps)",
                    "type": "alert_annotation"
                }
            ]
        }
    }
}

Human Readable Output

Alert 2009 annotations

added author id text type
2021-03-29T18:18:13+00:00 auto-annotation 886 Flowspec mitigation ‘testMit2’ started alert_annotation
2021-03-07T19:09:05+00:00 auto-annotation 797 Flowspec mitigation ‘testMit’ started alert_annotation
2021-03-07T11:00:02+00:00 auto-annotation 795 This alert was generated due to fast flood detection. The “Total Traffic” host alert signature has been triggered at router “Traffic-PCAP-CentOS”. (expected rate: 5 bps/50.00 Kpps, observed rate: 11 bps/0 pps) alert_annotation

na-sightline-alert-list


List all alerts. When an alert ID is given, only the relevant alert will be fetched.

Base Command

na-sightline-alert-list

Input

Argument Name Description Required
alert_id Alert ID. If given, all other arguments will be ignored. Optional
alert_class Alert class to filter by. Possible values are: bgp, cloudsignal, data, dos, smart, system_error, system_event, tms, traffic. Optional
alert_type Alert type to filter by. Possible values are: autoclassify_restart, bgp_down, bgp_hijack, bgp_instability, bgp_trap, blob_thresh, cloud_mit_request, cloudsignal_fault, collector_down, collector_start, config_change, device_system_error, dns_baseline, dos, dos_host_detection, dos_mo_profiled, dos_profiled_network, dos_profiled_router, fingerprint_thresh, flexible_license_error, flow_down, flow_missing, gre_down, hw_failure, smart_thresh, interface_usage, nucleus_fault, routing_failover, routing_interface_failover, service_thresh, smart_thresh, snmp_down, spcomm_failure, tms_fault, traffic_auto_mitigation. Optional
classification Alert classification to filter by. Possible values are: Possible Attack, False Positive, Verified Attack, Network Failure, Flash Crowd, Trivial. Optional
importance Alert importance to filter by. For more complex operators use the ‘importance_operator’ argument. Possible values are: Low, Medium, High. Optional
importance_operator The operator to apply on the importance argument (“>” is greater than, “<” is less than, “=” is equal to). For example: if the chosen operator is “>” and the chosen importance is “Low”, only alerts with and importance greater than Low will be fetched. Possible values are: <, =, >. Optional
ongoing Alert status to filter by. If not set, all statuses will be fetched. Possible values are: true, false. Optional
start_time Alert start time to filter by. For more complex operators use the ‘start_time_operator’ argument. Optional
start_time_operator The operator to apply on the “start_time” argument. For example: if the chosen operator is “>” and the given time is “2020-12-01T13:15:00”, only alerts with a starting time greater than “2020-12-01T13:15:00” will be fetched. Possible values are: =, >, <. Optional
stop_time Alert stop time to filter by. For more complex operators use the ‘stop_time_operator’ argument. Optional
stop_time_operator The operator to apply on the “stop_time” argument. For example: if the chosen operator is “>” and the given time is “2020-12-01T13:15:00”, only alerts with a stopping time greater than “2020-12-01T13:15:00” will be fetched. Possible values are: =, >, <. Optional
managed_object_id ID of the managed object associated with the alert. Can be obtained from the na-sightline-managed-object-list command. Optional
page The page to return starting from 1. Optional
limit Maximal number of alerts to retrieve. Also sets the size of the returned page. Default is 50. Optional
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.Alert.alert_class String The class of the alert. One of the following: bgp, cloudsignal, data, dos, smart, system_error, system_event ,tms ,traffic.
NASightline.Alert.alert_type String The type of the alert. One of the following: bgp_hijack, bgp_instability, bgp_trap, cloudsignal, cloudsignal_fault, cloud_mit_request, data, bgp_down, flow_down, snmp_down, dos, dos_host_detection, dos_profiled_network, dos_profiled_router, mobile, mobile_fault, smart, smart_thresh, system_error, collector_down, flexible_license, hw_failure, routing_failover, routing_failover_interface, spcomm_failure, system_monitor, system_event, config_change, tms, dns_baseline, gre_down, tms_fault, traffic, blob_thresh, fingerprint_thresh, interface_usage, service_thresh, traffic_auto_mitigation.
NASightline.Alert.id String The ID of the alert.
NASightline.Alert.importance Number Importance of the alert. One of the following 2: high, 1: medium, 0: low
NASightline.Alert.ongoing Boolean Whether the alert is currently active.
NASightline.Alert.relationships Unknown Relationships of the alert (only visible when extending the data).
NASightline.Alert.start_time Date Date and time at which the alert activity was first detected.
NASightline.Alert.type String Type of the returned object.
NASightline.Alert.classification String Classification of the alert. One of the following: False Positive, Flash Crowd, Network Failure, Possible Attack, Trivial, Verified Attack
NASightline.Alert.stop_time Date Date and time at which the alert activity was no longer detected.
NASightline.Alert.subobject Unknown Subobject data (only visible when extending the data).

Command Example

!na-sightline-alert-list limit=2

Context Example

{
    "NASightline": {
        "Alert": [
            {
                "alert_class": "data",
                "alert_type": "flow_down",
                "id": "2799",
                "importance": 1,
                "ongoing": true,
                "start_time": "2021-05-08T16:07:13+00:00",
                "subobject": {},
                "type": "alert"
            },
            {
                "alert_class": "dos",
                "alert_type": "dos_host_detection",
                "classification": "Possible Attack",
                "id": "2798",
                "importance": 2,
                "ongoing": false,
                "start_time": "2021-05-08T16:00:02+00:00",
                "stop_time": "2021-05-08T16:10:29+00:00",
                "subobject": {
                    "direction": "Incoming",
                    "fast_detected": true,
                    "host_address": "1.2.3.4",
                    "impact_boundary": "managed object",
                    "impact_bps": 1072,
                    "impact_pps": 3,
                    "ip_version": 4,
                    "misuse_types": [
                        "Total Traffic"
                    ],
                    "severity_percent": 10720,
                    "severity_threshold": 10,
                    "severity_unit": "bps",
                    "summary_url": "/page?id=customer_summary&gid=122"
                },
                "type": "alert"
            }
        ]
    }
}

Human Readable Output

Alerts

alert_class alert_type id importance links ongoing start_time subobject type
data flow_down 2799 1 self: https://xsoar-example:57585/api/sp/v7/alerts/2799 true 2021-05-08T16:07:13+00:00   alert
dos dos_host_detection 2798 2 self: https://xsoar-example:57585/api/sp/v7/alerts/2798 false 2021-05-08T16:00:02+00:00   alert

na-sightline-mitigation-list


List all mitigations. When a mitigation ID is given, only the relevant mitigation will be fetched.

Base Command

na-sightline-mitigation-list

Input

Argument Name Description Required
mitigation_id The mitigation ID to get. Can be obtained from the na-sightline-mitigation-list command. Optional
page The page to return starting from 1. Optional
limit Maximal number of mitigations to retrieve. Also sets the size of the returned page. Default is 50. Optional
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.Mitigation.description String Description of the mitigation.
NASightline.Mitigation.id String The ID of the mitigation.
NASightline.Mitigation.ip_version Number IP version of the traffic that is being mitigated.
NASightline.Mitigation.is_automitigation Boolean Whether the mitigation is an auto-mitigation.
NASightline.Mitigation.name String Mitigation name.
NASightline.Mitigation.ongoing Boolean Whether the mitigation is currently running.
NASightline.Mitigation.start String Start date and time of the mitigation in ISO 8601 format.
NASightline.Mitigation.subtype String The type of mitigation. One of the following: blackhole, flowspec, tms.
NASightline.Mitigation.type String Type of the returned object.
NASightline.Mitigation.user String The user who initiated a mitigation.
NASightline.Mitigation.relationships Unknown Relationships of the mitigation (only visible when extending the data).
NASightline.Mitigation.subobject Unknown Subobject data (only visible when extending the data).

Command Example

!na-sightline-mitigation-list limit=2

Context Example

{
    "NASightline": {
        "Mitigation": [
            {
                "description": "TMS mitigation for alert 101",
                "id": "flowspec-36",
                "ip_version": 4,
                "is_automitigation": false,
                "name": "DoS Alert 1079",
                "ongoing": true,
                "start": "2021-04-22T07:39:27.849350+00:00",
                "subtype": "flowspec",
                "type": "mitigation",
                "user": "demisto"
            },
            {
                "description": "Some annotation description",
                "id": "flowspec-12",
                "ip_version": 4,
                "is_automitigation": false,
                "name": "Mitigation Annotation Name1",
                "ongoing": true,
                "start": "2021-04-17T18:03:54.875020+00:00",
                "subtype": "flowspec",
                "type": "mitigation",
                "user": "demisto"
            }
        ]
    }
}

Human Readable Output

Mitigation list

description id ip_version is_automitigation links name ongoing start subtype type user
TMS mitigation for alert 101 flowspec-36 4 false self: https://xsoar-example:57585/api/sp/v7/mitigations/flowspec-36 DoS Alert 1079 true 2021-04-22T07:39:27.849350+00:00 flowspec mitigation demisto
Some annotation description flowspec-12 4 false self: https://xsoar-example:57585/api/sp/v7/mitigations/flowspec-12 Mitigation Annotation Name1 true 2021-04-17T18:03:54.875020+00:00 flowspec mitigation demisto

na-sightline-mitigation-create


Add a TMS or flowspec mitigation with the attributes and relationships passed in the JSON sub_object.

Base Command

na-sightline-mitigation-create

Input

Argument Name Description Required
name Mitigation name. Required
ip_version IP version of the traffic that is being mitigated. This attribute cannot be changed once it is set. Possible values are: IPv4, IPv6. Required
description Description of the mitigation. Optional
ongoing Whether to start the mitigation (true) or not (false). Possible values are: true, false. Default is false. Optional
sub_type The type of mitigation. Possible values are: tms, flowspec. Required
sub_object JSON object that specifies the attributes specific to the mitigation subtype. For example: {“bgp_announce”: false, “protection_prefixes”: [“192.0.2.0/24”]}. List of values supported for each sub-type can be found in the Netscout Arbor Sightline documentation: <your_server_url>/api/sp/doc/v7/mitigations.html#url-/mitigations/. Required
alert_id ID of the alert associated with the mitigation. Can be obtained from the na-sightline-alert-list command. Optional
mitigation_template_id ID of the mitigation template applied to this mitigation. To get a list of available templates and their IDs, run the na-sightline-mitigation-template-list command. Optional
router_ids (Flowspec mitigations only) Comma-separated list of IDs of the routers to which the flowspec announcement is made. To get a list of available routers and their IDs run the na-sightline-router-list command. Optional
managed_object_id (TMS mitigations only) ID of the managed object associated with the alert. To get a list of available managed objects and their IDs run the na-sightline-managed-object-list command. Optional
tms_group_id (TMS mitigations only) ID of the TMS group that the associated managed object belongs to. To get a list of available TMS groups and their IDs run the na-sightline-tms-group-list command. Optional
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.Mitigation.id String The ID of the mitagation.
NASightline.Mitigation.ip_version Number IP version of the traffic that is being mitigated.
NASightline.Mitigation.is_automitigation Boolean Whether the mitigation is an auto-mitigation.
NASightline.Mitigation.name String Mitigation name.
NASightline.Mitigation.ongoing Boolean Whether the mitigation is currently running.
NASightline.Mitigation.subobject Unknown Subobject data (only visible when extending the data).
NASightline.Mitigation.subtype String The type of mitigation. One of the following: blackhole, flowspec, tms.
NASightline.Mitigation.type String Type of the returned object.
NASightline.Mitigation.relationships Unknown Relationships of the mitigation (only visible when extending the data).

Command Example

!na-sightline-mitigation-create description="Some mitigation description" ip_version=IPv4 name="Mitigation Annotation Name" ongoing=true sub_object="{\"protection_prefixes\": [\"192.0.2.0/24\"]}" sub_type=flowspec

Context Example

{
    "NASightline": {
        "Mitigation": {
            "description": "Some mitigation description",
            "id": "flowspec-58",
            "ip_version": 4,
            "is_automitigation": false,
            "name": "Mitigation Annotation Name",
            "ongoing": true,
            "start": "2021-05-08T20:16:53.251710+00:00",
            "subobject": {
                "action": {
                    "type": "accept"
                },
                "bgp_communities": [],
                "l3vpn_route_distinguisher": "",
                "l3vpn_route_targets": []
            },
            "subtype": "flowspec",
            "type": "mitigation",
            "user": "demisto"
        }
    }
}

Human Readable Output

Mitigation was created

description id ip_version is_automitigation links name ongoing start subtype type user
Some mitigation description flowspec-58 4 false self: https://xsoar-example:57585/api/sp/v7/mitigations/flowspec-58 Mitigation Annotation Name true 2021-05-08T20:16:53.251710+00:00 flowspec mitigation demisto

na-sightline-mitigation-delete


Delete a given mitigation.

Base Command

na-sightline-mitigation-delete

Input

Argument Name Description Required
mitigation_id The mitigation ID to delete. Can be obtained from the na-sightline-mitigation-list command. Required

Context Output

There is no context output for this command.

Command Example

!na-sightline-mitigation-delete mitigation_id=flowspec-34

Human Readable Output

Mitigation flowspec-34 was deleted

na-sightline-mitigation-template-list


Get a list of available mitigation templates.

Base Command

na-sightline-mitigation-template-list

Input

Argument Name Description Required
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.MitigationTemplate.description String The description of the mitigation template.
NASightline.MitigationTemplate.id String The ID of the mitigation template.
NASightline.MitigationTemplate.ip_version Number The IP version of the traffic that you want to mitigate with this mitigation template.
NASightline.MitigationTemplate.name String The name of the mitigation template.
NASightline.MitigationTemplate.subtype String The type of mitigation this template can be applied to.
NASightline.MitigationTemplate.system Boolean System or custom object.
NASightline.MitigationTemplate.type String Type of the returned object.
NASightline.MitigationTemplate.subobject Unknown Subobject data (only visible when extending the data).
NASightline.MitigationTemplate.relationships Unknown Relationships of the mitigation template (only visible when extending the data).

Command Example

!na-sightline-mitigation-template-list limit=2

Context Example

{
    "NASightline": {
        "MitigationTemplate": [
            {
                "description": "Default mitigation values inherited by all new IPv4 mitigations (unless otherwise scoped)",
                "id": "1",
                "ip_version": 4,
                "name": "Default IPv4",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Auto-Mitigation template use by default for all IPv4 auto-mitigations. Auto-mitigation must be enabled for the managed object.",
                "id": "2",
                "ip_version": 4,
                "name": "Auto-Mitigation IPv4",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Template contains countermeasures that support TMS deployments focused on VoIP Gateway Flood Protection",
                "id": "3",
                "ip_version": 4,
                "name": "VoIP Gateway Protection",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Template provides example countermeasures that would support deployments for DNS infrastructure protection",
                "id": "4",
                "ip_version": 4,
                "name": "DNS Flood Protection",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Rogue DC++ P2P clients have been used to attack HTTP Server infrastructure. This template provides an example of payload REGEX inspection for filtering clients used for a DC++ HTTP attack",
                "id": "5",
                "ip_version": 4,
                "name": "Rogue DC++ Protection",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "TCP SYN flood countermeasure",
                "id": "6",
                "ip_version": 4,
                "name": "TCP SYN Flood",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "ICMP Flood Countermeasure",
                "id": "7",
                "ip_version": 4,
                "name": "ICMP Flood",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Default mitigation values inherited by all new IPv6 mitigations (unless otherwise scoped)",
                "id": "8",
                "ip_version": 6,
                "name": "Default IPv6",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            },
            {
                "description": "Auto-Mitigation template use by default for all IPv6 auto-mitigations. Auto-mitigation must be enabled for the managed object.",
                "id": "9",
                "ip_version": 6,
                "name": "Auto-Mitigation IPv6",
                "subtype": "tms",
                "system": true,
                "type": "mitigation_template"
            }
        ]
    }
}

Human Readable Output

Mitigation template list

description id ip_version links name subtype system type
Default mitigation values inherited by all new IPv4 mitigations (unless otherwise scoped) 1 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/1 Default IPv4 tms true mitigation_template
Auto-Mitigation template use by default for all IPv4 auto-mitigations. Auto-mitigation must be enabled for the managed object. 2 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/2 Auto-Mitigation IPv4 tms true mitigation_template
Template contains countermeasures that support TMS deployments focused on VoIP Gateway Flood Protection 3 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/3 VoIP Gateway Protection tms true mitigation_template
Template provides example countermeasures that would support deployments for DNS infrastructure protection 4 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/4 DNS Flood Protection tms true mitigation_template
Rogue DC++ P2P clients have been used to attack HTTP Server infrastructure. This template provides an example of payload REGEX inspection for filtering clients used for a DC++ HTTP attack 5 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/5 Rogue DC++ Protection tms true mitigation_template
TCP SYN flood countermeasure 6 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/6 TCP SYN Flood tms true mitigation_template
ICMP Flood Countermeasure 7 4 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/7 ICMP Flood tms true mitigation_template
Default mitigation values inherited by all new IPv6 mitigations (unless otherwise scoped) 8 6 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/8 Default IPv6 tms true mitigation_template
Auto-Mitigation template use by default for all IPv6 auto-mitigations. Auto-mitigation must be enabled for the managed object. 9 6 self: https://xsoar-example:57585/api/sp/v7/mitigation_templates/9 Auto-Mitigation IPv6 tms true mitigation_template

na-sightline-router-list


Get a list of available routers.

Base Command

na-sightline-router-list

Input

Argument Name Description Required
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.Router.advanced_fallback_alg String The algorithm used to classify interfaces during auto-configuration that either report no traffic or have no associated BGP information: internal, external, or use_bgp_and_local. use_bgp_and_local classifies each observed flow, based on learned BGP information and the configured IP address space.
NASightline.Router.advanced_use_simpson_flowspec_redirect_ip Boolean If true, BGP Redirect-to-IP flowspec announcements are generated conforming to draft-simpson-idr-flowspec-redirect-02.txt.
NASightline.Router.bgp2_capabilities_labeled_unicast Boolean If true, Sightline is permitted to generate BGP 6PE diversion announcements for IPv6 destinations over the secondary BGP session per RFC 4798.
NASightline.Router.bgp_capabilities_l3vpn_flowspec_ipv4 Boolean (MPLS Layer 3 VPNs only) If true, Sightline includes the route distinguisher (RD) and route target (RT) values in BGP flowspec diversion announcements for IPv4 traffic in flowspec mitigations and TMS mitigations.
NASightline.Router.bgp_capabilities_l3vpn_flowspec_ipv6 Boolean (MPLS Layer 3 VPNs only) If true, Sightline includes the route distinguisher (RD) and route target (RT) values in BGP flowspec diversion announcements for IPv6 traffic in flowspec mitigations and TMS mitigations.
NASightline.Router.bgp_capabilities_labeled_unicast Boolean If true, Sightline is permitted to generate BGP 6PE diversion announcements for for IPv6 destinations over the primary BGP session per RFC 4798.
NASightline.Router.description String Router description.
NASightline.Router.flow_alerting Boolean If true, enables flow down alerting for this router.
NASightline.Router.flow_export_ip String The IP address of the router that sends flow records to Sightline.
NASightline.Router.flow_flow_ignored String Either ignore NetFlow from this router (on) or not (off).
NASightline.Router.flow_flow_ignored_ipv6 String Either ignore IPv6 NetFlow from this router (on) or not (off).
NASightline.Router.flow_sample_rate String The sample rate of the flow information sent by this router.
NASightline.Router.id String The ID of the router.
NASightline.Router.is_proxy Boolean If true, Sightline treats the router as a proxy for other routers.
NASightline.Router.license_type String The router license type: core, edge, or unset. For more information, see “Configuring Routers” in the Sightline and TMS User Guide.
NASightline.Router.name String Router name
NASightline.Router.snmp_authprotocol String SNMP v3 authentication protocol. One of the following: md5, sha, sha-224, sha-256, sha-384, sha-512.
NASightline.Router.snmp_priv_protocol String The SNMP v3 privacy protocol: DES or AES.
NASightline.Router.snmp_security_level String SNMP v3 security level. One of the following: noAuthNoPriv (no pass-phrase authentication is performed), authNoPriv (pass-phrase authentication is performed, but there is no encryption of the data in the trap messages), authPriv (pass-phrase authentication is performed and the data in the trap messages is encrypted).
NASightline.Router.snmp_version Number SNMP version: 1, 2, or 3.
NASightline.Router.type String Type of the returned object.
NASightline.Router.advanced_local_as String The default local AS number override.
NASightline.Router.bgp_capabilities_flowspec Boolean If true, Sightline can use the primary BGP peering session to generate BGP flowspec diversion announcements for IPv4 traffic in flowspec mitigations and TMS mitigations.
NASightline.Router.bgp_capabilities_flowspec_ipv4 Boolean If true, Sightline can use the primary BGP peering session to generate BGP flowspec diversion announcements for IPv4 traffic in flowspec mitigations and TMS mitigations.
NASightline.Router.bgp_capabilities_monitor_routes_ipv4 String If primary, the primary BGP peering session is used to monitor the IPv4 routes on the router for the purposes of classifying IPv4 traffic. If secondary, the secondary BGP peering session is used. If disabled, IPv4 routes are not monitored and IPv4 traffic is not classified using BGP routing information from this router.
NASightline.Router.bgp_ip_address String The remote IP address that you want Sightline to use to create a BGP peering session with this router.
NASightline.Router.bgp_remote_as String The ASN of the router.
NASightline.Router.bgp_session_name String A name to help identify the BGP peering session in the Sightline UI when you create a blackhole or TMS mitigation.
NASightline.Router.relationships Unknown Relationships of the router (only visible when extending the data).

Command Example

!na-sightline-router-list limit=2

Context Example

{
    "NASightline": {
        "Router": [
            {
                "advanced_fallback_alg": "internal",
                "advanced_use_simpson_flowspec_redirect_ip": false,
                "bgp2_capabilities_labeled_unicast": false,
                "bgp_capabilities_l3vpn_flowspec_ipv4": false,
                "bgp_capabilities_l3vpn_flowspec_ipv6": false,
                "bgp_capabilities_labeled_unicast": false,
                "description": "Traffic-PCAP-CentOS - 192.168.1.116",
                "flow_alerting": true,
                "flow_export_ip": "192.168.1.116",
                "flow_flow_ignored": "off",
                "flow_flow_ignored_ipv6": "off",
                "flow_sample_rate": "1",
                "id": "121",
                "is_proxy": false,
                "license_type": "core",
                "name": "Traffic-PCAP-CentOS",
                "snmp_authprotocol": "md5",
                "snmp_priv_protocol": "DES",
                "snmp_security_level": "noAuthNoPriv",
                "snmp_version": 2,
                "type": "router"
            },
            {
                "advanced_fallback_alg": "internal",
                "advanced_local_as": "44",
                "advanced_use_simpson_flowspec_redirect_ip": false,
                "bgp2_capabilities_labeled_unicast": false,
                "bgp_capabilities_flowspec": true,
                "bgp_capabilities_flowspec_ipv4": true,
                "bgp_capabilities_l3vpn_flowspec_ipv4": false,
                "bgp_capabilities_l3vpn_flowspec_ipv6": false,
                "bgp_capabilities_labeled_unicast": false,
                "bgp_capabilities_monitor_routes_ipv4": "primary",
                "bgp_ip_address": "192.168.1.124",
                "bgp_remote_as": "4",
                "bgp_session_name": "NetscoutProfile",
                "description": "To Netscout PANW FW Router",
                "flow_alerting": true,
                "flow_flow_ignored": "off",
                "flow_flow_ignored_ipv6": "off",
                "id": "186",
                "is_proxy": false,
                "license_type": "core",
                "name": "PANW-FW_Netscout",
                "snmp_authprotocol": "md5",
                "snmp_priv_protocol": "DES",
                "snmp_security_level": "noAuthNoPriv",
                "snmp_version": 2,
                "type": "router"
            }
        ]
    }
}

Human Readable Output

Router list

id name description is_proxy license_type snmp_authprotocol snmp_priv_protocol snmp_security_level snmp_version
121 Traffic-PCAP-CentOS Traffic-PCAP-CentOS - 192.168.1.116 false core md5 DES noAuthNoPriv 2
186 PANW-FW_Netscout To Netscout PANW FW Router false core md5 DES noAuthNoPriv 2

na-sightline-managed-object-list


Get a list of available managed objects.

Base Command

na-sightline-managed-object-list

Input

Argument Name Description Required
page The page to return starting from 1. Optional
limit Maximal number of mitigations to retrieve. Also sets the size of the returned page. Default is 50. Optional
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.ManagedObject.autodetected Boolean If true, Sightline automatically detects and configures VPN sites when the match type of a VPN managed object is a route target and the VPN sites match the configured route targets.
NASightline.ManagedObject.automitigation_precise_protection_prefixes Boolean If true, the precise protection prefixes feature for auto-mitigations is enabled.
NASightline.ManagedObject.detection_network_country_enabled Boolean If true, profiled country detection is enabled.
NASightline.ManagedObject.detection_network_enabled Boolean If true, profiled network detection is enabled.
NASightline.ManagedObject.detection_profiled_autorate Boolean If true, automatic rate calculation for profiled router detection is enabled.
NASightline.ManagedObject.detection_profiled_enabled Boolean If true, profiled router detection is enabled.
NASightline.ManagedObject.detection_profiled_fast_flood_enabled Boolean If true, fast flood detection for profiled routers is enabled.
NASightline.ManagedObject.detection_profiled_outgoing_enabled Boolean If true, outgoing detection for profiled router detection is enabled.
NASightline.ManagedObject.detection_profiled_severity_duration Number Number of seconds that traffic must exceed a given severity threshold before Sightline escalates its severity for profiled router detection.
NASightline.ManagedObject.detection_profiled_severity_snmp_enabled Boolean If true, SNMP link rate severity calculation is enabled for profiled router detection.
NASightline.ManagedObject.detection_profiled_threshold_bandwidth Number Threshold for interface bandwidth alerts for profiled router detection. An integer from 1 to 5, where: 1 = detect more alerts, 2 = default, 3 = detect fewer alerts, 4 = detect even fewer alerts, 5 = detect fewest alerts.
NASightline.ManagedObject.detection_profiled_threshold_packet_rate Number Threshold for interface packet alerts for profiled router detection. An integer from 1 to 5, where: 1 = detect more alerts, 2 = default, 3 = detect fewer alerts, 4 = detect even fewer alerts, 5 = detect fewest alerts.
NASightline.ManagedObject.detection_profiled_threshold_protocol Number Threshold for all protocol alerts for profiled router detection. An integer from 1 to 5, where: 1 = detect more alerts, 2 = default, 3 = detect fewer alerts, 4 = detect even fewer alerts, 5 = detect fewest alerts.
NASightline.ManagedObject.dynamic_match_enabled Boolean If true, Sightline can monitor traffic for OTT domains that have frequently changing service IP addresses.
NASightline.ManagedObject.editable Boolean If true, is editable.
NASightline.ManagedObject.family String A valid managed object type. Not all values appear in the UI as managed object types. One of the following: none, peer, profile, customer, worm (deprecated), vpn, vpnsite, service, subscriber.
NASightline.ManagedObject.id String The ID of the managed object.
NASightline.ManagedObject.match String A value appropriate for the specified match_type.
NASightline.ManagedObject.match_enabled Boolean If true, Sightline records flow for this managed object.
NASightline.ManagedObject.match_type String The managed object’s match type. One of the following: advanced, appid, asregexp, cidr_blocks, cidr_groups, cidr_v6_blocks, community, extended_community, interface, profiled_interface_group, subas, peer_as, tmsports.
NASightline.ManagedObject.mitigation_automitigation_stop_event String The event that stops this TMS auto-mitigation. One of the following: manual, after_mitigation_starts, after_alert_ends.
NASightline.ManagedObject.mitigation_automitigation_stop_minutes Number Stops the TMS auto-mitigation after the specified number of minutes for the after_mitigation_starts or after_alert_ends stop events. This is automatically set to 0 if mitigation_automitigation_stop_event is manual.
NASightline.ManagedObject.mitigation_automitigation_tms_enabled Boolean If true, TMS auto-mitigation is enabled.
NASightline.ManagedObject.mitigation_blackhole_auto_enabled Boolean If true, blackhole auto-mitigation is enabled.
NASightline.ManagedObject.mitigation_flowspec_auto_enabled Boolean If true, flowspec auto-mitigation is enabled.
NASightline.ManagedObject.name String The managed object’s name.
NASightline.ManagedObject.num_children Number The number of child managed objects assigned to this one.
NASightline.ManagedObject.parent_editable Boolean If false, parent is read-only.
NASightline.ManagedObject.relationships Unknown Relationships of the managed object (only visible when extending the data).
NASightline.ManagedObject.scrub_insight_mo_match Boolean If true, Sightline disassociates the managed object from the flow before sending the flow to Insight, thereby preventing the managed object from being subject to or appearing in Insight queries.
NASightline.ManagedObject.tags String A list of tags that are applied to the managed object.
NASightline.ManagedObject.type String Type of the returned object.

Command Example

!na-sightline-managed-object-list limit=2

Context Example

{
    "NASightline": {
        "ManagedObject": {
            "autodetected": false,
            "automitigation_precise_protection_prefixes": false,
            "automitigation_precise_protection_prefixes_mit_on_query_failure": false,
            "custom_shared_host_detection_setting": true,
            "detection_network_country_enabled": false,
            "detection_network_enabled": false,
            "detection_profiled_autorate": false,
            "detection_profiled_enabled": false,
            "detection_profiled_fast_flood_enabled": false,
            "detection_profiled_outgoing_enabled": true,
            "detection_profiled_severity_duration": 300,
            "detection_profiled_severity_snmp_enabled": false,
            "detection_profiled_threshold_bandwidth": 2,
            "detection_profiled_threshold_packet_rate": 2,
            "detection_profiled_threshold_protocol": 2,
            "dynamic_match_enabled": false,
            "editable": true,
            "family": "customer",
            "id": "122",
            "match": "1.2.3.4/32",
            "match_enabled": true,
            "match_type": "cidr_blocks",
            "mitigation_automitigation": false,
            "mitigation_automitigation_stop_event": "after_alert_ends",
            "mitigation_automitigation_stop_minutes": 0,
            "mitigation_automitigation_tms_enabled": false,
            "mitigation_blackhole_auto_enabled": false,
            "mitigation_flowspec_auto_enabled": false,
            "name": "TestMO1",
            "num_children": 0,
            "parent_editable": false,
            "scrub_insight_mo_match": false,
            "tags": [
                "customer"
            ],
            "type": "managed_object"
        }
    }
}

Human Readable Output

Managed object list

id name tags match_type match_enabled match family autodetected
122 TestMO1 customer cidr_blocks true 1.2.3.4/32 customer false

na-sightline-tms-group-list


Get a list of available TMS groups.

Base Command

na-sightline-tms-group-list

Input

Argument Name Description Required
extend_data Whether to extend the results with all available data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
NASightline.TMSGroup.check_available_bw Boolean If true, ensures that all TMS appliances or Cisco ASR 9000 vDDoS Protection devices in a group use less than 90% of the allowed traffic rate in order for a mitigation to start.
NASightline.TMSGroup.check_bgp_peering Boolean If true, ensures that the TMS appliances or Cisco ASR 9000 vDDoS Protection devices are part of a peering session.
NASightline.TMSGroup.check_group_allup Boolean If true, requires all group members to be up before starting a mitigation. This ensures that sufficient resources are available before a mitigation starts.
NASightline.TMSGroup.default_bgp_offramp Boolean If true, the default BGP diversion nexthops of the TMS appliances or Cisco ASR 9000 vDDoS Protection devices in the TMS group are used.
NASightline.TMSGroup.description String Description of the TMS group.
NASightline.TMSGroup.fail_open Boolean If true, ends the mitigation if one or more group members fails or becomes unreachable.
NASightline.TMSGroup.flowspec_redirect_ipv4_destination String In TMS flowspec diversion deployments, these attributes each specify a destination route target or IP address. The Sightline peer uses these destinations in TMS mitigations to advertise routes to its BGP peers.
NASightline.TMSGroup.flowspec_redirect_ipv4_type String In TMS flowspec diversion deployments, these attributes define whether the Sightline peer redirects TMS mitigation traffic to a route target or to an IP address.
NASightline.TMSGroup.flowspec_redirect_ipv6_destination String In TMS flowspec diversion deployments, these attributes each specify a destination route target or IP address. The Sightline peer uses these destinations in TMS mitigations to advertise routes to its BGP peers.
NASightline.TMSGroup.flowspec_redirect_ipv6_type String In TMS flowspec diversion deployments, these attributes define whether the Sightline peer redirects TMS mitigation traffic to a route target or to an IP address.
NASightline.TMSGroup.id String The TMS group ID.
NASightline.TMSGroup.l3vpn_flowspec_ipv4_route_distinguisher String The route distinguisher (RD) for a VPN, which uniquely identifies the routes for that VPN.
NASightline.TMSGroup.l3vpn_flowspec_ipv6_route_distinguisher String The route distinguisher (RD) for a VPN, which uniquely identifies the routes for that VPN.
NASightline.TMSGroup.member_limits_differ Boolean If true, TMS device limits (such as maximum mitigations or filter lists) differ, which leads to either performance issues if devices change midstream for ongoing mitigations, or failure to start or save mitigations.
NASightline.TMSGroup.mitigation_orchestration.bandwidth_threshold_percent Number The percentage of total bandwidth capacity at which this TMS group will become overloaded.
NASightline.TMSGroup.mitigation_orchestration.enabled Boolean If true, mitigation orchestration is enabled for this TMS group.
NASightline.TMSGroup.name String TMS group name.
NASightline.TMSGroup.nexthop String The IPv4 address for the BGP diversion nexthop. It overrides the default nexthops of the TMS appliances or Cisco ASR 9000 vDDoS Protection devices that are in the TMS group.
NASightline.TMSGroup.nexthop_v6 String The IPv6 address for the BGP diversion nexthop. It overrides the default nexthops of the TMS appliances or Cisco ASR 9000 vDDoS Protection devices that are in the TMS group.
NASightline.TMSGroup.relationships Unknown Relationships of the managed object (only visible when extending the data).
NASightline.TMSGroup.system Boolean If true, the TMS group is pre-configured in Sightline and is not editable.
NASightline.TMSGroup.tms_group_type String Type of the TMS group.
NASightline.TMSGroup.type String Type of the returned object.

Command Example

!na-sightline-tms-group-list limit=2

Context Example

{
    "NASightline": {
        "TMSGroup": [
            {
                "bgp_communities": [],
                "check_available_bw": true,
                "check_bgp_peering": true,
                "check_group_allup": true,
                "default_bgp_offramp": true,
                "description": "Default all mitigation group. Mitigations will use all ports on all configured TMS devices.",
                "dns_auth_active_secondary_servers": [],
                "fail_open": false,
                "flowspec_communities": [],
                "flowspec_offramp": "",
                "flowspec_redirect_ipv4_destination": "",
                "flowspec_redirect_ipv4_type": "",
                "flowspec_redirect_ipv6_destination": "",
                "flowspec_redirect_ipv6_type": "",
                "id": "3",
                "l3vpn_flowspec_ipv4_route_distinguisher": "",
                "l3vpn_flowspec_ipv4_route_targets": [],
                "l3vpn_flowspec_ipv6_route_distinguisher": "",
                "l3vpn_flowspec_ipv6_route_targets": [],
                "member_limits_differ": false,
                "mitigation_orchestration": {
                    "bandwidth_threshold_percent": 85,
                    "enabled": false
                },
                "name": "All",
                "nexthop": "",
                "nexthop_v6": "",
                "system": true,
                "tms_group_type": "",
                "type": "tms_group"
            },
            {
                "bgp_communities": [],
                "check_available_bw": true,
                "check_bgp_peering": true,
                "check_group_allup": true,
                "default_bgp_offramp": false,
                "description": "",
                "dns_auth_active_secondary_servers": [],
                "fail_open": true,
                "flowspec_communities": [],
                "flowspec_offramp": "",
                "flowspec_redirect_ipv4_destination": "",
                "flowspec_redirect_ipv4_type": "route_target",
                "flowspec_redirect_ipv6_destination": "",
                "flowspec_redirect_ipv6_type": "route_target",
                "id": "192",
                "l3vpn_flowspec_ipv4_route_distinguisher": "",
                "l3vpn_flowspec_ipv4_route_targets": [],
                "l3vpn_flowspec_ipv6_route_distinguisher": "",
                "l3vpn_flowspec_ipv6_route_targets": [],
                "member_limits_differ": false,
                "mitigation_orchestration": {
                    "bandwidth_threshold_percent": 85,
                    "enabled": false
                },
                "name": "anar_test",
                "nexthop": "",
                "nexthop_v6": "",
                "system": false,
                "tms_group_type": "",
                "type": "tms_group"
            }
        ]
    }
}

Human Readable Output

TMS group list

check_available_bw check_bgp_peering check_group_allup default_bgp_offramp description fail_open flowspec_redirect_ipv4_type flowspec_redirect_ipv6_type id links member_limits_differ mitigation_orchestration name system type
true true true true Default all mitigation group. Mitigations will use all ports on all configured TMS devices. false     3 self: https://xsoar-example:57585/api/sp/v7/tms_groups/3 false bandwidth_threshold_percent: 85
enabled: false
All true tms_group
true true true false   true route_target route_target 192 self: https://xsoar-example:57585/api/sp/v7/tms_groups/192 false bandwidth_threshold_percent: 85
enabled: false
anar_test false tms_group

Configuration parameters

  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • url — Server URL (e.g., https://192.168.0.1) (required)
  • User
  • isFetch — Fetch incidents
  • first_fetch — First fetch time
  • max_fetch — Fetch Limit
  • look_back — Minutes to look back when fetching
  • alert_class — Alert Class
  • alert_type — Alert Type
  • importance — Minimal importance to fetch
  • ongoing — Event Status
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (9)

  • na-sightline-alert-annotation-list

    Lists the collection of annotations for a given alert.

  • na-sightline-alert-list

    List all alerts. When an alert ID is given, only the relevant alert will be fetched.

  • na-sightline-managed-object-list

    Get a list of available managed objects.

  • na-sightline-mitigation-create

    Add a TMS or flowspec mitigation with the attributes and relationships passed in the JSON sub_object.

  • na-sightline-mitigation-delete

    Delete a given mitigation.

  • na-sightline-mitigation-list

    List all mitigations. When a mitigation ID is given, only the relevant mitigation will be fetched.

  • na-sightline-mitigation-template-list

    Get a list of available mitigation templates.

  • na-sightline-router-list

    Get a list of available routers.

  • na-sightline-tms-group-list

    Get a list of available TMS groups.

from time import sleep
from datetime import datetime, timedelta

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

from copy import deepcopy
import requests
import urllib3

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

""" CONSTANTS """

DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"  # ISO8601 format with UTC, default in XSOAR
IMPORTANCE_DICTIONARY = {"Low": "0", "Medium": "1", "High": "2"}
ONGOING_DICTIONARY = {
    "Ongoing": "true",
    "Not Ongoing": "false",
}
IP_DICTIONARY = {"IPv4": 4, "IPv6": 6}

ROUTERS_HR_HEADERS = [
    "id",
    "name",
    "description",
    "is_proxy",
    "license_type",
    "snmp_authprotocol",
    "snmp_priv_protocol",
    "snmp_security_level",
    "snmp_version",
]

MANAGED_OBJECTS_HR_HEADERS = ["id", "name", "tags", "match_type", "match_enabled", "match", "family", "autodetected"]

""" CLIENT CLASS """


class NetscoutClient(BaseClient):
    """Client class to interact with the service API

    This Client implements API calls, and does not contain any XSOAR logic.
    Should only do requests and return data.
    It inherits from BaseClient defined in CommonServer Python.
    Most calls use _http_request() that handles proxy, SSL verification, etc.
    """

    OPERATOR_NAME_DICTIONARY = {
        # <parm name>: <argument operator name>
        "importance": "importance_operator",
        "start_time": "start_time_operator",
        "stop_time": "stop_time_operator",
    }

    RELATIONSHIP_TO_TYPE = {"routers": "router"}

    MAX_ALERTS_FOR_FIRST_FETCH = 10000

    def __init__(
        self,
        base_url,
        verify,
        proxy,
        first_fetch,
        headers=None,
        max_fetch=None,
        look_back=None,
        alert_class=None,
        alert_type=None,
        classification=None,
        importance=None,
        ongoing=None,
    ):
        self.first_fetch = first_fetch
        self.max_fetch = max_fetch
        self.look_back = look_back
        self.alert_class = alert_class
        self.alert_type = alert_type
        self.classification = classification
        self.importance = importance
        self.ongoing = ongoing
        self.importance_operator = ">"

        super().__init__(base_url=base_url, verify=verify, headers=headers, proxy=proxy)

    def http_request(
        self,
        method: str,
        url_suffix: Optional[str] = None,
        params: Optional[dict] = None,
        json_data: Optional[dict] = None,
        return_empty_response: Optional[bool] = None,
        status_list_to_retry: list = None,
    ):
        return super()._http_request(
            method=method,
            url_suffix=url_suffix,
            params=params,
            json_data=json_data,
            error_handler=self.error_handler,
            return_empty_response=return_empty_response,
            status_list_to_retry=status_list_to_retry,
        )

    @staticmethod
    def error_handler(res: requests.Response):
        """
        Error handler for API calls
        Args:
            res (requests.Response): Response to handle error for

        """
        try:
            # Try to parse json error response
            error_entry = res.json()
            error: str = f"Error in API call [{res.status_code}] - {res.reason}"
            if res.status_code in (400, 422, 404):
                error_list: list = []
                for err in error_entry.get("errors"):
                    # Building the list of errors
                    new_error_source = err.get("source", {}).get("pointer", "").split("/")[-1]
                    new_error_details = err.get("detail")
                    new_error = f"{new_error_source}: {new_error_details}" if new_error_source else new_error_details
                    error_list.append(new_error)

                # If we manged to build a list of errors use it otherwise use basic information
                if error_list:
                    error = f"{error}: \n" + "\n".join(error_list)

            elif res.status_code in (500, 401):
                message = error_entry.get("errors", [])[0].get("message")
                if message:
                    error = f"{error}\n{message}"
            demisto.error(res.text)
            raise DemistoException(error)

        except ValueError:
            raise DemistoException(f"Could not parse error returned from Netscout Arbor Sightline server:\n{str(res.content)}")

    def build_relationships(self, **kwargs) -> dict:
        """
        Builds the relationships object for creating a mitigation. An example of relationships object is:
        {
            "mitigation_template": {
                "data": {
                    "id": "4", "type": "mitigation_template"
                }
            },
            "alert": {
                "data": {
                    "id": "101", "type": "alert"
                    "id": "101", "type": "alert"
                }
            }
        }
        Args:
            kwargs (dict): Dict containing key values parameters to be used for relationships. for example:
            {'ip_version': 4}

        Returns:
            (dict): Netscout relationships object
        """
        relationships: dict[str, Any] = {}
        for key, val in kwargs.items():
            if val:
                # In some cases the name of the relationships is not the same as the type (most cases it is)
                _type = self.RELATIONSHIP_TO_TYPE.get(key, key)
                if key == "routers":
                    relationships[key] = {"data": [{"type": _type, "id": val[0]}]}
                else:
                    relationships[key] = {"data": {"type": _type, "id": val}}
        return relationships

    def build_data_attribute_filter(self, attributes_dict: dict) -> str:
        """
        Builds data attribute filter in the NetscoutArbor form. For example: '/data/attributes/importance>1' where
        key=importance operator='>' and value=1.
        The function iterates over all arguments (besides operators listed in the OPERATOR_NAME_DICTIONARY) and chain
        together the 'key operator val' such that the argument name is 'key', its value is 'val' and operator is '=' if
        no relevant operator is present. In case of multiple parameters the attributes are separated with 'AND'.

        Args:
            attributes_dict (dict): Dict containing key values filter parameters. for example: {'importance': 1}

        Returns:
            (str): Netscout data attribute filter string. For example:
            /data/attributes/importance>1 AND /data/attributes/ongoing=true
        """
        param_list = []
        operator_names = self.OPERATOR_NAME_DICTIONARY.values()
        for key, val in attributes_dict.items():
            # We don't create a filter for operator names
            if key not in operator_names and val:
                operator = "="  # type: str

                # If the current parameter supports a special operator (it appears in the OPERATOR_NAME_DICTIONARY),
                # we take the operator value using the operator name (that appears in the OPERATOR_NAME_DICTIONARY)
                if operator_name := self.OPERATOR_NAME_DICTIONARY.get(key):
                    operator = attributes_dict.get(operator_name, "") if attributes_dict.get(operator_name) else "="

                param_list.append(f"/data/attributes/{key + operator + val}")
        return " AND ".join(param_list)

    def fetch_incidents(self, params_dict: dict) -> tuple[list, dict]:
        """Perform fetch incidents process.

        Args:
            params_dict (dict): The params configured by the user to perform the fetch with.
        Returns:
            (list, dict): List of incidents to save and last run state.
        """
        last_run = demisto.getLastRun()

        fetch_limit = last_run.get("limit") or self.max_fetch

        # end_time is now (and not extremely useful), but update_last_run_object wants it.
        start_time, end_time = get_fetch_run_time_range(
            last_run=last_run,
            first_fetch=self.first_fetch,
            look_back=self.look_back,
            date_format=DATE_FORMAT,
        )

        # We can only filter using '> start_time' not '>= start_time'. Adjust by one second instead.
        tmp_start_time = datetime.strptime(start_time, DATE_FORMAT)
        tmp_start_time - timedelta(seconds=1)
        start_time = tmp_start_time.strftime(DATE_FORMAT)

        demisto.debug(f"Fetching incidents between {start_time} and {end_time}")

        incidents: list = []

        time_attributes_dict = assign_params(start_time=start_time, start_time_operator=">")
        params_dict.update(time_attributes_dict)
        data_attribute_filter = self.build_data_attribute_filter(params_dict)
        demisto.debug(f"NetscoutArborSightline fetch params are: search_filter={data_attribute_filter}")

        # We use the status_list_to_retry since in some rare cases the API returns 500 error on consecutive API
        # calls.
        all_alerts = self.fetch_paged_alerts(
            fetch_limit=fetch_limit, search_filter=data_attribute_filter, status_list_to_retry=[500]
        )
        demisto.debug(f"Got {len(all_alerts)} incidents from the API, before filtering")

        filtered_alerts = filter_incidents_by_duplicates_and_limit(
            incidents_res=all_alerts, last_run=last_run, fetch_limit=fetch_limit, id_field="id"
        )
        demisto.debug(f"After filtering, there are {len(filtered_alerts)} incidents")

        for alert in filtered_alerts:
            id_ = alert.get("id")
            attributes = alert.get("attributes", {})
            alert_type = attributes.get("alert_type")
            start_time = attributes.get("start_time")
            if start_time.endswith("+00:00"):
                start_time = start_time.removesuffix("+00:00") + "Z"

            incidents.append(
                {
                    "name": f"{alert_type}: {id_}",
                    "occurred": start_time,
                    "dbotMirrorId": id_,
                    "rawJSON": json.dumps(alert),
                }
            )

        last_run = update_last_run_object(
            last_run=last_run,
            incidents=incidents,
            fetch_limit=self.max_fetch,
            start_fetch_time=start_time,
            end_fetch_time=end_time,
            look_back=self.look_back,
            created_time_field="occurred",
            id_field="dbotMirrorId",
            date_format=DATE_FORMAT,
            increase_last_run_time=False,
        )
        demisto.debug(f"Last run after the fetch run: {last_run}")

        return incidents, last_run

    def fetch_incidents_loop(self) -> tuple[list, dict]:
        """
        Calls the fetch incidents function to pull incidents with for each alert_type/alert_class separately.

        Returns:
            (list, str): List of incidents to save and string representing the creation time of the latest incident to
            be saved.
        """
        incidents = []
        params_dict = assign_params(
            alert_class=self.alert_class,
            alert_type=self.alert_type,
            importance=self.importance,
            classification=self.classification,
            importance_operator=self.importance_operator,
            ongoing=self.ongoing,
        )
        if self.alert_type:
            key = "alert_type"
            class_type_list = self.alert_type

        elif self.alert_class:
            key = "alert_class"
            class_type_list = self.alert_class
        else:
            key = ""
            class_type_list = []
            demisto.debug(f"No condition was matched {key=} {class_type_list=}")

        if self.alert_class or self.alert_type:
            for item in class_type_list:
                params_dict[key] = item

                last_incidents, last_run = self.fetch_incidents(params_dict)
                incidents += last_incidents
                sleep(5)
        else:
            incidents, last_run = self.fetch_incidents(params_dict)

        return incidents, last_run

    def fetch_paged_alerts(
        self,
        fetch_limit: int,
        search_filter: Optional[str] = None,
        status_list_to_retry: list = None,
    ) -> list[dict]:
        """Fetch alerts using API paging and combine the results into a single list."""
        # Fetch an initial page to get the metadata about total matching alerts.
        first_page = self.list_alerts(search_filter=search_filter, status_list_to_retry=status_list_to_retry)

        meta = first_page.get("meta", {})
        pagination = meta.get("pagination", {})
        # Pagniation object returns null when no results are returned.
        total_count = pagination.get("totalCount") or 0
        per_page = pagination.get("perPage") or 1

        # Jump ahead if we don't need all the pages.
        first_index = total_count - fetch_limit + 1
        first_page_num = first_index // per_page
        if first_page_num > 1:
            first_page = self.list_alerts(
                page=first_page_num, page_size=per_page, search_filter=search_filter, status_list_to_retry=status_list_to_retry
            )

        pages = [first_page]

        # Loop over all the pages.
        while True:
            prev_links = pages[-1].get("links", {})
            next_link = prev_links.get("next")
            if next_link is None:
                break

            # Fetch the next page of results.
            page = self._http_request(
                method="GET",
                full_url=next_link,
                status_list_to_retry=status_list_to_retry,
            )
            pages.append(page)

        # Reverse the results so the oldest is first.
        alerts: list[dict] = []
        for page in reversed(pages):
            alerts.extend(reversed(page.get("data", [])))
        return alerts

    def list_alerts(
        self,
        page: Optional[int] = None,
        page_size: Optional[int] = None,
        search_filter: Optional[str] = None,
        status_list_to_retry: list = None,
    ) -> dict:
        return self.http_request(
            method="GET",
            url_suffix="alerts/",
            status_list_to_retry=status_list_to_retry,
            params=assign_params(page=page, perPage=page_size, filter=search_filter),
        )

    def get_alert(self, alert_id: str) -> dict:
        return self.http_request(method="GET", url_suffix=f"alerts/{alert_id}")

    def get_annotations(self, alert_id: str) -> dict:
        return self.http_request(method="GET", url_suffix=f"alerts/{alert_id}/annotations/")

    def list_mitigations(self, mitigation_id: str, page: Optional[int] = None, page_size: Optional[int] = None) -> dict:
        return self.http_request(
            method="GET",
            url_suffix=f"mitigations/{mitigation_id}" if mitigation_id else "mitigations",
            params=assign_params(page=page, perPage=page_size),
        )

    def create_mitigation(self, data: dict) -> dict:
        return self.http_request(method="POST", url_suffix="mitigations/", json_data=data)

    def delete_mitigation(self, mitigation_id: str):
        self.http_request(method="DELETE", url_suffix=f"mitigations/{mitigation_id}", return_empty_response=True)

    def mitigation_template_list(self) -> dict:
        return self.http_request(method="GET", url_suffix="mitigation_templates/")

    def router_list(self) -> dict:
        return self.http_request(method="GET", url_suffix="routers/")

    def managed_object_list(self, page: Optional[int] = None, page_size: Optional[int] = None) -> dict:
        return self.http_request(method="GET", url_suffix="managed_objects/", params=assign_params(page=page, perPage=page_size))

    def tms_group_list(self) -> dict:
        return self.http_request(method="GET", url_suffix="tms_groups/")


""" HELPER FUNCTIONS """


def clean_links(target_obj: Union[dict, list]):
    """
    Recursively look for a all keys named 'links' and remove them from the object.
    Args:
        target_obj (dict/list): An object to remove the links key from.
    """

    if isinstance(target_obj, dict):
        remove_keys(target_obj, ["links"])
        for val in target_obj.values():
            clean_links(val)

    if isinstance(target_obj, list):
        for i in target_obj:
            clean_links(i)


def validate_json_arg(json_str: str, arg_name: str) -> dict:
    """
    Parse the json data. If the format is invalid an appropriate exception will be raised
    Args:
        json_str (str): The data to parse
        arg_name (str): The argument name where the data eas given (for exception purposes)
    Return:
        (dict): dict representing the given json
    """
    try:
        sub_object = json.loads(json_str)
        return sub_object
    except Exception as err:
        raise DemistoException(
            f"The value given in the {arg_name} argument is not a valid JSON format:\n{json_str}\nERROR:\n{err}"
        )


def remove_keys(obj: dict, keys_to_remove: list):
    """
    Removes the the given keys from a given dict.
    Args:
        obj (dict): The object to remove the key from.
        keys_to_remove (lst): List of keys to remove.
    """
    for key in keys_to_remove:
        if obj.get(key):
            del obj[key]


def flatten_key(obj: dict, key_to_flatten: str):
    """
    Extract the data inside a given key to the root level of the object.
    Args:
        obj (dict): The object to extract the data from.
        key_to_flatten (str): The key name to extract.
    """
    if sub_dictionary := obj.get(key_to_flatten):
        for sub_key, sub_val in sub_dictionary.items():
            obj[sub_key] = sub_val
        del obj[key_to_flatten]


def build_human_readable(data: dict) -> dict:
    """
    Removes the relationships and subobject data from the object and extracts the data inside attributes to the root
    level of the object to be displayed nicely in human readable.
    Args:
        data (dict): The data to create human readable from.
    Return:
        (dict): The same object without the relationships data and with the attributes extracted to the root level.
    """
    hr = deepcopy(data)
    flatten_key(hr, "attributes")
    remove_keys(hr, ["relationships", "subobject"])
    return hr


def build_output(data: dict, extend_data: bool = False, key_to_flat: str = "attributes", keys_to_remove: list = None) -> dict:
    keys_to_remove = keys_to_remove if keys_to_remove else ["relationships"]
    data_copy = deepcopy(data)
    clean_links(data_copy)
    if key_to_flat:
        flatten_key(data_copy, key_to_flat)
    if not extend_data:
        remove_keys(data_copy, keys_to_remove)
    return data_copy


def cast_importance_to_minimal(importance: str) -> Optional[str]:
    """
    If a minimal importance param was given, cast it to the corresponding minimal value to  be used with the '>'
    operator.
    That is:
        High -> '2' -> '1'
        Medium -> '1' -> '0'
        Low -> '0' -> None (so it will be ignored and will not be used as an  importance param)
    Args:
         importance (str): The  importance to cast.
    Returns:
         (str): The value to be used withh the '>` operator.
    """
    str_importance = IMPORTANCE_DICTIONARY.get(importance)
    if str_importance and str_importance != "0":
        return str(int(str_importance) - 1)
    else:
        return None


""" COMMAND FUNCTIONS """


def test_module(client: NetscoutClient) -> str:
    client.fetch_incidents_loop()
    return "ok"


def fetch_incidents_command(client: NetscoutClient):
    incidents, last_run = client.fetch_incidents_loop()
    demisto.incidents(incidents)
    demisto.setLastRun(last_run)


def list_alerts_command(client: NetscoutClient, args: dict):
    limit = arg_to_number(args.get("limit"))
    page = arg_to_number(args.get("page"))
    alert_id = args.get("alert_id")
    alert_class = args.get("alert_class")
    alert_type = args.get("alert_type")
    classification = args.get("classification")
    importance = IMPORTANCE_DICTIONARY.get(args.get("importance", ""))
    importance_operator = args.get("importance_operator")
    ongoing = args.get("ongoing") if args.get("ongoing") else None
    start_time = args.get("start_time")
    start_time_operator = args.get("start_time_operator")
    stop_time = args.get("stop_time")
    stop_time_operator = args.get("stop_time_operator")
    managed_object_id = args.get("managed_object_id")
    extend_data = argToBoolean(args.get("extend_data", False))
    if alert_id:
        raw_result = client.get_alert(alert_id)
    else:
        attributes_dict = assign_params(
            alert_id=alert_id,
            alert_class=alert_class,
            alert_type=alert_type,
            classification=classification,
            importance=importance,
            importance_operator=importance_operator,
            ongoing=ongoing,
            start_time=start_time,
            start_time_operator=start_time_operator,
            stop_time=stop_time,
            stop_time_operator=stop_time_operator,
        )
        data_attribute_filter = client.build_data_attribute_filter(attributes_dict)
        data_relationships_filter = (
            f"AND /data/relationships/managed_object/data/id={managed_object_id}" if managed_object_id else ""
        )
        search_filter = data_attribute_filter + data_relationships_filter
        raw_result = client.list_alerts(page=page, page_size=limit, search_filter=search_filter)

    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    hr = [build_human_readable(data=alert) for alert in data]
    outputs = [build_output(data=alert, extend_data=extend_data) for alert in data]

    return CommandResults(
        outputs_prefix="NASightline.Alert",
        outputs_key_field="id",
        outputs=outputs,
        readable_output=tableToMarkdown("Alerts", hr),
        raw_response=raw_result,
    )


def alert_annotation_list_command(client: NetscoutClient, args: dict):
    alert_id = args.get("alert_id", "")
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.get_annotations(alert_id)
    data = raw_result.get("data", [])
    hr = [build_human_readable(data=annotation) for annotation in data]
    annotations = [build_output(data=annotation, extend_data=extend_data) for annotation in data]
    context = {"AlertID": alert_id, "Annotations": annotations}
    return CommandResults(
        outputs_prefix="NASightline.AlertAnnotation",
        outputs_key_field="AlertID",
        outputs=context,
        readable_output=tableToMarkdown(f"Alert {alert_id} annotations", hr),
        raw_response=raw_result,
    )


def mitigation_list_command(client: NetscoutClient, args: dict):
    page = arg_to_number(args.get("page"))
    limit = arg_to_number(args.get("limit"))
    mitigation_id = args.get("mitigation_id", "")
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.list_mitigations(mitigation_id, page=page, page_size=limit)
    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    hr = [build_human_readable(data=mitigation) for mitigation in data]
    mitigations = [
        build_output(data=mitigation, keys_to_remove=["relationships", "subobject"], extend_data=extend_data)
        for mitigation in data
    ]
    return CommandResults(
        outputs_prefix="NASightline.Mitigation",
        outputs_key_field="id",
        outputs=mitigations,
        readable_output=tableToMarkdown("Mitigation list", hr),
        raw_response=raw_result,
    )


def mitigation_create_command(client: NetscoutClient, args: dict):
    ip_version = IP_DICTIONARY.get(args["ip_version"])
    if not ip_version:
        raise DemistoException(
            'ip_version value can be one of the following: '
            f'{",".join(list(IP_DICTIONARY.keys()))}. {args.get("ip_version")} was given.'
        )
    description = args.get("description")
    name = args.get("name")
    ongoing = args.get("ongoing", "false")
    sub_type = args.get("sub_type")
    sub_object = validate_json_arg(args["sub_object"], "sub_object")
    alert_id = args.get("alert_id")
    managed_object_id = args.get("managed_object_id")
    mitigation_template_id = args.get("mitigation_template_id")
    router_ids = argToList(args.get("router_ids"))
    tms_group_id = args.get("tms_group_id")
    extend_data = argToBoolean(args.get("extend_data", False))

    relationships = client.build_relationships(
        alert=alert_id,
        managed_object=managed_object_id,
        mitigation_template=mitigation_template_id,
        routers=router_ids,
        tms_group=tms_group_id,
    )
    attributes = assign_params(
        description=description, ip_version=ip_version, name=name, ongoing=ongoing, subtype=sub_type, subobject=sub_object
    )
    object_data = {"relationships": relationships, "attributes": attributes}
    raw_result = client.create_mitigation(data={"data": object_data})
    data = raw_result.get("data", {})
    hr = build_human_readable(data=data)
    mitigation = build_output(data=data, extend_data=extend_data)
    return CommandResults(
        outputs_prefix="NASightline.Mitigation",
        outputs_key_field="id",
        outputs=mitigation,
        readable_output=tableToMarkdown("Mitigation was created", hr),
        raw_response=raw_result,
    )


def mitigation_delete_command(client: NetscoutClient, args: dict[str, str]):
    mitigation_id = args.get("mitigation_id", "")
    client.delete_mitigation(mitigation_id)
    hr = f"### Mitigation {mitigation_id} was deleted"
    return CommandResults(readable_output=hr)


def mitigation_template_list_command(client: NetscoutClient, args: dict):
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.mitigation_template_list()
    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    hr = [build_human_readable(data=mitigation_template) for mitigation_template in data]
    mitigation_templates = [
        build_output(data=mitigation_template, extend_data=extend_data, keys_to_remove=["relationships", "subobject"])
        for mitigation_template in data
    ]

    return CommandResults(
        outputs_prefix="NASightline.MitigationTemplate",
        outputs_key_field="id",
        outputs=mitigation_templates,
        readable_output=tableToMarkdown("Mitigation template list", hr, removeNull=True),
        raw_response=raw_result,
    )


def router_list_command(client: NetscoutClient, args: dict):
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.router_list()
    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    hr = [build_human_readable(router) for router in data]
    routers = [build_output(data=router, extend_data=extend_data) for router in data]
    return CommandResults(
        outputs_prefix="NASightline.Router",
        outputs_key_field="id",
        outputs=routers,
        readable_output=tableToMarkdown("Router list", hr, headers=ROUTERS_HR_HEADERS, removeNull=True),
        raw_response=raw_result,
    )


def managed_object_list_command(client: NetscoutClient, args: dict):
    page = arg_to_number(args.get("page"))
    limit = arg_to_number(args.get("limit"))
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.managed_object_list(page=page, page_size=limit)
    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    objects = [build_output(data=managed_object, extend_data=extend_data) for managed_object in data]
    hr = [build_human_readable(data=managed_object) for managed_object in data]
    return CommandResults(
        outputs_prefix="NASightline.ManagedObject",
        outputs_key_field="id",
        outputs=objects,
        readable_output=tableToMarkdown("Managed object list", hr, headers=MANAGED_OBJECTS_HR_HEADERS, removeNull=True),
        raw_response=raw_result,
    )


def tms_group_list_command(client: NetscoutClient, args: dict):
    extend_data = argToBoolean(args.get("extend_data", False))
    raw_result = client.tms_group_list()
    data = raw_result.get("data")
    data = data if isinstance(data, list) else [data]
    hr = [build_human_readable(data=tms_group) for tms_group in data]
    groups = [build_output(data=group, extend_data=extend_data) for group in data]
    return CommandResults(
        outputs_prefix="NASightline.TMSGroup",
        outputs_key_field="id",
        outputs=groups,
        readable_output=tableToMarkdown("TMS group list", hr, removeNull=True),
        raw_response=raw_result,
    )


""" MAIN FUNCTION """


def main() -> None:
    try:
        command = demisto.command()
        params = demisto.params()

        if not params.get("User") or not (api_token := params.get("User", {}).get("password")):
            raise DemistoException("Missing API Key. Fill in a valid key in the integration configuration.")
        base_url = urljoin(params["url"], "api/sp")
        verify_certificate = not params.get("insecure", False)
        proxy = params.get("proxy", False)
        first_fetch = None
        if first_fetch_dt := arg_to_datetime(params.get("first_fetch", "3 days")):
            first_fetch = first_fetch_dt.isoformat()
        max_fetch = min(arg_to_number(params.get("max_fetch")) or 50, 100)
        look_back = arg_to_number(params.get("look_back")) or 1
        alert_class = argToList(params.get("alert_class"))
        alert_type = argToList(params.get("alert_type"))
        if alert_class and alert_type:
            raise DemistoException(
                "Cannot filter alerts with both 'Alert Class' and 'Alert Type' configured. Either choose "
                "the entire class you want to fetch or the specific types from within that class."
            )
        classification = params.get("classification")
        importance = cast_importance_to_minimal(params.get("importance"))
        ongoing = ONGOING_DICTIONARY.get(params.get("ongoing"))

        demisto.debug(f"Command being called is {demisto.command()}")

        headers: dict = {"X-Arbux-APIToken": api_token}

        client = NetscoutClient(
            base_url=base_url,
            verify=verify_certificate,
            headers=headers,
            proxy=proxy,
            first_fetch=first_fetch,
            max_fetch=max_fetch,
            look_back=look_back,
            alert_class=alert_class,
            alert_type=alert_type,
            classification=classification,
            importance=importance,
            ongoing=ongoing,
        )
        args: dict = demisto.args()

        result = ""
        if command == "test-module":
            result = test_module(client)
        elif command == "fetch-incidents":
            fetch_incidents_command(client)
        elif command == "na-sightline-alert-list":
            result = list_alerts_command(client, args)
        elif command == "na-sightline-alert-annotation-list":
            result = alert_annotation_list_command(client, args)
        elif command == "na-sightline-mitigation-list":
            result = mitigation_list_command(client, args)
        elif command == "na-sightline-mitigation-create":
            result = mitigation_create_command(client, args)
        elif command == "na-sightline-mitigation-delete":
            result = mitigation_delete_command(client, args)
        elif command == "na-sightline-mitigation-template-list":
            result = mitigation_template_list_command(client, args)
        elif command == "na-sightline-router-list":
            result = router_list_command(client, args)
        elif command == "na-sightline-managed-object-list":
            result = managed_object_list_command(client, args)
        elif command == "na-sightline-tms-group-list":
            result = tms_group_list_command(client, args)
        else:
            raise NotImplementedError(f"Command: {command} is not implemented")

        if result:
            return_results(result)

    except Exception as e:
        return_error(f"Failed to execute {command} command.\nError:\n{str(e)}")


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