FireEye HX Deprecated

Deprecated. Use FireEyeHX v2 instead.

Endpoint · FireEye HX

Details

IDFireEye HX
ProviderTrellix
CategoryEndpoint
From Version5.0.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

FireEye Endpoint Security is an integrated solution that detects what others miss and protects endpoint against known and unknown threats. The HX Demisto integration provides access to information about endpoints, acquisitions, alerts, indicators, and containment. Customers can extract critical data and effectively operate security operations automated playbook.

Configure FireEye HX in Cortex

Parameter Required
Server URL (e.g. https://192.168.0.1:3000) True
Credentials True
Password True
Version True
Trust any certificate (not secure) False
Use system proxy settings False
Fetch incidents False
Incident type False
Fetch limit False
Incidents Fetch Interval 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.

fireeye-hx-host-containment


Apply containment for a specific host, so that it no longer has access to other systems.

Base Command

fireeye-hx-host-containment

Input

Argument Name Description Required
hostName The host name to be contained. If the hostName is not specified, the agentId must be specified. Optional
agentId The agent id running on the host to be contained. If the agentId is not specified, the hostName must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Hosts._id Unknown FireEye HX Agent ID.
FireEyeHX.Hosts.agent_version Unknown The agent version.
FireEyeHX.Hosts.excluded_from_containment Unknown Determines whether the host is excluded from containment.
FireEyeHX.Hosts.containment_missing_software Unknown Boolean value to indicate for containment missing software.
FireEyeHX.Hosts.containment_queued Unknown Determines whether the host is queued for containment.
FireEyeHX.Hosts.containment_state Unknown The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu.
FireEyeHX.Hosts.stats.alerting_conditions Unknown The number of conditions that have alerted for the host.
FireEyeHX.Hosts.stats.alerts Unknown Total number of alerts, including exploit-detection alerts.
FireEyeHX.Hosts.stats.exploit_blocks Unknown The number of blocked exploits on the host.
FireEyeHX.Hosts.stats.malware_alerts Unknown The number of malware alerts associated with the host.
FireEyeHX.Hosts.hostname Unknown The host name.
FireEyeHX.Hosts.domain Unknown Domain name.
FireEyeHX.Hosts.timezone Unknown Host time zone.
FireEyeHX.Hosts.primary_ip_address Unknown The host IP address.
FireEyeHX.Hosts.last_poll_timestamp Unknown The timestamp of the last system poll preformed on the host.
FireEyeHX.Hosts.initial_agent_checkin Unknown Timestamp of the initial agent check-in.
FireEyeHX.Hosts.last_alert_timestamp Unknown The time stamp of the last alert for the host.
FireEyeHX.Hosts.last_exploit_block_timestamp Unknown Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked.
FireEyeHX.Hosts.os.product_name Unknown Specific operating system
FireEyeHX.Hosts.os.bitness Unknown OS Bitness.
FireEyeHX.Hosts.os.platform Unknown Family of operating systems. Valid values are win, osx, and linux.
FireEyeHX.Hosts.primary_mac Unknown The host MAC address.

Command Example

!fireeye-hx-host-containment agentId=”uGvn34ZkM3bfSf1nOT”
!fireeye-hx-host-containment hostname=“DESKTOP-HK8OI62”

Context Example

 {  
   "FireEyeHX":{  
      "Hosts":{  
         "last_alert":{  
            "url":"/hx/api/v3/alerts/5",
            "_id":5
         },
         "domain":"DEMISTO",
         "last_exploit_block_timestamp":null,
         "containment_state":"contain",
         "timezone":"Eastern Daylight Time",
         "gmt_offset_seconds":-14400,
         "initial_agent_checkin":"2018-03-26T14:21:31.273Z",
         "stats":{  
            "alerting_conditions":1,
            "exploit_alerts":0,
            "acqs":11,
            "malware_false_positive_alerts":0,
            "alerts":1,
            "exploit_blocks":0,
            "malware_cleaned_count":0,
            "malware_alerts":0,
            "malware_quarantined_count":0
         },
         "primary_mac":"XX-XX-XX-XX-XX-XX",
         "hostname":"DESKTOP-XXX",
         "primary_ip_address":"^^^XX.XX.XX.XX^^^",
         "last_audit_timestamp":"2018-05-03T13:59:23.000Z",
         "last_alert_timestamp":"2018-04-16T08:59:51.693+00:00",
         "containment_queued":false,
         "sysinfo":{  
            "url":"/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
         },
         "last_exploit_block":null,
         "reported_clone":false,
         "url":"/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT",
         "excluded_from_containment":false,
         "last_poll_timestamp":"2018-05-03T14:01:22.000Z",
         "last_poll_ip":"^^^XX.XX.XX.XX^^^",
         "containment_missing_software":false,
         "_id":" uGvnGVpZkDSFySf2ZOiT ",
         "os":{  
            "kernel_version":null,
            "platform":"win",
            "patch_level":null,
            "bitness":"64-bit",
            "product_name":"Windows 10 Enterprise Evaluation"
         },
         "agent_version":"26.21.10"
      }
   }
}

fireeye-hx-cancel-containment


Release a specific host from containment.

Base Command

fireeye-hx-cancel-containment

Input

Argument Name Description Required
hostName The host name to be contained. If the hostName is not specified, the agentId must be specified. Optional
agentId The agent id running on the host to be contained. If the agentId is not specified, the hostName must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Hosts._id Unknown FireEye HX Agent ID.
FireEyeHX.Hosts.agent_version Unknown The agent version.
FireEyeHX.Hosts.excluded_from_containment Unknown Determines whether the host is excluded from containment.
FireEyeHX.Hosts.containment_missing_software Unknown Boolean value to indicate for containment missing software.
FireEyeHX.Hosts.containment_queued Unknown Determines whether the host is queued for containment.
FireEyeHX.Hosts.containment_state Unknown The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu.
FireEyeHX.Hosts.stats.alerting_conditions Unknown The number of conditions that have alerted for the host.
FireEyeHX.Hosts.stats.alerts Unknown Total number of alerts, including exploit-detection alerts.
FireEyeHX.Hosts.stats.exploit_blocks Unknown The number of blocked exploits on the host.
FireEyeHX.Hosts.stats.malware_alerts Unknown The number of malware alerts associated with the host.
FireEyeHX.Hosts.hostname Unknown The host name.
FireEyeHX.Hosts.domain Unknown Domain name.
FireEyeHX.Hosts.timezone Unknown Host time zone.
FireEyeHX.Hosts.primary_ip_address Unknown The host IP address.
FireEyeHX.Hosts.last_poll_timestamp Unknown The timestamp of the last system poll preformed on the host.
FireEyeHX.Hosts.initial_agent_checkin Unknown Timestamp of the initial agent check-in.
FireEyeHX.Hosts.last_alert_timestamp Unknown The time stamp of the last alert for the host.
FireEyeHX.Hosts.last_exploit_block_timestamp Unknown Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked.
FireEyeHX.Hosts.os.product_name Unknown Specific operating system
FireEyeHX.Hosts.os.bitness Unknown OS Bitness.
FireEyeHX.Hosts.os.platform Unknown Family of operating systems. Valid values are win, osx, and linux.
FireEyeHX.Hosts.primary_mac Unknown The host MAC address.

Command Examples

!fireeye-hx-cancel-containment hostname=“DESKTOP-HK8OI62”
!fireeye-hx-cancel-containment agentId=”uGvn34ZkM3bfSf1nOT”

Context Example

{
    "FireEyeHX": {
        "Hosts": {
            "last_alert": {
                "url": "/hx/api/v3/alerts/5", 
                "_id": 5
            }, 
            "domain": "DEMISTO", 
            "last_exploit_block_timestamp": null, 
            "containment_state": "normal", 
            "timezone": "Eastern Daylight Time", 
            "gmt_offset_seconds": -14400, 
            "initial_agent_checkin": "2018-03-26T14:21:31.273Z", 
            "stats": {
                "alerting_conditions": 1, 
                "exploit_alerts": 0, 
                "acqs": 11, 
                "malware_false_positive_alerts": 0, 
                "alerts": 1, 
                "exploit_blocks": 0, 
                "malware_cleaned_count": 0, 
                "malware_alerts": 0, 
                "malware_quarantined_count": 0
            }, 
            "primary_mac": "XX-XX-XX-XX-XX-XX", 
            "hostname": "DESKTOP-XXX", 
            "primary_ip_address": "^^^XX.XX.XX.XX^^^", 
            "last_audit_timestamp": "2018-05-03T13:59:23.000Z", 
            "last_alert_timestamp": "2018-04-16T08:59:51.693+00:00", 
            "containment_queued": false, 
            "sysinfo": {
                "url": "/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
            }, 
            "last_exploit_block": null, 
            "reported_clone": false, 
            "url": "/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT", 
            "excluded_from_containment": false, 
            "last_poll_timestamp": "2018-05-03T14:01:22.000Z", 
            "last_poll_ip": "^^^XX.XX.XX.XX^^^", 
            "containment_missing_software": false, 
            "_id": " uGvnGVpZkDSFySf2ZOiT ", 
            "os": {
                "kernel_version": null, 
                "platform": "win", 
                "patch_level": null, 
                "bitness": "64-bit", 
                "product_name": "Windows 10 Enterprise Evaluation"
            }, 
            "agent_version": "26.21.10"
        }
    }
 }

fireeye-hx-get-alerts


Get a list of alerts, use the different arguments to filter the results returned.

Base Command

fireeye-hx-get-alerts

Input

Argument Name Description Required
hasShareMode Identifies which alerts result from indicators with the specified share mode. Possible values are: any, restricted, unrestricted. Optional
resolution Sorts the results by the specified field. Possible values are: active_threat, alert, block, partial_block. Optional
agentId Filter by the agent ID. Optional
conditionId Filter by condition ID. Optional
eventAt Filter event occurred time. ISO-8601 timestamp.. Optional
alertId Filter by alert ID. Optional
matchedAt Filter by match detection time. ISO-8601 timestamp. Optional
minId Filter that returns only records with an AlertId field value great than the minId value. Optional
reportedAt Filter by reported time. ISO-8601 timestamp. Optional
IOCsource Source of alert- indicator of compromise. Possible values are: yes. Optional
EXDsource Source of alert - exploit detection. Possible values are: yes. Optional
MALsource Source of alert - malware alert. Possible values are: yes. Optional
limit Limit the results returned. Optional
sort Sorts the results by the specified field in ascending order. Possible values are: agentId, conditionId, eventAt, alertId, matchedAt, id, reportedAt. Optional
sortOrder The sort order for the results. Possible values are: ascending, descending. Optional

Context Output

Path Type Description
FireEyeHX.Alerts._id Unknown FireEye alert ID.
FireEyeHX.Alerts.agent._id Unknown FireEye agent ID.
FireEyeHX.Alerts.agent.containment_state Unknown Host containment state.
FireEyeHX.Alerts.condition._id Unknown The condition unique ID.
FireEyeHX.Alerts.event_at Unknown Time when the event occoured.
FireEyeHX.Alerts.matched_at Unknown Time when the event was matched.
FireEyeHX.Alerts.reported_at Unknown Time when the event was reported.
FireEyeHX.Alerts.source Unknown Source of alert.
FireEyeHX.Alerts.matched_source_alerts._id Unknown Source alert ID.
FireEyeHX.Alerts.matched_source_alerts.appliance_id Unknown Appliance ID
FireEyeHX.Alerts.matched_source_alerts.meta Unknown Source alert meta.
FireEyeHX.Alerts.matched_source_alerts.indicator_id Unknown Indicator ID.
FireEyeHX.Alerts.resolution Unknown Alert resulotion.
FireEyeHX.Alerts.event_type Unknown Event type.

Command Example

!fireeye-hx-get-alerts limit="10" sort="id" sortOrder="descending"

Context Example

{
    "FireEyeHX": {
        "Alerts": {
            "_id": 5,
            "agent": {
                "_id": "uGvnGVp…4bKeySf2ZOiT",
                "containment_state": "normal",
                "url": "/hx/api/v3/hosts/ uGvnGVp…4bKeySf2ZOiT "
            },
            "condition": {
                "_id": "CSaoSZFw…JNPW0mw==",
                "url": "/hx/api/v3/conditions/ CSaoSZFw…JNPW0mw =="
            },
            "event_at": "2018-04-16T08:59:02.061Z",
            "event_id": 7885715,
            "event_type": "fileWriteEvent",
            "event_values": {
                "fileWriteEvent/closed": 1,
                "fileWriteEvent/dataAtLowestOffset": "dGVzdGVzdA==",
                "fileWriteEvent/devicePath": "\\Device\\HarddiskVolume2",
                "fileWriteEvent/drive": "C",
                "fileWriteEvent/fileExtension": "txt",
                "fileWriteEvent/fileName": "testest - Copy.txt",
                "fileWriteEvent/filePath": "Users\\demistodev\\Documents",
                "fileWriteEvent/fullPath": "C:\\Users\\User\\Documents\\testest - Copy.txt",
                "fileWriteEvent/lowestFileOffsetSeen": 0,
                "fileWriteEvent/md5": " c3add7b947…817c79f7b7bd ",
                "fileWriteEvent/numBytesSeenWritten": 7,
                "fileWriteEvent/pid": 3308,
                "fileWriteEvent/process": "explorer.exe",
                "fileWriteEvent/processPath": "C:\\Windows",
                "fileWriteEvent/size": 7,
                "fileWriteEvent/textAtLowestOffset": "testest",
                "fileWriteEvent/timestamp": "2018-04-16T08:59:02.061Z",
                "fileWriteEvent/username": "DEMISTO\\User",
                "fileWriteEvent/writes": 1
            },
            "is_false_positive": null,
            "matched_at": "2018-04-16T08:59:10.000Z",
            "matched_source_alerts": [],
            "reported_at": "2018-04-16T08:59:51.693Z",
            "resolution": "ALERT",
            "source": "IOC",
            "url": "/hx/api/v3/alerts/5"
        }
    },
    "File": [
        {
            "Extension": "txt",
            "MD5": "c3add7b947…817c79f7b7bd",
            "Name": "testest - Copy.txt",
            "Path": "C:\\Users\\User\\Documents\\testest - Copy.txt"
        }
    ],
    "IP": [], 
    "RrgistryKey": []
}

fireeye-hx-suppress-alert


Suppress alert by ID

Base Command

fireeye-hx-suppress-alert

Input

Argument Name Description Required
alertId The alert id. The alert id is listed in the output of ‘get-alerts’ command. Optional

Context Output

There is no context output for this command.

Command Example

!fireeye-hx-suppress-alert alertId=2

fireeye-hx-get-indicators


Get a list of indicators

Base Command

fireeye-hx-get-indicators

Input

Argument Name Description Required
category The indicator category. Optional
searchTerm The searchTerm can be any name, category, signature, source, or condition value. Optional
shareMode Determines who can see the indicator. You must belong to the correct authorization group . Possible values are: any, restricted, unrestricted, visible. Optional
sort Sorts the results by the specified field in ascending order. Possible values are: category, activeSince, createdBy, alerted. Optional
createdBy Person who created the indicator. Optional
alerted Whether the indicator resulted in alerts. Possible values are: yes, no. Optional
limit Limit the number of results. Optional

Context Output

Path Type Description
FireEyeHX.Indicators._id Unknown FireEye unique indicator ID.
FireEyeHX.Indicators.name Unknown The indicator name as displayed in the UI.
FireEyeHX.Indicators.description Unknown Indicator description.
FireEyeHX.Indicators.category.name Unknown Catagory name.
FireEyeHX.Indicators.created_by Unknown The “Created By” field as displayed in UI
FireEyeHX.Indicators.active_since Unknown Date indicator became active.
FireEyeHX.Indicators.stats.source_alerts Unknown Total number of source alerts associated with this indicator.
FireEyeHX.Indicators.stats.alerted_agents Unknown Total number of agents with HX alerts associated with this indicator.
FireEyeHX.Indicators.platforms Unknown List of families of operating systems.
FireEyeHX.Indicators.uri_name String URI formatted name of the indicator.
FireEyeHX.Indicators.category.uri_name String URI name of the category.

Command Example

!fireeye-hx-get-indicators limit=2

Context Example

{
    "FireEyeHX": {
        "Indicators": [
            {
                "_id": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
                "_revision": "20211017115618818832920449",
                "active_since": "2021-10-17T11:56:18.818Z",
                "category": {
                    "_id": 2,
                    "name": "Custom",
                    "share_mode": "unrestricted",
                    "uri_name": "Custom",
                    "url": "/hx/api/v3/indicator_categories/custom"
                },
                "create_actor": {
                    "_id": 1001,
                    "username": "api-admin"
                },
                "create_text": null,
                "created_by": "api-admin",
                "description": null,
                "display_name": null,
                "meta": null,
                "name": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
                "platforms": [
                    "win",
                    "osx",
                    "linux"
                ],
                "signature": null,
                "stats": {
                    "active_conditions": 0,
                    "alerted_agents": 0,
                    "source_alerts": 0
                },
                "update_actor": {
                    "_id": 1001,
                    "username": "api-admin"
                },
                "uri_name": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
                "url": "/hx/api/v3/indicators/custom/34757fe7_bdd7_4c85_b0e1_9adfb5e48300"
            },
            {
                "_id": "c6286e1b-10bd-4046-8aff-0dbcc5b1e974",
                "_revision": "20201214155227728995101265",
                "active_since": "2021-09-28T14:44:04.245Z",
                "category": {
                    "_id": 7,
                    "name": "Mandiant Unrestricted Intel",
                    "share_mode": "unrestricted",
                    "uri_name": "mandiant_unrestricted",
                    "url": "/hx/api/v3/indicator_categories/mandiant_unrestricted"
                },
                "create_actor": {
                    "_id": 3,
                    "username": "mandiant"
                },
                "create_text": "General_Windows_unrestricted_2021.09.270849",
                "created_by": "General_Windows_unrestricted_2021.09.270849",
                "description": "This IOC alerts on suspicious filewrites by the legitimate solarwinds process solarwinds.businesslayerhost.exe. solarwinds.businesslayerhost.exe is part of the the Network Performance Monitor (NPM) module of Solarwinds; responsible for detecting and diagnosing network performance issues. This may be an evidence of SUNBURST which is a backdoor that has the ability to spawn and kill processes, write and delete files, set and create registry keys, gather system information, and disable a set of forensic analysis tools and services.This is associated with MITRE ATT&CK (r) Tactic(s): Initial Access and Technique(s): T1195.002.",
                "display_name": "SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY)",
                "meta": null,
                "name": "SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY)",
                "platforms": [
                    "win",
                    "osx",
                    "linux"
                ],
                "signature": null,
                "stats": {
                    "active_conditions": 6,
                    "alerted_agents": 0,
                    "source_alerts": 0
                },
                "update_actor": {
                    "_id": 3,
                    "username": "mandiant"
                },
                "uri_name": "c6286e1b-10bd-4046-8aff-0dbcc5b1e974",
                "url": "/hx/api/v3/indicators/mandiant_unrestricted/c6286e1b_10bd_4046_8aff_0dbcc5b1e974"
            }
        ]
    }
}

Human Readable Output

FireEye HX Get Indicator- None

OS Name Created By Active Since Category Signature Active Condition Hosts With Alerts Source Alerts
win, osx, linux 34757fe7-bdd7-4c85-b0e1-9adfb5e48300 api-admin 2021-10-17T11:56:18.818Z Custom   0 0 0
win, osx, linux SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY) General_Windows_unrestricted_2021.09.270849 2021-09-28T14:44:04.245Z Mandiant Unrestricted Intel   6 0 0

fireeye-hx-get-indicator


Get a specific indicator details

Base Command

fireeye-hx-get-indicator

Input

Argument Name Description Required
category Indicator category. Please use the uri_category value. Required
name Indicator name. Please use the uri_name value. Required

Context Output

Path Type Description
FireEyeHX.Indicators._id Unknown FireEye unique indicator ID.
FireEyeHX.Indicators.name Unknown The indicator name as displayed in the UI.
FireEyeHX.Indicators.description Unknown Indicator description.
FireEyeHX.Indicators.category.name Unknown Catagory name.
FireEyeHX.Indicators.created_by Unknown The “Created By” field as displayed in UI
FireEyeHX.Indicators.active_since Unknown Date indicator became active.
FireEyeHX.Indicators.stats.source_alerts Unknown Total number of source alerts associated with this indicator.
FireEyeHX.Indicators.stats.alerted_agents Unknown Total number of agents with HX alerts associated with this indicator.
FireEyeHX.Indicators.platforms Unknown List of families of operating systems.
FireEyeHX.Conditions._id Unknown FireEye unique condition ID.
FireEyeHX.Conditions.event_type Unknown Event type.
FireEyeHX.Conditions.enabled Unknown Indicates whether the condition is enabled.

Command Example

!fireeye-hx-get-indicator category=Custom name="5def0b16-87bc-42a2-877a-bca45ebcbc9a"

Context Example

{
    "FireEyeHX": {
        "Conditions": [
            {
                "_id": "YhXur1M8FNRDi8GAr9CMbQ==",
                "enabled": true,
                "event_type": "dnsLookupEvent",
                "is_private": false,
                "tests": [
                    {
                        "operator": "equal",
                        "token": "dnsLookupEvent/hostname",
                        "type": "text",
                        "value": "example.lol"
                    }
                ],
                "url": "/hx/api/v3/conditions/YhXur1M8FNRDi8GAr9CMbQ",
                "uuid": "6215eeaf-533c-44d4-838b-c180afd08c6d"
            },
            {
                "_id": "gB7gGHN9RmLNdf8mwuvQ8Q==",
                "enabled": true,
                "event_type": "dnsLookupEvent",
                "is_private": false,
                "tests": [
                    {
                        "operator": "equal",
                        "token": "dnsLookupEvent/hostname",
                        "type": "text",
                        "value": "example.abc"
                    }
                ],
                "url": "/hx/api/v3/conditions/gB7gGHN9RmLNdf8mwuvQ8Q",
                "uuid": "801ee018-737d-4662-8d75-ff26c2ebd0f1"
            }
        ],
        "Indicators": {
            "_id": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
            "_revision": "20210920184007966360614215",
            "active_since": "2021-09-20T18:40:07.966Z",
            "category": {
                "_id": 2,
                "name": "Custom",
                "share_mode": "unrestricted",
                "uri_name": "Custom",
                "url": "/hx/api/v3/indicator_categories/custom"
            },
            "create_actor": {
                "_id": 1001,
                "username": "api-admin"
            },
            "create_text": null,
            "created_by": "api-admin",
            "description": null,
            "display_name": null,
            "meta": null,
            "name": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
            "platforms": [
                "win",
                "osx",
                "linux"
            ],
            "signature": null,
            "stats": {
                "active_conditions": 2,
                "alerted_agents": 0,
                "source_alerts": 0
            },
            "update_actor": {
                "_id": 1001,
                "username": "api-admin"
            },
            "uri_name": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
            "url": "/hx/api/v3/indicators/custom/5def0b16_87bc_42a2_877a_bca45ebcbc9a"
        }
    }
}

Human Readable Output

Indicator “5def0b16-87bc-42a2-877a-bca45ebcbc9a” Alerts on

Event Type Operator Value
dnsLookupEvent equal example.lol
dnsLookupEvent equal example.abc

fireeye-hx-get-host-information


Get information on a host associated with an agent.

Base Command

fireeye-hx-get-host-information

Input

Argument Name Description Required
agentId The agent ID. If the agent ID is not specified, the host Name must be specified. Optional
hostName The host name. If the host name is not specified, the agent ID must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Hosts._id Unknown FireEye HX Agent ID.
FireEyeHX.Hosts.agent_version Unknown The agent version.
FireEyeHX.Hosts.excluded_from_containment Unknown Determines whether the host is excluded from containment.
FireEyeHX.Hosts.containment_missing_software Unknown Boolean value to indicate for containment missing software.
FireEyeHX.Hosts.containment_queued Unknown Determines whether the host is queued for containment.
FireEyeHX.Hosts.containment_state Unknown The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu.
FireEyeHX.Hosts.stats.alerting_conditions Unknown The number of conditions that have alerted for the host.
FireEyeHX.Hosts.stats.alerts Unknown Total number of alerts, including exploit-detection alerts.
FireEyeHX.Hosts.stats.exploit_blocks Unknown The number of blocked exploits on the host.
FireEyeHX.Hosts.stats.malware_alerts Unknown The number of malware alerts associated with the host.
FireEyeHX.Hosts.hostname Unknown The host name.
FireEyeHX.Hosts.domain Unknown Domain name.
FireEyeHX.Hosts.timezone Unknown Host time zone.
FireEyeHX.Hosts.primary_ip_address Unknown The host IP address.
FireEyeHX.Hosts.last_poll_timestamp Unknown The timestamp of the last system poll preformed on the host.
FireEyeHX.Hosts.initial_agent_checkin Unknown Timestamp of the initial agent check-in.
FireEyeHX.Hosts.last_alert_timestamp Unknown The time stamp of the last alert for the host.
FireEyeHX.Hosts.last_exploit_block_timestamp Unknown Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked.
FireEyeHX.Hosts.os.product_name Unknown Specific operating system
FireEyeHX.Hosts.os.bitness Unknown OS Bitness.
FireEyeHX.Hosts.os.platform Unknown Family of operating systems. Valid values are win, osx, and linux.
FireEyeHX.Hosts.primary_mac Unknown The host MAC address.

Command Example

!fireeye-hx-get-host-information hostName=”DESKTOP-XXX”

Context Output

{
    "FireEyeHX": {
        "Hosts": {
            "last_alert": {
                "url": "/hx/api/v3/alerts/5", 
                "_id": 5
            }, 
            "domain": "DEMISTO", 
            "last_exploit_block_timestamp": null, 
            "containment_state": "normal", 
            "timezone": "Eastern Daylight Time", 
            "gmt_offset_seconds": -14400, 
            "initial_agent_checkin": "2018-03-26T14:21:31.273Z", 
            "stats": {
                "alerting_conditions": 1, 
                "exploit_alerts": 0, 
                "acqs": 11, 
                "malware_false_positive_alerts": 0, 
                "alerts": 1, 
                "exploit_blocks": 0, 
                "malware_cleaned_count": 0, 
                "malware_alerts": 0, 
                "malware_quarantined_count": 0
            }, 
            "primary_mac": "XX-XX-XX-XX-XX-XX", 
            "hostname": "DESKTOP-XXX", 
            "primary_ip_address": "^^^XX.XX.XX.XX^^^", 
            "last_audit_timestamp": "2018-05-03T13:59:23.000Z", 
            "last_alert_timestamp": "2018-04-16T08:59:51.693+00:00", 
            "containment_queued": false, 
            "sysinfo": {
                "url": "/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
            }, 
            "last_exploit_block": null, 
            "reported_clone": false, 
            "url": "/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT", 
            "excluded_from_containment": false, 
            "last_poll_timestamp": "2018-05-03T14:01:22.000Z", 
            "last_poll_ip": "^^^XX.XX.XX.XX^^^", 
            "containment_missing_software": false, 
            "_id": " uGvnGVpZkDSFySf2ZOiT ", 
            "os": {
                "kernel_version": null, 
                "platform": "win", 
                "patch_level": null, 
                "bitness": "64-bit", 
                "product_name": "Windows 10 Enterprise Evaluation"
            }, 
            "agent_version": "26.21.10"
        }
    },
    "Endpoint": {
        "MACAddress": "XX-XX-XX-XX-XX-XX", 
        "Domain": "DEMISTO", 
        "IPAddress": "^^^XX.XX.XX.XX^^^", 
        "Hostname": "DESKTOP-XXX", 
        "OSVersion": "Windows 10 Enterprise Evaluation", 
        "OS": "win", 
        "ID": " uGvnGVpZkDSFySf2ZOiT "
    }, 
}

fireeye-hx-get-alert


Get details of a specific alert

Base Command

fireeye-hx-get-alert

Input

Argument Name Description Required
alertId The alert ID. Required

Context Output

Path Type Description
FireEyeHX.Alerts._id Unknown FireEye alert ID.
FireEyeHX.Alerts.agent._id Unknown FireEye agent ID.
FireEyeHX.Alerts.agent.containment_state Unknown Host containment state.
FireEyeHX.Alerts.condition._id Unknown The condition unique ID.
FireEyeHX.Alerts.event_at Unknown Time when the event occoured.
FireEyeHX.Alerts.matched_at Unknown Time when the event was matched.
FireEyeHX.Alerts.reported_at Unknown Time when the event was reported.
FireEyeHX.Alerts.source Unknown Source of alert.
FireEyeHX.Alerts.matched_source_alerts._id Unknown Source alert ID.
FireEyeHX.Alerts.matched_source_alerts.appliance_id Unknown Appliance ID
FireEyeHX.Alerts.matched_source_alerts.meta Unknown Source alert meta.
FireEyeHX.Alerts.matched_source_alerts.indicator_id Unknown Indicator ID.
FireEyeHX.Alerts.resolution Unknown Alert resulotion.
FireEyeHX.Alerts.event_type Unknown Event type.

fireeye-hx-file-acquisition


Aquire a specific file as a password protected zip file. The password for unlocking the zip file is ‘unzip-me’.

Base Command

fireeye-hx-file-acquisition

Input

Argument Name Description Required
fileName The file name. Required
filePath The file path. Required
acquireUsing Whether to aqcuire the file using the API or RAW. By default, raw file will be acquired. Use API option when file is encrypted. Possible values are: API, RAW. Optional
agentId The agent ID associated with the host that holds the file. If the hostName is not specified, the agentId must be specified. Optional
hostName The host that holds the file. If the agentId is not specified, hostName must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Acquisitions.Files._id Unknown The acquisition unique ID.
FireEyeHX.Acquisitions.Files.state Unknown The acquisition state.
FireEyeHX.Acquisitions.Files.md5 Unknown File md5.
FireEyeHX.Acquisitions.Files.req_filename Unknown The file name.
FireEyeHX.Acquisitions.Files.req_path Unknown The file path.
FireEyeHX.Acquisitions.Files.host._id Unknown FireEye HX agent ID.

Command Example

!fireeye-hx-file-acquisition fileName="test.txt"filePath="C:\\Users\\user\\Documents" hostName="DESKTOP-DES01"

Context Output

"FireEyeHX": {
        "Acquisitions": {
            "Files": {
                "_id": 13,
                "_revision": "206073441021688",
                "alert": null,
                "comment": null,
                "condition": null,
                "error_message": "The acquisition completed with issues.",
                "external_id": null,
                "finish_time": "2018-04-26T07:34:14.100Z",
                "host": {
                    "_id": "uGvnGVpZkKeySf2ZT",
                    "url": "/hx/api/v3/hosts/ uGvnGVpZkKeySf2ZT "
                },
                "indicator": null,
                "md5": "ee26908bf9…64b37da4754a",
                "req_filename": "ex.txt",
                "req_path": "C:\\Users\\user\\Documents",
                "req_use_api": null,
                "request_actor": {
                    "_id": 1001,
                    "username": "api"
                },
                "request_time": "2018-04-26T07:33:03.000Z",
                "state": "COMPLETE",
                "url": "/hx/api/v3/acqs/files/13",
                "zip_passphrase": "unzip-me"
            }
        }
    }

fireeye-hx-delete-file-acquisition


Delete the file acquisition, by ID.

Base Command

fireeye-hx-delete-file-acquisition

Input

Argument Name Description Required
acquisitionId The acquisition ID. Required

Context Output

There is no context output for this command.

Command Example

!fireeye-hx-delete-file-acquisition acquisitionId=10

fireeye-hx-data-acquisition


Start a data acquisition process to gather artifacts from the system disk and memory. The data is fetched as mans file.

Base Command

fireeye-hx-data-acquisition

Input

Argument Name Description Required
script Acquisition script in JSON format. Optional
scriptName The script name. If the Acquisition script is specified, the script name must be specified as well. Optional
defaultSystemScript Use default script. Select the host system. Possible values are: osx, win, linux. Optional
agentId The agent ID. If the host name is not specified, the agent ID must be specified. Optional
hostName The host name. If the agent ID is not specified, the host name must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Acquisitions.Data._id Unknown The acquisition unique ID.
FireEyeHX.Acquisitions.Data.state Unknown The acquisition state.
FireEyeHX.Acquisitions.Data.md5 Unknown File md5.
FireEyeHX.Acquisitions.Data.finish_time Unknown Time when the acquisition was finished.
FireEyeHX.Acquisitions.Data.host._id unknown Agent ID

Command Example

! fireeye-hx-data-acquisition hostName="DESKTOP-DES01" defaultSystemScript=win

Contex Example

{
    "FireEyeHX": {
        "Acquisitions": {
            "Data": {
                "comment": null, 
                "zip_passphrase": null, 
                "request_actor": {
                    "username": "api", 
                    "_id": 1001
                }, 
                "name": "test", 
                "script": {
                    "download": "/hx/api/v3/scripts/131ab1da5086fe09f5a210437de366007867fa26.json", 
                    "url": "/hx/api/v3/scripts/^^^131ab1da5086fe09f5a210437de366007867fa26^^^", 
                    "_id": "^^^131ab1da5086fe09f5a210437de366007867fa26^^^"
                }, 
                "finish_time": "2018-05-15T11:58:18.541Z", 
                "_revision": "20180515115818542250101787", 
                "error_message": "The triage completed with issues.", 
                "state": "COMPLETE", 
                "request_time": "2018-05-15T11:57:22.000Z", 
                "url": "/hx/api/v3/acqs/live/28", 
                "host": {
                    "url": "/hx/api/v3/hosts/uGvnGVpZkM4bKeySf2ZOiT", 
                    "_id": "uGvnGVpZkXXXX2ZOiT"
                }, 
                "download": "/hx/api/v3/acqs/live/28.mans", 
                "_id": 28, 
                "external_id": null, 
                "md5": null
            }
        }
    }, 
    "File": {
        "Info": "mans", 
        "SHA1": "^^^4374d09a27ef85XXXXX66785c040d7febff7d8^^^", 
        "Name": "agent_uGvnGVpZkMXXXX2ZOiT_data.mans", 
        "Extension": "mans", 
        "Size": 5154, 
        "EntryID": "383@1", 
        "SSDeep": "96:JraN9hyFIVls4Dst99i462teLuf0XXXXyU2y46Gd/pV:xapyFIVibPi462teLuf0TXdLNJLU23dt", 
        "SHA256": "7944d5e86ce2bXXXXe154d4c2923ddf47016a07b84b460f08b0f2f", 
        "Type": "Zip archive data, at least v2.0 to extract\n", 
        "MD5": "^^^c24a2c4aeXXXXf89e1e012dae^^^"
    }
}

fireeye-hx-delete-data-acquisition


Delete data acquisition.

Base Command

fireeye-hx-delete-data-acquisition

Input

Argument Name Description Required
acquisitionId The acquisition ID. Required

Context Output

There is no context output for this command.

Command Example

!fireeye-hx-delete-data-acquisition acquisitionId=10

fireeye-hx-search


Search endpoints to check all hosts or a subset of hosts for a specific file or indicator.

Base Command

fireeye-hx-search

Input

Argument Name Description Required
agentsIds IDs of agents to be searched. Optional
hostsNames Names of hosts to be searched. Optional
hostSet Id of host set to be searched. Optional
limit Limit results count (once limit is reached, the search is stopped). Optional
exhaustive Should search be exhaustive or quick. Possible values are: yes, no. Default is True. Optional
ipAddress A valid IPv4 address to search for. Optional
ipAddressOperator Which operator to apply to the given IP address. Possible values are: equals, not equals. Optional
fileMD5Hash A 32-character MD5 hash value to search for. Optional
fileMD5HashOperator Which operator to apply to the given MD5 hash. Possible values are: equals, not equals. Optional
fileFullPath Full path of file to search. Optional
fileFullPathOperator Which operator to apply to the given file path. Possible values are: equals, not equals, contains, not contains. Optional
dnsHostname DNS value to search for. Optional
dnsHostnameOperator Which operator to apply to the given DNS. Possible values are: equals, not equals, contains, not contains. Optional
stopSearch Method in which search should be stopped after finding <limit> number of results. Possible values are: stopAndDelete, stop. Optional

Context Output

Path Type Description
FireEyeHX.Search.Results.Timestamp - Modified string Time when the entry was last modified
FireEyeHX.Search.Results.File Text Written string The file text content
FireEyeHX.Search.Results.File Name string Name of the file
FireEyeHX.Search.Results.File Full Path string The full path of the file
FireEyeHX.Search.Results.File Bytes Written string Number of bytes written to the file
FireEyeHX.Search.Results.Size in bytes string Size of the file in bytes
FireEyeHX.Search.Results.Browser Version string Version of the browser
FireEyeHX.Search.Results.Browser Name string Name of the browser
FireEyeHX.Search.Results.Cookie Name string Name of the cookie
FireEyeHX.Search.Results.DNS Hostname string Name of the DNS host
FireEyeHX.Search.Results.URL string The event URL
FireEyeHX.Search.Results.Username string The event username
FireEyeHX.Search.Results.File MD5 Hash string MD5 hash of the file
FireEyeHX.Search.HostID string ID of the host
FireEyeHX.Search.HostName string Name of host
FireEyeHX.Search.HostUrl string Inner FireEye host url
FireEyeHX.Search.SearchID string ID of performed search
FireEyeHX.Search.Results.Timestamp - Accessed string Last accessed time
FireEyeHX.Search.Results.Port number Port
FireEyeHX.Search.Results.Process ID string ID of the process
FireEyeHX.Search.Results.Local IP Address string Local IP Address
FireEyeHX.Search.Results.Local IP Address string Local IP Address
FireEyeHX.Search.Results.Local Port number Local Port
FireEyeHX.Search.Results.Username string Username
FireEyeHX.Search.Results.Remote Port number Remote Port
FireEyeHX.Search.Results.IP Address string IP Address
FireEyeHX.Search.Results.Process Name string Process Name
FireEyeHX.Search.Results.Timestamp - Event string Timestamp - Event
FireEyeHX.Search.Results.type string The type of the event
FireEyeHX.Search.Results.id string ID of the result

fireeye-hx-get-host-set-information


Get a list of all host sets known to your HX Series appliance

Base Command

fireeye-hx-get-host-set-information

Input

Argument Name Description Required
hostSetID ID of a specific host set to get. Optional
offset Specifies which record to start with in the response. The offset value must be an unsigned 32-bit integer. The default is 0. Optional
limit Specifies how many records are returned. The limit value must be an unsigned 32-bit integer. The default is 50. Optional
search Searches the names of all host sets connected to the specified HX appliance. Optional
sort Sorts the results by the specified field in ascending or descending order. The default is sorting by name in ascending order. Sortable fields are _id (host set ID) and name (host set name). Optional
name Specifies the name of host set to look for. Optional
type Specifies the type of host sets to search for. Optional

Context Output

Path Type Description
FireEyeHX.HostSets._id number host set id
FireEyeHX.HostSets._revision string Revision number
FireEyeHX.HostSets.name string Host set name
FireEyeHX.HostSets.type string Host set type (static/dynamic/hidden)
FireEyeHX.HostSets.url string Host set FireEye url

Command Example


#### Context Example

```json
{
    "FireEyeHX": {
        "HostSets": {
            "_id": 1001,
            "_revision": "20210308150955358783164361",
            "name": "Demisto",
            "type": "venn",
            "url": "/hx/api/v3/host_sets/1001"
        }
    }
}

Human Readable Output

FireEye HX Get Host Sets Information

Name ID Type
Demisto 1001 venn

fireeye-hx-create-indicator


Create new indicator

Base Command

fireeye-hx-create-indicator

Input

Argument Name Description Required
category The indicator category. Required

Context Output

Path Type Description
FireEyeHX.Indicators.active_since date Date indicator became active.
FireEyeHX.Indicators.meta string Meta data for new indicator
FireEyeHX.Indicators.display_name string The indicator display name
FireEyeHX.Indicators.name string The indicator name as displayed in the UI.
FireEyeHX.Indicators.created_by string The “Created By” field as displayed in UI
FireEyeHX.Indicators.url string The data URL
FireEyeHX.Indicators.create_text Unknown The indicator create text
FireEyeHX.Indicators.platforms string List of families of operating systems.
FireEyeHX.Indicators.create_actor._id number The ID of the actor
FireEyeHX.Indicators.create_actor.username string Actor user name
FireEyeHX.Indicators.signature string Signature of indicator
FireEyeHX.Indicators._revision string Indicator revision
FireEyeHX.Indicators._id string FireEye unique indicator ID.
FireEyeHX.Indicator.description string Indicator description
FireEyeHX.Indicators.category._id number Category ID
FireEyeHX.Indicators.category.name string Category name
FireEyeHX.Indicators.category.share_mode string Category share mode
FireEyeHX.Indicators.category.uri_name string Category uri name
FireEyeHX.Indicators.category.url string Category URL
FireEyeHX.Indicators.uri_name string The indicator uri name
FireEyeHX.Indicators.stats.active_conditions number Indicator active conditions
FireEyeHX.Indicators.stats.alerted_agents number Total number of agents with HX alerts associated with this indicator.
FireEyeHX.Indicators.stats.source_alerts number Total number of source alerts associated with this indicator.
FireEyeHX.Indicators.update_actor._id number Update actor ID
FireEyeHX.Indicators.update_actor.username string Update actor name

fireeye-hx-append-conditions


Add conditions to an indicator. Conditions can be MD5, hash values, domain names and IP addresses.

Base Command

fireeye-hx-append-conditions

Input

Argument Name Description Required
category The indicator category. Please use the uri_category value. Required
name The name of the indicator. Please use the uri_name value. Required
condition A list of conditions to add. The list can include a list of IPv4 addresses, MD5 files, and domain names. For example: example.netexample.orgexample.lol. Required

Context Output

There is no context output for this command.

fireeye-hx-get-all-hosts-information


Get information on all hosts

Base Command

fireeye-hx-get-all-hosts-information

Input

| Argument Name | Description | Required |
| — | — | — |

Context Output

Path Type Description
FireEyeHX.Hosts._id Unknown FireEye HX Agent ID.
FireEyeHX.Hosts.agent_version Unknown The agent version.
FireEyeHX.Hosts.excluded_from_containment Unknown Determines whether the host is excluded from containment.
FireEyeHX.Hosts.containment_missing_software Unknown Boolean value to indicate for containment missing software.
FireEyeHX.Hosts.containment_queued Unknown Determines whether the host is queued for containment.
FireEyeHX.Hosts.containment_state Unknown The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu.
FireEyeHX.Hosts.stats.alerting_conditions Unknown The number of conditions that have alerted for the host.
FireEyeHX.Hosts.stats.alerts Unknown Total number of alerts, including exploit-detection alerts.
FireEyeHX.Hosts.stats.exploit_blocks Unknown The number of blocked exploits on the host.
FireEyeHX.Hosts.stats.malware_alerts Unknown The number of malware alerts associated with the host.
FireEyeHX.Hosts.hostname Unknown The host name.
FireEyeHX.Hosts.domain Unknown Domain name.
FireEyeHX.Hosts.timezone Unknown Host time zone.
FireEyeHX.Hosts.primary_ip_address Unknown The host IP address.
FireEyeHX.Hosts.last_poll_timestamp Unknown The timestamp of the last system poll preformed on the host.
FireEyeHX.Hosts.initial_agent_checkin Unknown Timestamp of the initial agent check-in.
FireEyeHX.Hosts.last_alert_timestamp Unknown The time stamp of the last alert for the host.
FireEyeHX.Hosts.last_exploit_block_timestamp Unknown Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked.
FireEyeHX.Hosts.os.product_name Unknown Specific operating system
FireEyeHX.Hosts.os.bitness Unknown OS Bitness.
FireEyeHX.Hosts.os.platform Unknown Family of operating systems. Valid values are win, osx, and linux.
FireEyeHX.Hosts.primary_mac Unknown The host MAC address.

Command Example


#### Context Example

```json
{
    "Endpoint": [
        {
            "Domain": "WORKGROUP",
            "Hostname": "WIN10X64",
            "ID": "Hqb2ns3oui1fpzg0BxI1Ch",
            "IPAddress": "1.1.1.1",
            "MACAddress": "00-50-56-89-1c-5b",
            "OS": "win",
            "OSVersion": "Windows 10 Pro"
        },
        {
            "Domain": "localdomain",
            "Hostname": "localhost",
            "ID": "GfLI00Q4zpidezw9I11rV6",
            "IPAddress": "1.1.1.1",
            "MACAddress": "00-50-56-89-e7-22",
            "OS": "linux",
            "OSVersion": "CentOS Linux 7 (Core)"
        }
    ],
    "FireEyeHX": {
        "Hosts": {
            "Agent ID": "GfLI00Q4zpidezw9I11rV6",
            "Agent Version": "31.28.17",
            "Containment State": "normal",
            "Domain": "localdomain",
            "Host IP": "1.1.1.1",
            "Host Name": "localhost",
            "Last Alert": null,
            "Last Poll": "2021-10-18T14:02:32.000Z",
            "OS": "linux"
        }
    }
}

Human Readable Output

FireEye HX Get Hosts Information

Host Name Host IP Agent ID Agent Version OS Last Poll Containment State Domain Last Alert
WIN10X64 1.1.1.1 Hqb2ns3oui1fpzg0BxI1Ch 31.28.17 win 2021-10-18T13:59:44.000Z normal WORKGROUP _id: 2
url: /hx/api/v3/alerts/2
localhost 1.1.1.1 GfLI00Q4zpidezw9I11rV6 31.28.17 linux 2021-10-18T14:02:32.000Z normal localdomain  

fireeye-hx-initiate-data-acquisition


Initiate a data acquisition process to gather artifacts from the system disk and memory

Base Command

fireeye-hx-initiate-data-acquisition

Input

Argument Name Description Required
script Acquisition script in JSON format. Optional
scriptName The script name. If the Acquisition script is specified, the script name must be specified as well. Optional
defaultSystemScript Use default script. Select the host system. Possible values are: osx, win, linux. Optional
agentId The agent ID. If the host name is not specified, the agent ID must be specified. Optional
hostName The host name. If the agent ID is not specified, the host name must be specified. Optional

Context Output

Path Type Description
FireEyeHX.Acquisitions.Data._id unknown The acquisition unique ID.
FireEyeHX.Acquisitions.Data.state unknown The acquisition state
FireEyeHX.Acquisitions.Data.md5 unknown File md5
FireEyeHX.Acquisitions.Data.host._id unknown Agent ID
FireEyeHX.Acquisitions.Data.host.hostname unknown Hostname
FireEyeHX.Acquisitions.Data.instance unknown FIreEye HX instance
FireEyeHX.Acquisitions.Data.finish_time unknown Time when the acquisition finished

Command Example


#### Human Readable Output

### fireeye-hx-get-data-acquisition

***
Gather artifacts from the system disk and memory for the given acquisition id. The data is fetched as mans file

#### Base Command

`fireeye-hx-get-data-acquisition`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| acquisitionId | The acquisition unique ID. | Required |

#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeHX.Acquisitions.Data._id | unknown | The acquisition unique ID. |
| FireEyeHX.Acquisitions.Data.state | unknown | The acquisition state. |
| FireEyeHX.Acquisitions.Data.md5 | unknown | File md5. |
| FireEyeHX.Acquisitions.Data.host._id | unknown | Agent ID |
| FireEyeHX.Acquisitions.Data.finish_time | unknown | Time when the acquisition finished |
| FireEyeHX.Acquisitions.Data.host.hostname | unknown | Hostname |
| FireEyeHX.Acquisitions.Data.instance | unknown | FIreEye HX instance |

#### Command Example

Human Readable Output

Error Responses - Timeout Error

Timeout error indicates that time limitation for the command has exceeded before results are returned.

To resolve this issue, configure new time limitation for the command.

  1. Navigate to Settings > About > Troubleshooting > Server Configuration.
  2. click Add Server Configuration.
  3. Set the key field using this format: FireEye HX.<command-name>.timeout.
  4. Set the value field to the desired time limit for the command to run (in minutes).

Known Limitations

Acquisitions limitations

  • Acquisitions are stored for 14 days or until the aggregate size of all acquisitions exceeds the acquisition space limit, which is from 30 GB to 9 TB, depending on the HX Series appliance.
  • When the acquisition space is completely full and automatic triages fill 10 percent of the acquisition space, the HX Series appliance reclaims disk space by removing automatic triage collections.
  • When the acquisition space is 90 percent full, no new acquisitions can be created, and bulk acquisitions that are running might be canceled.

Containment Limitations

  • Some hosts cannot be contained.
  • The time it takes to contain a host varies, based on factors such as agent connectivity, network traffic, and other jobs running in your environment.
  • You can only contain a host if the agent package for that host is available on the HX Series appliance.

Command Timeout

The following commands have high potential to exceed the default time limit for a running command. To avoid command timeout, change the command timeout settings.

  • fireeye-hx-search
  • fireeye-hx-data-acquisition
  • fireeye-hx-file-acquisition

Configure Command Timeout

  1. Navigate to Settings > About > Troubleshooting.
  2. In the Server Configuration section, click Add Server Configuration.
  3. Set the Key field using this format: FireEye HX.timeout
  4. Set the Value field to the timeout you need (in minutes).

Configuration parameters

  • server — Server URL (e.g. https://192.168.0.1:3000) (required)
  • credentials — Credentials (required)
  • version — Version (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • fetch_limit — Fetch limit
  • incidentFetchInterval — Incidents Fetch Interval

Commands (19)

  • fireeye-hx-append-conditions Deprecated

    Add conditions to an indicator. Conditions can be MD5, hash values, domain names and IP addresses.

  • fireeye-hx-cancel-containment Deprecated

    Release a specific host from containment.

  • fireeye-hx-create-indicator Deprecated

    Create new indicator.

  • fireeye-hx-data-acquisition Deprecated

    Start a data acquisition process to gather artifacts from the system disk and memory. The data is fetched as mans file.

  • fireeye-hx-delete-data-acquisition Deprecated

    Delete data acquisition.

  • fireeye-hx-delete-file-acquisition Deprecated

    Delete the file acquisition, by ID.

  • fireeye-hx-file-acquisition Deprecated

    Aquire a specific file as a password protected zip file. The password for unlocking the zip file is 'unzip-me'.

  • fireeye-hx-get-alert Deprecated

    Get details of a specific alert.

  • fireeye-hx-get-alerts Deprecated

    Get a list of alerts, use the different arguments to filter the results returned.

  • fireeye-hx-get-all-hosts-information Deprecated

    Get information on all hosts.

  • fireeye-hx-get-data-acquisition Deprecated

    Gather artifacts from the system disk and memory for the given acquisition id. The data is fetched as mans file.

  • fireeye-hx-get-host-information Deprecated

    Get information on a host associated with an agent.

  • fireeye-hx-get-host-set-information Deprecated

    Get a list of all host sets known to your HX Series appliance.

  • fireeye-hx-get-indicator Deprecated

    Get a specific indicator details.

  • fireeye-hx-get-indicators Deprecated

    Get a list of indicators.

  • fireeye-hx-host-containment Deprecated

    Apply containment for a specific host, so that it no longer has access to other systems.

  • fireeye-hx-initiate-data-acquisition Deprecated

    Initiate a data acquisition process to gather artifacts from the system disk and memory.

  • fireeye-hx-search Deprecated

    Search endpoints to check all hosts or a subset of hosts for a specific file or indicator.

  • fireeye-hx-suppress-alert Deprecated

    Suppress alert by ID.

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

"""

IMPORTS

"""
import base64
import json
import os
import re
import time

import requests

# disable insecure warnings
requests.packages.urllib3.disable_warnings()

"""

HANDLE PROXY

"""


def set_proxies():

    if not demisto.params().get('proxy', False):
        del os.environ['HTTP_PROXY']
        del os.environ['HTTPS_PROXY']
        del os.environ['http_proxy']
        del os.environ['https_proxy']


"""

GLOBAL VARS

"""
TOKEN = ''
SERVER_URL = demisto.params()['server']
USERNAME = demisto.params()['credentials']['identifier']
PASSWORD = demisto.params()['credentials']['password']
PASSWORD = PASSWORD.encode('utf-8')
USE_SSL = not demisto.params()['insecure']
VERSION = demisto.params()['version']
GET_HEADERS = {
    'Accept': 'application/json'
}
POST_HEADERS = {
    'Accept': 'application/json',
    'Content-type': 'application/json'
}
PATCH_HEADERS = {
    'Content-Type': 'text/plain'
}
BASE_PATH = '{}/hx/api/{}'.format(SERVER_URL, VERSION)
INDICATOR_MAIN_ATTRIBUTES = [
    'OS',
    'Name',
    'Created By',
    'Active Since',
    'Category',
    'Signature',
    'Active Condition',
    'Hosts With Alerts',
    'Source Alerts'
]
ALERT_MAIN_ATTRIBUTES = [
    'Alert ID',
    'Reported',
    'Event Type',
    'Agent ID'
]
HOST_MAIN_ATTRIBUTES = [
    'Host Name',
    'Host IP',
    'Agent ID',
    'Agent Version',
    'OS',
    'Last Poll',
    'Containment State',
    'Domain',
    'Last Alert'
]
HOST_SET_MAIN_ATTRIBUTES = [
    'Name',
    'ID',
    'Type'
]
# scripts for data acquisitions
STANDART_INVESTIGATIVE_DETAILS_OSX = {
    "commands": [
        {
            "name": "sysinfo"
        },
        {
            "name": "disks"
        },
        {
            "name": "volumes"
        },
        {
            "name": "useraccounts"
        },
        {
            "name": "groups"
        },
        {
            "name": "files-api",
            "parameters": [
                {
                    "name": "Path",
                    "value": "/"
                },
                {
                    "name": "Regex",
                    "value": "^(?:Applications|Library|System|User|bin|cores|opt|private|sbin|usr)+"
                },
                {
                    "name": "Include Remote Locations",
                    "value": False
                },
                {
                    "name": "Depth",
                    "value": -1
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": False
                },
                {
                    "name": "AND Operator",
                    "value": False
                },
                {
                    "name": "Include Files",
                    "value": True
                },
                {
                    "name": "Include Directories",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                }
            ]
        },
        {
            "name": "persistence",
            "parameters": [
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Preserve Times",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": False
                }
            ]
        },
        {
            "name": "tasks",
            "parameters": [
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                }
            ]
        },
        {
            "name": "processes-api"
        },
        {
            "name": "urlhistory",
            "parameters": [
                {
                    "name": "TargetBrowser",
                    "value": "Chrome"
                },
                {
                    "name": "TargetBrowser",
                    "value": "Firefox"
                },
                {
                    "name": "TargetBrowser",
                    "value": "Safari"
                }
            ]
        },
        {
            "name": "quarantine-events"
        },
        {
            "name": "ports"
        },
        {
            "name": "services",
            "parameters": [
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                }
            ]
        },
        {
            "name": "stateagentinspector",
            "parameters": [
                {
                    "name": "eventTypes",
                    "value": []
                }
            ]
        },
        {
            "name": "syslog"
        }
    ]
}
STANDART_INVESTIGATIVE_DETAILS_LINUX = {
    "commands": [
        {
            "name": "sysinfo"
        },
        {
            "name": "files-api",
            "parameters": [
                {
                    "name": "Path",
                    "value": "/"
                },
                {
                    "name": "Regex",
                    "value": "^(?:usr|lib|lib64|opt|home|sbin|bin|etc|root)+"
                },
                {
                    "name": "Include Remote Locations",
                    "value": False
                },
                {
                    "name": "Depth",
                    "value": -1
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "AND Operator",
                    "value": False
                },
                {
                    "name": "Include Files",
                    "value": True
                },
                {
                    "name": "Include Directories",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                }
            ]
        },
        {
            "name": "processes-api"
        },
        {
            "name": "ports"
        },
        {
            "name": "shell-history",
            "parameters": [
                {
                    "name": "ShellList",
                    "value": [
                        "bash",
                        "zsh",
                        "ksh93"
                    ]
                }
            ]
        }
    ]
}
STANDART_INVESTIGATIVE_DETAILS_WIN = {
    "commands": [
        {
            "name": "sysinfo"
        },
        {
            "name": "disks",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "volumes",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "useraccounts",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "prefetch",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "files-raw",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "Active Files",
                    "value": True
                },
                {
                    "name": "Deleted Files",
                    "value": True
                },
                {
                    "name": "Parse NTFS INDX Buffers",
                    "value": True
                },
                {
                    "name": "Path",
                    "value": "%systemdrive%"
                },
                {
                    "name": "Depth",
                    "value": -1
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Analyze Entropy",
                    "value": False
                },
                {
                    "name": "Enumerate Imports",
                    "value": False
                },
                {
                    "name": "Enumerate Exports",
                    "value": False
                },
                {
                    "name": "Analyze File Anomalies",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": False
                },
                {
                    "name": "Strings",
                    "value": False
                },
                {
                    "name": "AND Operator",
                    "value": False
                },
                {
                    "name": "Include Files",
                    "value": True
                },
                {
                    "name": "Include Directories",
                    "value": True
                },
                {
                    "name": "Get Resources",
                    "value": False
                },
                {
                    "name": "Get Resource Data",
                    "value": False
                },
                {
                    "name": "Get Version Info",
                    "value": False
                }
            ]
        },
        {
            "name": "persistence",
            "parameters": [
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Preserve Times",
                    "value": False
                },
                {
                    "name": "Enumerate Imports",
                    "value": False
                },
                {
                    "name": "Enumerate Exports",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "Analyze Entropy",
                    "value": False
                },
                {
                    "name": "Analyze File Anomalies",
                    "value": False
                },
                {
                    "name": "Get Resources",
                    "value": False
                },
                {
                    "name": "Get Version Info",
                    "value": False
                },
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "registry-raw",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "Type",
                    "value": "All"
                }
            ]
        },
        {
            "name": "tasks",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                },
                {
                    "name": "raw mode",
                    "value": False
                }
            ]
        },
        {
            "name": "eventlogs",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "processes-memory",
            "parameters": [
                {
                    "name": "Preserve Times",
                    "value": False
                },
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "MemD5",
                    "value": False
                },
                {
                    "name": "enumerate imports",
                    "value": True
                },
                {
                    "name": "enumerate exports",
                    "value": True
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "sections",
                    "value": True
                },
                {
                    "name": "ports",
                    "value": True
                },
                {
                    "name": "handles",
                    "value": True
                },
                {
                    "name": "detect injected dlls",
                    "value": True
                },
                {
                    "name": "raw mode",
                    "value": False
                },
                {
                    "name": "strings",
                    "value": False
                }
            ]
        },
        {
            "name": "urlhistory",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "GetThumbnails",
                    "value": False
                },
                {
                    "name": "GetIndexedPageContent",
                    "value": False
                }
            ]
        },
        {
            "name": "ports",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                }
            ]
        },
        {
            "name": "services",
            "parameters": [
                {
                    "name": "Prevent Hibernation",
                    "value": True
                },
                {
                    "name": "MD5",
                    "value": True
                },
                {
                    "name": "SHA1",
                    "value": False
                },
                {
                    "name": "SHA256",
                    "value": False
                },
                {
                    "name": "Verify Digital Signatures",
                    "value": True
                },
                {
                    "name": "Preserve Times",
                    "value": False
                },
                {
                    "name": "raw mode",
                    "value": False
                }
            ]
        },
        {
            "name": "stateagentinspector",
            "parameters": [
                {
                    "name": "eventTypes",
                    "value": []
                }
            ]
        }
    ]
}

SYS_SCRIPT_MAP = {
    'osx': STANDART_INVESTIGATIVE_DETAILS_OSX,
    'win': STANDART_INVESTIGATIVE_DETAILS_WIN,
    'linux': STANDART_INVESTIGATIVE_DETAILS_LINUX
}

"""

COMMAND HANDLERS

"""


def get_token_request():
    """
    returns a token on successful request
    """

    url = '{}/token'.format(BASE_PATH)

    # basic authentication
    try:
        response = requests.request(
            'GET',
            url,
            headers=GET_HEADERS,
            verify=USE_SSL,
            auth=(USERNAME, PASSWORD)
        )
    except requests.exceptions.SSLError as e:
        LOG(e)
        raise ValueError('An SSL error occurred when trying to connect to the server.\
        Consider configuring unsecure connection in the integration settings')

    # handle request failure
    if response.status_code not in range(200, 205):
        message = parse_error_response(response)
        raise ValueError('Token request failed with status code {}\n{}'.format(response.status_code, message))
    # successful request
    response_headers = response.headers
    token = response_headers.get('X-FeApi-Token')
    return token


def get_token():

    token = get_token_request()
    if token:
        return token
    raise Exception('Failed to get a token, unexpected response structure from the server')


"""

HOST INFORMATION

"""


def get_host_by_agent_request(agent_id):
    """
    returns the response body

    raises an exception on:

        - http request failure
        - response status code different from 200
    """
    url = '{}/hosts/{}'.format(BASE_PATH, agent_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )

    # successful request
    try:
        return response.json()['data']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to get host information - unexpected response structure from the server.')


def get_host_information():
    """

    return the host information to the war room, given an agentId or hostName from input.

    """
    args = demisto.args()

    if not args.get('agentId') and not args.get('hostName'):
        raise ValueError('Please provide either agentId or hostName')

    host = {}  # type: Dict[str, str]
    if args.get('agentId'):
        host = get_host_by_agent_request(args.get('agentId'))
    else:
        host = get_host_by_name_request(args.get('hostName'))

    md_table = tableToMarkdown(
        'FireEye HX Get Host Information',
        host_entry(host),
        headers=HOST_MAIN_ATTRIBUTES
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': host,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Hosts(obj._id==val._id)": host,
            "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host)
        }
    }
    demisto.results(entry)


def get_hosts_information():
    """

    return the host information to the war room, given an agentId or hostName from input.

    """

    offset = 0
    hosts = []  # type: List[Dict[str, str]]

    # get all hosts
    while True:
        hosts_partial_results = get_hosts_request(offset=offset, limit=1000)
        if not hosts_partial_results:
            break
        hosts.extend(hosts_partial_results)
        offset = len(hosts)

    hosts_entry = [host_entry(host) for host in hosts]
    md_table = tableToMarkdown(
        'FireEye HX Get Hosts Information',
        hosts_entry,
        headers=HOST_MAIN_ATTRIBUTES
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': hosts,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Hosts(obj._id==val._id)": hosts_entry,
            "Endpoint(obj.ID==val.ID)": [collect_endpoint_contxt(host)for host in hosts]
        }
    }
    demisto.results(entry)


def get_host_set_information():
    """
    return host set information to the war room according to given id or filters

    """
    args = demisto.args()

    url = '{}/host_sets/{}'.format(BASE_PATH, args.get('hostSetID', ''))
    url_params = {
        'limit': args.get('limit'),
        'offset': args.get('offset'),
        'search': args.get('search'),
        'sort': args.get('sort'),
        'name': args.get('name'),
        'type': args.get('type')
    }
    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS,
        url_params=url_params
    )
    host_set = []  # type: List[Dict[str, str]]
    try:
        if args.get('hostSetID'):
            data = response.json()['data']
            host_set = [data]
        else:
            data = response.json()['data']
            host_set = data.get('entries', [])
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to get host set information - unexpected response from the server.\n' + response.text)

    md_table = "No host sets found"
    if len(host_set) > 0:
        md_table = tableToMarkdown(
            'FireEye HX Get Host Sets Information',
            host_set_entry(host_set),
            headers=HOST_SET_MAIN_ATTRIBUTES
        )

    entry = {
        'Type': entryTypes['note'],
        'Contents': host_set,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.HostSets(obj._id==val._id)": host_set
        }
    }
    demisto.results(entry)


def get_hosts_request(limit=None, offset=None, has_active_threats=None, has_alerts=None,
                      agent_version=None, containment_queued=None, containment_state=None,
                      host_name=None, os_platform=None, reported_clone=None, time_zone=None):
    """
    returns the response body

    raises an exception on:

        - http request failure
        - response status code different from 200
    """
    url = '{}/hosts'.format(BASE_PATH)
    url_params = {
        'limit': limit,
        'offset': offset,
        'has_active_threats': has_active_threats,
        'has_alerts': has_alerts,
        'agent_version': agent_version,
        'containment_queued': containment_queued,
        'containment_state': containment_state,
        'hostname': host_name,
        'os.platform': os_platform,
        'reported_clone': reported_clone,
        'time_zone': time_zone
    }
    # remove None values
    url_params = {k: v for k, v in url_params.items() if v is not None}

    response = http_request(
        'GET',
        url,
        url_params=url_params,
        headers=GET_HEADERS
    )
    # successful request
    try:
        return response.json()['data']['entries']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to parse response body - unexpected response structure from the server.')


def get_host_by_name_request(host_name):

    try:
        return get_hosts_request(host_name=host_name, limit=1)[0]
    except Exception as e:
        LOG(e)
        raise ValueError('Host {} not found.'.format(host_name))


def get_all_agents_ids():
    """
    returns a list of all agents ids
    """
    offset = 0
    hosts = []  # type: List[Dict[str, str]]

    # get all hosts
    while True:
        hosts_partial_results = get_hosts_request(offset=offset, limit=1000)
        if not hosts_partial_results:
            break
        hosts.extend(hosts_partial_results)
        offset = len(hosts)
    return [host.get('_id') for host in hosts]


def get_agent_id(host_name):
    """
    returns the agent id given the host name

    raises an exception on:
        - unexpected response structure
        - empty results

    """
    host = get_host_by_name_request(host_name)
    try:
        return host['_id']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to get agent id for host {}'.format(host_name))


def collect_endpoint_contxt(host):

    return {
        'Hostname': host.get('hostname'),
        'ID': host.get('_id'),
        'IPAddress': host.get('primary_ip_address'),
        'Domain': host.get('domain'),
        'MACAddress': host.get('primary_mac'),
        'OS': host.get('os', {}).get('platform'),
        'OSVersion': host.get('os', {}).get('product_name')
    }


"""

HOST CONTAINMENT

"""


def containment_request(agent_id):
    """

    no return value on successful request

    """
    url = '{}/hosts/{}/containment'.format(BASE_PATH, agent_id)
    body = {
        'state': 'contain'
    }

    try:
        api_version = int(VERSION[-1])
    except Exception as exc:
        raise ValueError('Invalid version was set: {} - {}'.format(VERSION, str(exc)))
    if api_version >= 3:
        http_request(
            'POST',
            url,
            headers=POST_HEADERS
        )
    else:
        http_request(
            'POST',
            url,
            body=body,
            headers=POST_HEADERS
        )
    # no exception raised - successful request


def containment():
    """

    returns a success message to the war room

    """

    args = demisto.args()

    # validate one of the arguments was passed
    if not args:
        raise ValueError('Please provide either agentId or hostName')

    # in case a hostName was given, set the agentId accordingly
    if args.get('hostName'):
        args['agentId'] = get_agent_id(args['hostName'])

    containment_request(args['agentId'])
    # no exceptions raised->successful request

    host = get_host_by_agent_request(args['agentId'])
    entry = {
        'Type': entryTypes['note'],
        'Contents': 'Containment rquest for the host was sent and approved successfully',
        'ContentsFormat': formats['text'],
        'EntryContext': {
            "FireEyeHX.Hosts(obj._id==val._id)": host,
            "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host)
        }
    }
    demisto.results(entry)


def containment_cancellation_request(agent_id):
    """

    no return value on successful request

    """
    url = '{}/hosts/{}/containment'.format(BASE_PATH, agent_id)

    http_request(
        'DELETE',
        url,
        headers=GET_HEADERS
    )
    # no exceptions are raised - successful request


def containment_cancellation():
    """

    returns a success message to the war room

    """

    args = demisto.args()

    # validate one of the arguments was passed
    if not args:
        raise ValueError('Please provide either agentId or hostName')

    # in case a hostName was given, set the agentId accordingly
    if args.get('hostName'):
        args['agentId'] = get_agent_id(args['hostName'])

    containment_cancellation_request(args['agentId'])
    # no exceptions raised->successful request

    host = get_host_by_agent_request(args['agentId'])
    entry = {
        'Type': entryTypes['note'],
        'Contents': 'The host is released from containment.',
        'ContentsFormat': formats['text'],
        'EntryContext': {
            "FireEyeHX.Hosts(obj._id==val._id)": host,
            "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host)
        }
    }
    demisto.results(entry)


"""

ALERTS

"""


def get_alert_request(alert_id):

    url = '{}/alerts/{}'.format(BASE_PATH, alert_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )
    return response.json().get('data')


def get_alert():

    alert_id = demisto.args().get('alertId')
    alert = get_alert_request(alert_id)

    alert_table = tableToMarkdown(
        'FireEye HX Get Alert # {}'.format(alert_id),
        alert_entry(alert),
        headers=ALERT_MAIN_ATTRIBUTES
    )

    event_type = alert.get('event_type')
    event_type = 'NewEvent' if not event_type else event_type
    event_type = re.sub("([a-z])([A-Z])", "\g<1> \g<2>", event_type).title()
    event_table = tableToMarkdown(
        event_type,
        alert.get('event_values')
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': alert,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': u'{}\n{}'.format(alert_table, event_table),
        'EntryContext': {
            "FireEyeHX.Alerts(obj._id==val._id)": alert
        }
    }
    demisto.results(entry)


def get_alerts_request(has_share_mode=None, resolution=None, agent_id=None, host_name=None,
                       condition_id=None, limit=None, offset=None, sort=None, min_id=None,
                       event_at=None, alert_id=None, matched_at=None, reported_at=None, source=None):
    """

    returns the response body on successful request

    """
    url = '{}/alerts'.format(BASE_PATH)

    body = {
        'has_share_mode': has_share_mode,
        'resolution': resolution,
        'agent._id': agent_id,
        'condition._id': condition_id,
        'event_at': event_at,
        'min_id': min_id,
        '_id': alert_id,
        'matched_at': matched_at,
        'reported_at': reported_at,
        'source': source,
        'limit': limit,
        'offset': offset,
        'sort': sort
    }

    # remove None values
    body = {k: v for k, v in body.items() if v is not None}

    response = http_request(
        'GET',
        url,
        url_params=body,
        headers=GET_HEADERS
    )
    try:
        return response.json()['data']['entries']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to parse response body')


def get_all_alerts(has_share_mode=None, resolution=None, agent_id=None, condition_id=None, limit=None,
                   sort=None, min_id=None, event_at=None, alert_id=None, matched_at=None, reported_at=None, source=None):
    """

    returns a list of alerts, all results up to limit

    """
    offset = 0
    alerts = []  # type: List[Dict[str, str]]

    max_records = limit or float('inf')

    while len(alerts) < max_records:
        alerts_partial_results = get_alerts_request(
            has_share_mode=has_share_mode,
            resolution=resolution,
            agent_id=agent_id,
            condition_id=condition_id,
            event_at=event_at,
            alert_id=alert_id,
            matched_at=matched_at,
            reported_at=reported_at,
            source=source,
            min_id=min_id,
            offset=offset,
            limit=limit or 100,
            sort=sort
        )
        # empty list
        if not alerts_partial_results:
            break
        alerts.extend(alerts_partial_results)
        offset = len(alerts)

    # remove access results
    if len(alerts) > max_records:
        alerts[int(max_records) - 1: -1] = []

    return alerts


def general_context_from_event(alert):

    def file_context(values):

        return {
            'Name': values.get('fileWriteEvent/fileName'),
            'MD5': values.get('fileWriteEvent/md5'),
            'Extension': values.get('fileWriteEvent/fileExtension'),
            'Path': values.get('fileWriteEvent/fullPath')
        }

    def ip_context(values):

        return {
            'Address': values.get('ipv4NetworkEvent/remoteIP')
        }

    def registry_key_context(values):

        return {
            'Path': values.get('regKeyEvent/path'),
            'Name': values.get('regKeyEvent/valueName'),
            'Value': values.get('regKeyEvent/value')
        }
    context_map = {
        'fileWriteEvent': file_context,
        'ipv4NetworkEvent': ip_context,
        'regKeyEvent': registry_key_context
    }

    if context_map.get(alert['event_type']) is not None:
        f = context_map[alert['event_type']]
        return f(alert['event_values'])
    return None


def collect_context(alerts):

    # collect_context
    files = []
    ips = []
    registry_keys = []

    for alert in alerts:
        event_type = alert.get('event_type')
        context = general_context_from_event(alert)
        if event_type == 'fileWriteEvent':
            files.append(context)
        elif event_type == 'ipv4NetworkEvent':
            ips.append(context)
        elif event_type == 'regKeyEvent':
            registry_keys.append(context)
    return (files, ips, registry_keys)


def get_alerts():
    """

    returns a list of alerts to the war room

    """

    args = demisto.args()
    source = []
    # add source type
    if args.get('MALsource'):
        source.append('mal')
    if args.get('EXDsource'):
        source.append('exd')
    if args.get('IOCsource'):
        source.append('ioc')

    sort_map = {
        'agentId': 'agent._id',
        'conditionId': 'condition._id',
        'eventAt': 'event_at',
        'alertId': '_id',
        'matchedAt': 'matched_at',
        'id': '_id',
        'reportedAt': 'reported_at'
    }

    if args.get('sort'):
        args['sort'] = '{}+{}'.format(sort_map.get(args['sort']), args.get('sortOrder', 'ascending'))

    if args.get('hostName'):
        args['agentId'] = get_agent_id(args.get('hostName'))

    if args.get('limit'):
        args['limit'] = int(args['limit'])

    alerts = get_all_alerts(
        has_share_mode=args.get("hasShareMode"),
        resolution=args.get('resolution'),
        agent_id=args.get('agentId'),
        condition_id=args.get('conditionId'),
        event_at=args.get('eventAt'),
        alert_id=args.get('alertId'),
        matched_at=args.get('matchedAt'),
        reported_at=args.get('reportedAt'),
        source=source,
        min_id=args.get('min_id'),
        limit=args.get('limit'),
        sort=args.get('sort')
    )

    # parse each alert to a record displayed in the human readable table
    alerts_entries = [alert_entry(alert) for alert in alerts]

    files, ips, registry_keys = collect_context(alerts)

    md_table = tableToMarkdown(
        'FireEye HX Get Alerts',
        alerts_entries,
        headers=ALERT_MAIN_ATTRIBUTES
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': alerts,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Alerts(obj._id==val._id)": alerts,
            'File': files,
            'RegistryKey': registry_keys,
            'IP': ips
        }
    }
    demisto.results(entry)


def suppress_alert_request(alert_id):
    """

    no return value on successful request

    """

    url = '{}/alerts/{}'.format(BASE_PATH, alert_id)

    http_request(
        'DELETE',
        url
    )


def suppress_alert():
    """

    returns a success message to the war room

    """

    alert_id = demisto.args().get('alertId')

    suppress_alert_request(alert_id)
    # no exceptions raised->successful request

    entry = {
        'Type': entryTypes['note'],
        'Contents': 'Alert {} suppressed successfully.'.format(alert_id),
        'ContentsFormat': formats['text']
    }
    demisto.results(entry)


"""

INDICATORS

"""


def new_indicator_request(category):
    """
    Create a new indicator
    """
    url = '{}/indicators/{}'.format(BASE_PATH, category)

    response = http_request(
        'POST',
        url,
        headers=GET_HEADERS
    )
    try:
        return response.json().get('data')
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to parse response body, unexpected response structure from the server.')


def create_indicator():
    """
    Get new indicator details
    returns a success message to the war room
    """

    category = demisto.args().get('category')

    response = new_indicator_request(category)

    md_table = {
        'ID': response.get('_id'),
    }
    entry = {
        'Type': entryTypes['note'],
        'Contents': response,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': tableToMarkdown('FireEye HX New Indicator created successfully', md_table),
        'EntryContext': {
            "FireEyeHX.Indicators(obj._id===val._id)": response
        }
    }
    demisto.results(entry)


def append_conditions_request(name, category, body):
    """
    Append conditions to indicator request
    """

    url = '{}/indicators/{}/{}/conditions'.format(BASE_PATH, category, name)

    response = http_request(
        'PATCH',
        url,
        conditions_params=body,
        headers=PATCH_HEADERS
    )

    return response.json()


def append_conditions():
    """
    Append conditions to indicator
    no return value on successfull request
    """
    name = demisto.args().get('name')
    category = demisto.args().get('category')
    body = demisto.args().get('condition')

    body = body.replace(',', '\n')

    response = append_conditions_request(name, category, body)

    md_table = {
        'Name': name,
        'Category': category,
        'Conditions': body
    }

    entry = {
        'Type': entryTypes['note'],
        'Contents': response,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': tableToMarkdown('The conditions were added successfully', md_table)
    }
    demisto.results(entry)


def get_indicator_request(category, name):
    """

    returns a json object representing an indicator

    """

    url = '{}/indicators/{}/{}'.format(BASE_PATH, category, name)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS,
    )
    return response.json().get('data')


def get_indicator_conditions_request(category, name, limit=None, offset=None, enabled=None, has_alerts=None):
    """

    returns a list of json objects, each representing an indicator condition
    if no results are found- returns None

    """
    url = '{}/indicators/{}/{}/conditions'.format(BASE_PATH, category, name)
    url_params = {
        'limit': limit,
        'offset': offset,
        'enabled': enabled,
        'has_alerts': has_alerts
    }
    # remove None values
    url_params = {k: v for k, v in url_params.items() if v is not None}

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS,
        url_params=url_params
    )
    try:
        return response.json()['data']['entries']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to parse response body')


def get_all_enabled_conditions(indicator_category, indicator_name):

    offset = 0
    conditions = []   # type: List[Dict[str, str]]

    # get all results
    while True:
        conditions_partial_results = get_indicator_conditions_request(
            indicator_category,
            indicator_name,
            enabled=True,
            offset=offset
        )
        if not conditions_partial_results:
            break
        conditions.extend(conditions_partial_results)
        offset = len(conditions)
    return conditions


def get_indicator_conditions():
    """

    returns a list of enabled conditions assosiated with a specific indicator to the war room

    """

    args = demisto.args()

    conditions = get_all_enabled_conditions(
        args.get('category'),
        args.get('name')
    )

    conditions_entries = [condition_entry(condition) for condition in conditions]

    md_table = tableToMarkdown(
        'Indicator "{}" Alerts on'.format(args.get('name')),
        conditions_entries
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': conditions,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Conditions(obj._id==val._id)": conditions
        }
    }
    demisto.results(entry)


def get_indicator():

    args = demisto.args()

    indicator = get_indicator_request(
        args.get('category'),
        args.get('name')
    )

    md_table = tableToMarkdown(
        'FireEye HX Get Indicator- {}'.format(args.get('name')),
        indicator_entry(indicator),
        headers=INDICATOR_MAIN_ATTRIBUTES
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': indicator,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Indicators(obj._id==val._id)": indicator
        }
    }
    demisto.results(entry)


def get_indicators_request(category=None, search=None, limit=None, offset=None,
                           share_mode=None, sort=None, created_by=None, alerted=None):

    url = '{}/indicators'.format(BASE_PATH)
    if category:
        url = url + '/' + category

    url_params = {
        'search': search,
        'limit': limit,
        'offset': offset,
        'category.share_mode': share_mode,
        'sort': sort,
        'created_by': created_by,
        'stats.alerted_agents': alerted
    }

    # remove None value
    url_params = {k: v for k, v in url_params.items() if v}

    response = http_request(
        'GET',
        url,
        url_params=url_params,
        headers=GET_HEADERS,
    )
    try:
        response_body = response.json()
        data = response_body['data']
        # no results found
        if data['total'] == 0:
            return None
        return data['entries']
    except Exception as e:
        LOG(e)
        raise ValueError('Failed to parse response body')


def get_all_indicators(category=None, search=None, share_mode=None, sort=None, created_by=None, alerted=None, limit=None):

    max_records = limit or float('inf')
    offset = 0
    indicators = []   # type: List[Dict[str, str]]

    # get all results
    while len(indicators) < max_records:
        indicators_partial_results = get_indicators_request(
            category=category,
            search=search,
            offset=offset,
            share_mode=share_mode,
            sort=sort,
            created_by=created_by,
            alerted=alerted,
            limit=limit or 100
        )
        if not indicators_partial_results:
            break
        indicators.extend(indicators_partial_results)
        offset = len(indicators)

    # remove access results
    if len(indicators) > max_records:
        indicators[int(max_records) - 1: -1] = []

    return indicators


def get_indicators():

    args = demisto.args()

    sort_map = {
        'category': 'category',
        'activeSince': 'active_since',
        'createdBy': 'created_by',
        'alerted': 'stats.alerted_agents'
    }

    if args.get('limit'):
        args['limit'] = int(args['limit'])
    if args.get('alerted'):
        args['alerted'] = args['alerted'] == 'yes'
    if args.get('sort'):
        args['sort'] = sort_map.get(args.get('sort'))

    # get all results
    indicators = get_all_indicators(
        category=args.get('category'),
        search=args.get('searchTerm'),
        share_mode=args.get('shareMode'),
        sort=args.get('sort'),
        created_by=args.get('createdBy'),
        alerted=args.get('alerted'),
        limit=args.get('limit')
    )

    indicators_entries = [indicator_entry(indicator) for indicator in indicators]

    md_table = tableToMarkdown(
        'FireEye HX Get Indicator- {}'.format(args.get('name')),
        indicators_entries,
        headers=INDICATOR_MAIN_ATTRIBUTES
    )

    entry = {
        'Type': entryTypes['note'],
        'Contents': indicators,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': md_table,
        'EntryContext': {
            "FireEyeHX.Indicators(obj._id==val._id)": indicators
        }
    }
    demisto.results(entry)


"""

SEARCH

"""


def search_request(query, host_set=None, hosts=None, exhaustive=False):

    url = '{}/searches'.format(BASE_PATH)

    body = {'query': query}

    if host_set:
        body['host_set'] = {'_id': int(host_set)}
    elif hosts:
        body['hosts'] = [{'_id': host} for host in hosts]

    if exhaustive:
        body['exhaustive'] = True

    try:
        response = http_request(
            'POST',
            url,
            headers=POST_HEADERS,
            body=body
        )
    except Exception as e:
        raise e
    if response.status_code == 409:
        raise ValueError('Request unsuccessful because the search limits \
        (10 existing searches or 5 running searches) have been exceeded')
    return response.json().get('data')


def get_search_information_request(search_id):
    """

    returns the search information represented by a json object.

    """

    url = '{}/searches/{}'.format(BASE_PATH, search_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )
    return response.json().get('data')


def get_search_results_request(search_id):
    """

    returns the search results represented by a json object.

    """

    url = '{}/searches/{}/results'.format(BASE_PATH, search_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )
    return response.json().get('data', {}).get('entries', [])


def stop_search_request(search_id):
    """

    returns the search information represented by a json object.

    """

    url = '{}/searches/{}/actions/stop'.format(BASE_PATH, search_id)

    response = http_request(
        'POST',
        url,
        headers=POST_HEADERS
    )
    return response.json()


def delete_search_request(search_id):
    """

    no return value on successful request

    """

    url = '{}/searches/{}'.format(BASE_PATH, search_id)
    http_request(
        'DELETE',
        url
    )


def search_results_to_context(results, search_id):

    for res in results:
        res["SearchID"] = search_id
        res["HostID"] = res.get("host", {}).get("_id")
        res["HostName"] = res.get("host", {}).get("hostname")
        res["HostUrl"] = res.get("host", {}).get("url")
        del res['host']
        res["Results"] = res.get("results")
        del res["results"]
        for resData in res.get("Results"):
            resData.update(resData.get("data", {}))
            del resData['data']
    return results


def start_search():

    args = demisto.args()

    '''
    to search all hosts past none of the arguments?

    # validate at list one of the arguments 'agentsIds', 'hostsNames', 'hostSet' was passed
    if not any([args.get('agentsIds'), args.get('hostsNames'), args.get('hostSet'), args.get('searchAllHosts')]):
        raise ValueError('Please provide one of the followings: agentsIds, hostsNames, hostSet')
    '''

    agents_ids = []  # type: List[Dict[str, str]]
    if args.get('agentsIds'):
        agents_ids = args['agentsIds'].split(',')
    elif args.get('hostsNames'):
        names = args.get('hostsNames').split(',')
        for name in names:
            try:
                agent_id = get_agent_id(name)
                agents_ids.append(agent_id)
            except Exception as e:
                LOG(e)
                pass
        if not agents_ids:
            raise ValueError('None of the host names were matched with an agent')

    # limit can't exceed 1000.
    limit = args.get('limit')
    if not limit or limit > 1000:
        limit = 1000

    arg_to_query_field_map = {
        'dnsHostname': 'DNS Hostname',
        'fileFullPath': 'File Full Path',
        'fileMD5Hash': 'File MD5 Hash',
        'ipAddress': 'IP Address'
    }

    query = []
    for arg in arg_to_query_field_map.keys():
        if not args.get(arg):
            continue
        field_filter = {
            'field': arg_to_query_field_map[arg],
            'operator': args['{}Operator'.format(arg)],
            'value': args[arg]
        }
        query.append(field_filter)

    search = search_request(
        query,
        hosts=agents_ids,
        host_set=args.get('hostSet'),
        exhaustive=args.get('exhaustive') == 'yes'
    )

    search_id = search.get('_id')

    '''
    loop to get search status once a minute. break on: search has stopped, matched
    results exceeded limit, or no more pending hosts.
    '''

    while True:
        search_info = get_search_information_request(search_id)
        matched = search_info.get('stats', {}).get('search_state', {}).get('MATCHED', 0)
        pending = search_info.get('stats', {}).get('search_state', {}).get('PENDING', 0)
        if search_info.get('state') == 'STOPPED' or matched >= limit or pending == 0:
            break
        time.sleep(60)  # pylint: disable=sleep-exists

    results = get_search_results_request(search_id)
    md_entries = [host_results_md_entry(host_results) for host_results in results]

    entry = {
        'Type': entryTypes['note'],
        'Contents': results,
        'ContentsFormat': formats['json'],
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': '## Search Results\n' + '\n'.join(md_entries),
        'EntryContext': {
            "FireEyeHX.Search": search_results_to_context(results, search_id)
        }
    }
    demisto.results(entry)

    # finally stop or delete the search
    possible_error_message = None
    try:
        if args.get('stopSearch') == 'stop':
            possible_error_message = 'Failed to stop search'
            stop_search_request(search_id)
        # no need to stop a search before deleting it.
        if args.get('stopSearch') == 'stopAndDelete':
            possible_error_message = 'Failed to delete search'
            delete_search_request(search_id)
        possible_error_message = None
    except Exception as e:
        LOG('{}\n{}'.format(possible_error_message, e))
        pass
    # add warning entry if necessary
    if possible_error_message:
        warning_entry = {
            'Type': entryTypes['note'],
            'Contents': possible_error_message,
            'ContentsFormat': formats['text'],
        }
        demisto.results(warning_entry)


"""

ACQUISITIONS

"""


def file_acquisition_request(agent_id, file_name, file_path, comment=None, external_id=None, req_use_api=None):

    url = '{}/hosts/{}/files'.format(BASE_PATH, agent_id)

    body = {
        'req_path': file_path,
        'req_filename': file_name,
        'comment': comment,
        'external_id': external_id,
        'req_use_api': req_use_api
    }

    # remove None values
    body = {k: v for k, v in body.items() if v is not None}

    response = http_request(
        'POST',
        url,
        body=body,
        headers=POST_HEADERS
    )

    return response.json().get('data')


def file_acquisition_package_request(acquisition_id):

    url = '{}/acqs/files/{}.zip'.format(BASE_PATH, acquisition_id)

    response = http_request(
        'GET',
        url
    )

    return response.content


def file_acquisition_information_request(acquisition_id):

    url = '{}/acqs/files/{}'.format(BASE_PATH, acquisition_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )

    return response.json().get('data')


def delete_file_acquisition_request(acquisition_id):
    """

    no return value on successful request

    """

    url = '{}/acqs/files/{}'.format(BASE_PATH, acquisition_id)

    http_request(
        'DELETE',
        url
    )


def delete_file_acquisition():
    """

    returns a success message to the war room

    """
    acquisition_id = demisto.args().get('acquisitionId')
    delete_file_acquisition_request(acquisition_id)
    # successful request

    return {
        'Type': entryTypes['note'],
        'Contents': 'file acquisition {} deleted successfully'.format(acquisition_id),
        'ContentsFormat': formats['text'],
    }


def file_acquisition():

    args = demisto.args()

    if not args.get('hostName') and not args.get('agentId'):
        raise ValueError('Please provide either agentId or hostName')

    if args.get('hostName'):
        args['agentId'] = get_agent_id(args['hostName'])

    use_api = args.get('acquireUsing') == 'API'

    acquisition_info = file_acquisition_request(
        args.get('agentId'),
        args.get('fileName'),
        args.get('filePath'),
        req_use_api=use_api
    )

    acquisition_id = acquisition_info.get('_id')

    LOG('acquisition request was successful. Waiting for acquisition process to be complete.')
    while True:
        acquisition_info = file_acquisition_information_request(acquisition_id)
        state = acquisition_info.get('state')
        if state in ['COMPLETE', 'ERROR', 'FAILED']:
            break
        time.sleep(10)  # pylint: disable=sleep-exists
    LOG('acquisition process has been complete. Fetching zip file.')

    acquired_file = file_acquisition_package_request(acquisition_id)

    message = '{} acquired successfully'.format(args.get('fileName'))
    if acquisition_info.get('error_message'):
        message = acquisition_info.get('error_message')

    entry = {
        'Type': entryTypes['note'],
        'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id),
        'ContentsFormat': formats['text'],
        'EntryContext': {
            "FireEyeHX.Acquisitions.Files(obj._id==val._id)": acquisition_info
        }
    }

    demisto.results(entry)
    demisto.results(fileResult('{}.zip'.format(os.path.splitext(args.get('fileName'))[0]), acquired_file))


def data_acquisition_request(agent_id, script_name, script):

    url = '{}/hosts/{}/live'.format(BASE_PATH, agent_id)

    body = {
        'name': script_name,
        'script': {'b64': script}
    }

    response = http_request(
        'POST',
        url,
        body=body
    )

    return response.json()['data']


def data_acquisition_information_request(acquisition_id):

    url = '{}/acqs/live/{}'.format(BASE_PATH, acquisition_id)

    response = http_request(
        'GET',
        url,
        headers=GET_HEADERS
    )

    return response.json()['data']


def data_collection_request(acquisition_id):

    url = '{}/acqs/live/{}.mans'.format(BASE_PATH, acquisition_id)

    response = http_request(
        'GET',
        url
    )

    return response.content


def data_acquisition():
    """

    returns the mans file to the war room

    """

    args = demisto.args()

    # validate the host name or agent ID was passed
    if not args.get('hostName') and not args.get('agentId'):
        raise ValueError('Please provide either agentId or hostName')

    if not args.get('defaultSystemScript') and not args.get('script'):
        raise ValueError('If the script is not provided, defaultSystemScript must be specified.')

    if args.get('script') and not args.get('scriptName'):
        raise ValueError('If the script is provided, script name must be specified as well.')

    if args.get('hostName'):
        args['agentId'] = get_agent_id(args['hostName'])

    # determine whether to use the default script
    sys = args.get('defaultSystemScript')
    if sys:
        args['script'] = json.dumps(SYS_SCRIPT_MAP[sys])
        args['scriptName'] = '{}DefaultScript'.format(sys)

    acquisition_info = data_acquisition_request(
        args['agentId'],
        args['scriptName'],
        base64.b64encode(args['script'])
    )

    acquisition_id = acquisition_info.get('_id')

    LOG('Acquisition request was successful. Waiting for acquisition process to be complete.')
    # loop to inquire acquisition state every 30 seconds
    # break when state is complete
    while True:
        acquisition_info = data_acquisition_information_request(acquisition_id)
        if acquisition_info.get('state') == 'COMPLETE':
            break
        time.sleep(30)  # pylint: disable=sleep-exists
    LOG('Acquisition process has been complete. Fetching mans file.')

    message = '{} acquired successfully'.format(args.get('fileName'))
    if acquisition_info.get('error_message'):
        message = acquisition_info.get('error_message')

    # output file and acquisition information to the war room
    data = data_collection_request(acquisition_id)
    entry = {
        'Type': entryTypes['note'],
        'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id),
        'ContentsFormat': formats['text'],
        'EntryContext': {
            "FireEyeHX.Acquisitions.Data(obj._id==val._id)": acquisition_info
        }
    }
    demisto.results(entry)
    demisto.results(fileResult('agent_{}_data.mans'.format(args['agentId']), data))


def initiate_data_acquisition():
    """
    Initiate data acquisition
    """

    args = demisto.args()

    # validate the host name or agent ID was passed
    if not args.get('hostName') and not args.get('agentId'):
        raise ValueError('Please provide either agentId or hostName')

    if not args.get('defaultSystemScript') and not args.get('script'):
        raise ValueError('If the script is not provided, defaultSystemScript must be specified.')

    if args.get('script') and not args.get('scriptName'):
        raise ValueError('If the script is provided, script name must be specified as well.')

    if args.get('hostName'):
        args['agentId'] = get_agent_id(args['hostName'])

    # determine whether to use the default script
    sys = args.get('defaultSystemScript')
    if sys:
        args['script'] = json.dumps(SYS_SCRIPT_MAP[sys])
        args['scriptName'] = '{}DefaultScript'.format(sys)

    acquisition_info = data_acquisition_request(
        args['agentId'],
        args['scriptName'],
        base64.b64encode(bytes(args['script'], 'utf-8')).decode()
    )

    # Add hostname to the host info of acquisition_info
    acquisition_info["host"]["hostname"] = args.get('hostName')
    # Add Integration Instance to the acquisition_info
    acquisition_info["instance"] = demisto.integrationInstance()

    entry = {
        'Type': entryTypes['note'],
        'Contents': 'Acquisition ID: {} on Instance: {}'.format(acquisition_info.get('_id'), demisto.integrationInstance()),
        'ContentsFormat': formats['text'],
        'EntryContext': {
            "FireEyeHX.Acquisitions.Data(obj._id==val._id && obj.instance==val.instance)": acquisition_info
        }
    }
    demisto.results(entry)


def get_data_acquisition():
    """
    Wait for acquisition process to complete and fetch the data
    """

    args = demisto.args()

    # validate the acquisitionId was passed
    if not args.get('acquisitionId'):
        raise ValueError('Please provide acquisitionId')

    acquisition_id = args.get("acquisitionId")

    acquisition_info = data_acquisition_information_request(acquisition_id)

    agent_id = acquisition_info.get('host').get('_id')
    host_info = get_host_by_agent_request(agent_id)
    hostname = host_info.get('hostname')

    # Add hostname to the host info of acquisition_info
    acquisition_info["host"]["hostname"] = hostname
    # Add Integration Instance to the acquisition_info
    acquisition_info["instance"] = demisto.integrationInstance()

    # if `state` equals to 'COMPLETE'
    if acquisition_info.get('state') == 'COMPLETE':

        message = 'Acquisition completed successfully.'
        if acquisition_info.get('error_message'):
            message = acquisition_info.get('error_message')

        # output file and acquisition information to the war room
        data = data_collection_request(acquisition_id)
        entry = {
            'Type': EntryType.NOTE,
            'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id),
            'ContentsFormat': EntryFormat.TEXT,
            'EntryContext': {
                'FireEyeHX.Acquisitions.Data(obj._id==val._id)': acquisition_info
            }
        }
        demisto.results(entry)
        demisto.results(fileResult('{}_agent_{}_data.mans'.format(acquisition_id, agent_id), data))
        return

    # else return message for states in [ NEW, ERROR, QUEUED, RUNNING, FAILED ]
    state = acquisition_info.get('state')

    message = "Acquisition process not yet completed."
    if acquisition_info.get('error_message'):
        message = acquisition_info.get('error_message')

    entry = {
        'Type': EntryType.NOTE,
        'Contents': '{}\nacquisition ID: {}\nstate: {}'.format(message, acquisition_id, state),
        'ContentsFormat': EntryFormat.TEXT,
        'EntryContext': {
            'FireEyeHX.Acquisitions.Data(obj._id==val._id && obj.instance==val.instance)': acquisition_info
        }
    }
    demisto.results(entry)


def delete_data_acquisition_request(acquisition_id):
    """

    no return value on successful request

    """

    url = '{}/acqs/live/{}'.format(BASE_PATH, acquisition_id)

    http_request(
        'DELETE',
        url
    )


def delete_data_acquisition():
    """

    returns a success message to the war room

    """
    acquisition_id = demisto.args().get('acquisitionId')
    delete_data_acquisition_request(acquisition_id)
    # successful request

    return {
        'Type': entryTypes['note'],
        'Contents': 'data acquisition {} deleted successfully'.format(acquisition_id),
        'ContentsFormat': formats['text'],
    }


"""

FETCH INCIDENTS

"""


def fetch_incidents():

    last_run = demisto.getLastRun()
    alerts = []  # type: List[Dict[str, str]]
    fetch_limit = int(demisto.params().get('fetch_limit') or '100')

    if last_run and last_run.get('min_id'):
        # get all alerts with id greater than min_id
        alerts = get_all_alerts(
            min_id=last_run.get('min_id'),
            sort='_id+ascending',
            limit=fetch_limit
        )
        # results are sorted in ascending order - the last alert holds the greatest id
        min_id = alerts[-1].get('_id') if alerts else None
    else:
        # get the last 100 alerts
        alerts = get_all_alerts(
            sort='_id+descending',
            limit=fetch_limit
        )
        # results are sorted in descending order - the first alert holds the greatest id
        min_id = alerts[0].get('_id') if alerts else None

    incidents = [parse_alert_to_incident(alert) for alert in alerts]
    demisto.incidents(incidents)
    if min_id is not None:
        demisto.setLastRun({'min_id': min_id})


@logger
def parse_alert_to_incident(alert):

    event_type = alert.get('event_type')
    event_type = 'NewEvent' if not event_type else event_type
    event_values = alert.get('event_values', {})
    event_indicators_map = {
        'fileWriteEvent': 'fileWriteEvent/fileName',
        'ipv4NetworkEvent': 'ipv4NetworkEvent/remoteIP',
        'dnsLookupEvent': 'dnsLookupEvent/hostname',
        'regKeyEvent': 'regKeyEvent/valueName'
    }
    event_indicator = event_indicators_map.get(event_type)
    event_indicator = 'No Indicator' if not event_indicator else event_indicator

    indicator = ''
    if isinstance(event_values, dict):
        indicator = event_values.get(event_indicator, '')

    incident_name = u'{event_type_parsed}: {indicator}'.format(
        event_type_parsed=re.sub("([a-z])([A-Z])", "\g<1> \g<2>", event_type).title(),
        indicator=indicator
    )

    incident = {
        'name': incident_name,
        'rawJSON': json.dumps(alert)
    }
    return incident


"""

ENTRY ENTITIES

"""


def indicator_entry(indicator):

    indicator_entry = {
        'OS': ', '.join(indicator.get('platforms', [])),
        'Name': indicator.get('name'),
        'Created By': indicator.get('created_by'),
        'Active Since': indicator.get('active_since'),
        'Category': indicator.get('category', {}).get('name'),
        'Signature': indicator.get('signature'),
        'Active Condition': indicator.get('stats', {}).get('active_conditions'),
        'Hosts With Alerts': indicator.get('stats', {}).get('alerted_agents'),
        'Source Alerts': indicator.get('stats', {}).get('source_alerts')
    }
    return indicator_entry


def host_entry(host):

    host_entry = {
        'Host Name': host.get('hostname'),
        'Last Poll': host.get('last_poll_timestamp'),
        'Agent ID': host.get('_id'),
        'Agent Version': host.get('agent_version'),
        'Host IP': host.get('primary_ip_address'),
        'OS': host.get('os', {}).get('platform'),
        'Containment State': host.get('containment_state'),
        'Domain': host.get('domain'),
        'Last Alert': host.get('last_alert')
    }
    return host_entry


def host_set_entry(host_sets):
    host_set_entries = [{
        'Name': host_set.get('name'),
        'ID': host_set.get('_id'),
        'Type': host_set.get('type')
    } for host_set in host_sets]
    return host_set_entries


def alert_entry(alert):

    alert_entry = {
        'Alert ID': alert.get('_id'),
        'Reported': alert.get('reported_at'),
        'Event Type': alert.get('event_type'),
        'Agent ID': alert.get('agent', {}).get('_id')
    }
    return alert_entry


def condition_entry(condition):

    indicator_entry = {
        'Event Type': condition.get('event_type'),
        'Operator': condition.get('tests', {})[0].get('operator'),
        'Value': condition.get('tests', {})[0].get('value'),

    }
    return indicator_entry


def host_results_md_entry(host_entry):

    results = host_entry.get('results', [])
    host_info = host_entry.get('host', {})
    entries = []
    for result in results:
        data = result.get('data', {})
        entry = {
            'Item Type': result.get('type'),
            'Summary': ' '.join(['**{}** {}'.format(k, v) for k, v in data.items()])
        }
        entries.append(entry)

    md_table = tableToMarkdown(
        host_info.get('hostname'),
        entries,
        headers=['Item Type', 'Summary']
    )
    return md_table


"""

ADDITIONAL FUNCTIONS

"""


def http_request(method, url, body=None, headers={}, url_params=None, conditions_params=None):
    """

    returns the http response

    """

    # add token to headers
    headers['X-FeApi-Token'] = TOKEN

    request_kwargs = {
        'headers': headers,
        'verify': USE_SSL
    }

    # add optional arguments if specified
    if body:
        # request_kwargs['data'] = ' '.join(format(x, 'b') for x in bytearray(json.dumps(body)))
        request_kwargs['data'] = json.dumps(body)
    if url_params:
        request_kwargs['params'] = url_params
    if conditions_params:
        request_kwargs['data'] = conditions_params

    LOG('attempting {} request sent to {} with arguments:\n{}'.format(method, url, json.dumps(request_kwargs, indent=4)))
    try:
        response = requests.request(
            method,
            url,
            **request_kwargs
        )
    except requests.exceptions.SSLError as e:
        LOG(e)
        raise ValueError('An SSL error occurred when trying to connect to the server. Consider configuring unsecure connection in \
        the integration settings.')

    # handle request failure
    if response.status_code not in range(200, 205):
        message = parse_error_response(response)
        raise ValueError('Request failed with status code {}\n{}'.format(response.status_code, message))

    return response


def logout():

    url = '{}/token'.format(BASE_PATH)

    try:
        http_request(
            'DELETE',
            url
        )
    except ValueError as e:
        LOG('Failed to logout with token')
        raise e
    LOG('logout successfully')


def parse_error_response(response):

    try:
        res = response.json()
        msg = res.get('message')
        if res.get('details') is not None and res.get('details')[0].get('message') is not None:
            msg = msg + "\n" + json.dumps(res.get('details')[0])
    except Exception as e:
        LOG(e)
        return response.text
    return msg


def return_error_entry(message):

    error_entry = {
        'Type': entryTypes['error'],
        'Contents': message,
        'ContentsFormat': formats['text']
    }

    demisto.results(error_entry)


"""

EXECUTION

"""


def main():
    global TOKEN
    set_proxies()

    command = demisto.command()
    LOG('Running command "{}"'.format(command))

    # ask for a token using user credentials
    TOKEN = get_token()

    try:
        if command == 'test-module':
            # token generated - credentials are valid
            demisto.results('ok')
        elif command == 'fetch-incidents':
            fetch_incidents()
        elif command == 'fireeye-hx-get-alerts':
            get_alerts()
        elif command == 'fireeye-hx-cancel-containment':
            containment_cancellation()
        elif command == 'fireeye-hx-host-containment':
            containment()
        elif command == 'fireeye-hx-create-indicator':
            create_indicator()
        elif command == 'fireeye-hx-get-indicator':
            get_indicator()
            get_indicator_conditions()
        elif command == 'fireeye-hx-get-indicators':
            get_indicators()
        elif command == 'fireeye-hx-suppress-alert':
            suppress_alert()
        elif command == 'fireeye-hx-get-host-information':
            get_host_information()
        elif command == 'fireeye-hx-get-alert':
            get_alert()
        elif command == 'fireeye-hx-file-acquisition':
            file_acquisition()
        elif command == 'fireeye-hx-delete-file-acquisition':
            delete_file_acquisition()
        elif command == 'fireeye-hx-data-acquisition':
            data_acquisition()
        elif command == 'fireeye-hx-initiate-data-acquisition':
            initiate_data_acquisition()
        elif command == 'fireeye-hx-get-data-acquisition':
            get_data_acquisition()
        elif command == 'fireeye-hx-delete-data-acquisition':
            delete_data_acquisition()
        elif command == 'fireeye-hx-search':
            start_search()
        elif command == 'fireeye-hx-get-host-set-information':
            get_host_set_information()
        elif command == 'fireeye-hx-append-conditions':
            append_conditions()
        elif command == 'fireeye-hx-get-all-hosts-information':
            get_hosts_information()
    except ValueError as e:
        return_error(e)
    finally:
        logout()


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