FireEye Email Security
FireEye Email Security (EX) series protects against breaches caused by advanced email attacks.
Email · FireEye Email Security (EX)
Details
| ID | FireEye Email Security |
|---|---|
| Provider | Trellix |
| Category | |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
FireEye Email Security (EX) series protects against breaches caused by advanced email attacks.
This integration was integrated and tested with version 9.0.2.929543 of FireEye Email Security.
API Key management
This integration generates an API Key from the username and password given to be authenticated with FireEye.
The API Key is valid for 15 minutes.
The integration manages the storage of this key, and its re-generation when the key expires.
Fetch FireEye EX Alert Emails
To fetch a FireEye EX alert email, you will need the UUID.
- Run the fireeye-ex-get-alert-details** command with the alert ID. For example,
**!fireeye-ex-get-alert-details alert_id=542* - Locate the UUID in the context data and run the fireeye-ex-get-artifacts-by-uuid command with the UUID. For example:
!fireeye-ex-get-artifacts-by-uuid uuid=243a2555-a915-47a1-a947-e71049f4971c - Download the email.
Access the FireEye Alert URL
To display a proper link in the FireEye NX Alert URL field of the FireEye EX Alert layout, you need to configure the hostname in the appliance settings of the FireEye application.
- Log in to your FireEye application.
- In the Hostname field, enter your URL/server/ip address.
Configure FireEye Email Security in Cortex
- Navigate to Settings > Integrations > Servers & Services.
| Parameter | Required |
|---|---|
| Your server URL | True |
| Username | True |
| Fetch incidents | False |
| Max incidents to fetch | False |
| First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year) | False |
| Incident type | False |
| Info level for fetched alerts | False |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
fireeye-ex-get-alerts
Searches and retrieves FireEye EX alerts based on several filters.
Base Command
fireeye-ex-get-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The ID number of the alert to retrieve. | Optional |
| duration | The time interval to search. This filter is used with either the start_time or end_time filter. If duration, start time, and end time are not specified, the system defaults to duration=12_hours, end_time=current_time. If only the duration is specified, the end_time defaults to the current_time. Possible values are: 1_hour, 2_hours, 6_hours, 12_hours, 24_hours, 48_hours. | Optional |
| start_time | The start time of the search. This filter is optional. Default is last day. Syntax: start_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om or ‘1 day/month/year’. | Optional |
| end_time | The end time of the search. This filter is used with the duration filter. If the end_time is specified but not the duration, the system defaults to duration=12_hours, ending at the specified end_time. Syntax: end_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om. | Optional |
| callback_domain | Searches for alerts that include callbacks to the specified domain. | Optional |
| dst_ip | The destination IPv4 address related to the malware alert. | Optional |
| src_ip | The source IPv4 address related to the malware alert. | Optional |
| file_name | The name of the malware file. | Optional |
| file_type | The malware file type. | Optional |
| info_level | The level of information to be returned. Possible values are: concise, normal, extended. Default is concise. | Optional |
| malware_name | The name of the malware object. | Optional |
| malware_type | The type of the malware object. Possible values are: domain_match, malware_callback, malware_object, web_infection, infection_match, riskware-infection, riskware-callback, riskware-object. | Optional |
| md5 | Searches for alerts that include a specific MD5 hash. | Optional |
| recipient_email | The email address of the malware object receiver. | Optional |
| sender_email | The email address of the malware object sender. | Optional |
| url | Searches for a specific alert URL. | Optional |
| limit | Maximum number of alerts to return. Default is 20. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.Alerts.id | String | The ID of the alert. |
| FireEyeEX.Alerts.uuid | String | The UUID of the alert. |
| FireEyeEX.Alerts.occurred | String | The time when the alert occurred. |
| FireEyeEX.Alerts.product | String | The product name of the alert. |
| FireEyeEX.Alerts.rootInfection | String | The ID of the infection associated with the malware alert. |
| FireEyeEX.Alerts.name | String | The link to the infection associated with the malware alert. |
| FireEyeEX.Alerts.vlan | String | The virtual LAN (VLAN) of the alert. |
| FireEyeEX.Alerts.malicious | String | A flag indicating whether the alert is malicious. |
| FireEyeEX.Alerts.severity | String | The severity of the alert. |
| FireEyeEX.Alerts.sensor | String | The sensor name that the alert is associated with. |
| FireEyeEX.Alerts.applianceId | String | The appliance ID of the alert. |
| FireEyeEX.Alerts.sensorIp | String | The sensor IP that the alert is associated with. |
| FireEyeEX.Alerts.ack | String | A flag indicating whether an acknowledgment is received. |
| FireEyeEX.Alerts.src | Unknown | The source of the alert. |
| FireEyeEX.Alerts.dst | Unknown | The destination of the alert. |
| FireEyeEX.Alerts.explanation | Unknown | The explanation data of the alert. |
Command Example
!fireeye-ex-get-alerts start_time="2 month" sender_email="test@malicious.net" limit=4
Context Example
{
"FireEyeEX": {
"Alerts": [
{
"ack": "no",
"action": "notified",
"alertUrl": "https://FireEyeEX/emps/eanalysis?e_id=9&type=url",
"applianceId": "86A8D8FA2D11",
"attackTime": "2021-02-14 09:42:43 +0000",
"dst": {
"smtpTo": "test@actualdomain.org"
},
"explanation": {
"malwareDetected": {
"malware": [
{
"md5Sum": "271c1bcd28d01c6863fdb5b5c5d94e73",
"name": "FETestEvent",
"sha256": "abebb5862eea61a3d0a1c75bf5a2e2abcd6c4ee6a6ad086e1d518445594970fc"
}
]
},
"osChanges": []
},
"id": 1,
"malicious": "yes",
"name": "MALWARE_OBJECT",
"occurred": "2021-02-14 09:42:47 +0000",
"product": "EMAIL_MPS",
"scVersion": "1115.212",
"severity": "MAJR",
"smtpMessage": {
"subject": "test"
},
"src": {
"smtpMailFrom": "test@malicious.net"
},
"uuid": "1174ddc9-f7cc-4c38-a08c-42fcc5c04d31",
"vlan": 0
},
{
"ack": "no",
"action": "notified",
"alertUrl": "https://FireEyeEX/emps/eanalysis?e_id=10&type=url",
"applianceId": "86A8D8FA2D11",
"attackTime": "2021-02-14 09:43:51 +0000",
"dst": {
"smtpTo": "test@actualdomain.org"
},
"explanation": {
"malwareDetected": {
"malware": [
{
"md5Sum": "6efaa05d0d98711416f7d902639155fb",
"name": "FETestEvent",
"sha256": "340d367ebe68ad833ea055cea7678463a896d03eae86f7816cc0c836b9508fa8"
}
]
},
"osChanges": []
},
"id": 2,
"malicious": "yes",
"name": "MALWARE_OBJECT",
"occurred": "2021-02-14 09:43:55 +0000",
"product": "EMAIL_MPS",
"scVersion": "1115.212",
"severity": "MAJR",
"smtpMessage": {
"subject": "test"
},
"src": {
"smtpMailFrom": "test@malicious.net"
},
"uuid": "e7656103-4faa-4853-b9a4-dbc615302aad",
"vlan": 0
},
{
"ack": "no",
"action": "notified",
"alertUrl": "https://FireEyeEX/emps/eanalysis?e_id=12&type=url",
"applianceId": "86A8D8FA2D11",
"attackTime": "2021-02-14 09:45:55 +0000",
"dst": {
"smtpTo": "test@actualdomain.org"
},
"explanation": {
"malwareDetected": {
"malware": [
{
"md5Sum": "a705075df02f217e8bfc9ac5ec2ffee2",
"name": "Malicious.LIVE.DTI.URL",
"sha256": "d1eeadbb4e3d1c57af5a069a0886aa2b4f71484721aafe5c90708b66b8d0090a"
}
]
},
"osChanges": []
},
"id": 3,
"malicious": "yes",
"name": "MALWARE_OBJECT",
"occurred": "2021-02-14 09:45:58 +0000",
"product": "EMAIL_MPS",
"scVersion": "1115.212",
"severity": "MAJR",
"smtpMessage": {
"subject": "test"
},
"src": {
"smtpMailFrom": "test@malicious.net"
},
"uuid": "da0a1ee3-da28-46fa-9e5d-6663a76babba",
"vlan": 0
},
{
"ack": "no",
"action": "notified",
"alertUrl": "https://FireEyeEX/emps/eanalysis?e_id=16&type=url",
"applianceId": "86A8D8FA2D11",
"attackTime": "2021-02-14 09:53:30 +0000",
"dst": {
"smtpTo": "test@actualdomain.org"
},
"explanation": {
"malwareDetected": {
"malware": [
{
"md5Sum": "2a0bea4c95837d5e6c62eb1e7faa4cc4",
"name": "Phish.LIVE.DTI.URL",
"sha256": "56805163764d9eab8b7311844fa0df3c4c32535042794b1c9a24579fb7836f29"
}
]
},
"osChanges": []
},
"id": 4,
"malicious": "yes",
"name": "MALWARE_OBJECT",
"occurred": "2021-02-14 09:53:33 +0000",
"product": "EMAIL_MPS",
"scVersion": "1115.212",
"severity": "MAJR",
"smtpMessage": {
"subject": "test"
},
"src": {
"smtpMailFrom": "test@malicious.net"
},
"uuid": "058ed867-b131-4acf-8b14-884146329a7f",
"vlan": 0
}
]
}
}
Human Readable Output
FireEye Email Security Alerts
id occurred product name malicious severity alertUrl 1 2021-02-14 09:42:47 +0000 EMAIL_MPS MALWARE_OBJECT yes MAJR https://FireEyeEX/emps/eanalysis?e_id=9&type=url 2 2021-02-14 09:43:55 +0000 EMAIL_MPS MALWARE_OBJECT yes MAJR https://FireEyeEX/emps/eanalysis?e_id=10&type=url 3 2021-02-14 09:45:58 +0000 EMAIL_MPS MALWARE_OBJECT yes MAJR https://FireEyeEX/emps/eanalysis?e_id=12&type=url 4 2021-02-14 09:53:33 +0000 EMAIL_MPS MALWARE_OBJECT yes MAJR https://FireEyeEX/emps/eanalysis?e_id=16&type=url
fireeye-ex-get-alert-details
Searches and retrieves the details of a single alert.
Base Command
fireeye-ex-get-alert-details
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The ID of the alert for which to retrieve its details. | Required |
| timeout | Timeout to retrieve the alert details. Default is 30 seconds. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.Alerts.id | String | The ID of the alert. |
| FireEyeEX.Alerts.uuid | String | The UUID of the alert. |
| FireEyeEX.Alerts.occurred | String | The time when the alert occurred. |
| FireEyeEX.Alerts.product | String | The product name of the alert. |
| FireEyeEX.Alerts.rootInfection | String | The ID of the infection associated with the malware alert. |
| FireEyeEX.Alerts.name | String | The link to the infection associated with the malware alert. |
| FireEyeEX.Alerts.vlan | String | The virtual LAN (VLAN) of the alert. |
| FireEyeEX.Alerts.malicious | String | A flag indicating whether the alert is malicious. |
| FireEyeEX.Alerts.severity | String | The severity of the alert. |
| FireEyeEX.Alerts.sensor | String | The sensor name that the alert is associated with. |
| FireEyeEX.Alerts.applianceId | String | The appliance ID of the alert. |
| FireEyeEX.Alerts.sensorIp | String | The sensor IP that the alert is associated with. |
| FireEyeEX.Alerts.ack | String | A flag indicating whether an acknowledgment is received. |
| FireEyeEX.Alerts.src | Unknown | The source of the alert. |
| FireEyeEX.Alerts.dst | Unknown | The destination of the alert. |
| FireEyeEX.Alerts.explanation | Unknown | The explanation data of the alert. |
Command Example
!fireeye-ex-get-alert-details alert_id=3
Context Example
{
"FireEyeEX": {
"Alerts": {
"ack": "no",
"action": "notified",
"alertUrl": "https://FireEyeEX/emps/eanalysis?e_id=12&type=url",
"applianceId": "86A8D8FA2D11",
"attackTime": "2021-02-14 09:45:55 +0000",
"dst": {
"smtpTo": "test@actualdomain.org"
},
"explanation": {
"malwareDetected": {
"malware": [
{
"md5Sum": "a705075df02f217e8bfc9ac5ec2ffee2",
"name": "Malicious.LIVE.DTI.URL",
"sha256": "d1eeadbb4e3d1c57af5a069a0886aa2b4f71484721aafe5c90708b66b8d0090a"
}
]
},
"osChanges": []
},
"id": 3,
"malicious": "yes",
"name": "MALWARE_OBJECT",
"occurred": "2021-02-14 09:45:58 +0000",
"product": "EMAIL_MPS",
"scVersion": "1115.212",
"severity": "MAJR",
"smtpMessage": {
"subject": "test"
},
"src": {
"smtpMailFrom": "test@malicious.net"
},
"uuid": "da0a1ee3-da28-46fa-9e5d-6663a76babba",
"vlan": 0
}
}
}
Human Readable Output
FireEye Email Security Alerts
id occurred product name malicious action src dst severity alertUrl 3 2021-02-14 09:45:58 +0000 EMAIL_MPS MALWARE_OBJECT yes notified smtpMailFrom: test@malicious.net smtpTo: test@actualdomain.org MAJR https://FireEyeEX/emps/eanalysis?e_id=12&type=url
fireeye-ex-get-artifacts-by-uuid
Downloads malware artifacts data for the specified UUID as a zip file.
Base Command
fireeye-ex-get-artifacts-by-uuid
Input
| Argument Name | Description | Required |
|---|---|---|
| uuid | The universally unique identifier (UUID) for the alert. | Required |
| timeout | Timeout to retrieve the artifacts. Default is 120 seconds. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.EntryID | string | The EntryID of the artifact file. |
| InfoFile.Extension | string | The extension of the artifact file. |
| InfoFile.Name | string | The name of the artifact file. |
| InfoFile.Info | string | The info of the artifact file. |
| InfoFile.Size | number | The size of the artifact file. |
| InfoFile.Type | string | The type of the artifact file. |
Command Example
!fireeye-ex-get-artifacts-by-uuid uuid=44f2a6f0-aa3f-451d-956f-25565671c4d3
Context Example
{
"InfoFile": {
"EntryID": "452@2c246757-e02c-458a-8620-dbc236283fb8",
"Extension": "zip",
"Info": "application/zip",
"Name": "artifacts_44f2a6f0-aa3f-451d-956f-25565671c4d3.zip",
"Size": 401,
"Type": "Zip archive data, at least v2.0 to extract"
}
}
Human Readable Output
fireeye-ex-get-artifacts-metadata-by-uuid
Gets artifacts metadata for the specified UUID.
Base Command
fireeye-ex-get-artifacts-metadata-by-uuid
Input
| Argument Name | Description | Required |
|---|---|---|
| uuid | The universally unique identifier (UUID) for the alert. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.Alerts.uuid | string | Universally unique ID (UUID) of the alert. |
| FireEyeEX.Alerts.artifactsInfoList.artifactType | string | The artifact type. |
| FireEyeEX.Alerts.artifactsInfoList.artifactName | string | The artifact name. |
| FireEyeEX.Alerts.artifactsInfoList.artifactSize | string | The zipped artifact size in bytes. |
Command Example
!fireeye-ex-get-artifacts-metadata-by-uuid uuid=44f2a6f0-aa3f-451d-956f-25565671c4d3
Context Example
{
"FireEyeEX": {
"Alerts": {
"artifactsInfoList": [
{
"artifactName": "name",
"artifactSize": "269",
"artifactType": "original_email"
}
],
"uuid": "uuid"
}
}
}
Human Readable Output
FireEye Email Security 44f2a6f0-aa3f-451d-956f-25565671c4d3 Artifact metadata
artifactName artifactSize artifactType name 269 original_email
fireeye-ex-get-quarantined-emails
Searches and retrieves quarantined emails.
Base Command
fireeye-ex-get-quarantined-emails
Input
| Argument Name | Description | Required |
|---|---|---|
| start_time | Specifies the start time of the search. This filter is optional. Default is last day. Syntax: start_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om or ‘1 day/month/year’. Default is 1 day. | Optional |
| end_time | Specifies the end time of the search. Default is now. Syntax: end_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om or ‘1 day/month/year’. | Optional |
| from | The sender email. | Optional |
| subject | The email subject. Must be URL encoded. | Optional |
| appliance_id | The appliance ID. | Optional |
| limit | The number of emails to return. Default is 20. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.QuarantinedEmail.appliance_id | string | The appliance ID associated with the quarantined email. |
| FireEyeEX.QuarantinedEmail.completed_at | string | The time the email was quarantined. |
| FireEyeEX.QuarantinedEmail.email_uuid | string | The quarantined email UUID. |
| FireEyeEX.QuarantinedEmail.from | string | The quarantined email sender. |
| FireEyeEX.QuarantinedEmail.message_id | string | The quarantined email message ID. |
| FireEyeEX.QuarantinedEmail.quarantine_path | string | The quarantined email path. |
| FireEyeEX.QuarantinedEmail.The quarantined email queue id. | string | The quarantined email queue ID. |
| FireEyeEX.QuarantinedEmail.subject | string | The quarantined email subject. |
Command Example
!fireeye-ex-get-quarantined-emails limit=2
Context Example
{
"FireEyeEX": {
"QuarantinedEmail": [
{
"completed_at": "2021-06-14T16:01:15",
"email_uuid": "uuid",
"from": "undisclosed_sender",
"message_id": "queue-id-queue@no-message-id",
"quarantine_path": "/data/email-analysis/quarantine2/2021-06-14/16/queue",
"queue_id": "queue",
"subject": "test"
},
{
"completed_at": "2021-06-14T16:01:15",
"email_uuid": "uuid",
"from": "undisclosed_sender",
"message_id": "queue-id-queue@no-message-id",
"quarantine_path": "/data/email-analysis/quarantine2/2021-06-14/16/queue",
"queue_id": "queue",
"subject": "test"
}
]
}
}
Human Readable Output
FireEye Email Security Quarantined emails
email_uuid from subject message_id completed_at uuid undisclosed_sender test queue-id-queue@no-message-id 2021-06-14T16:01:15 uuid undisclosed_sender test queue-id-queue@no-message-id 2021-06-14T16:01:15
fireeye-ex-release-quarantined-emails
Releases and deletes quarantined emails. This is not available when Email Security is in Drop mode.
Base Command
fireeye-ex-release-quarantined-emails
Input
| Argument Name | Description | Required |
|---|---|---|
| queue_ids | The quarantined emails queue IDs. Supports up to 100 IDs. | Required |
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
### fireeye-ex-delete-quarantined-emails
***
Deletes quarantined emails. This is not available when Email Security is in Drop mode.
#### Base Command
`fireeye-ex-delete-quarantined-emails`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| queue_ids | The quarantined emails queue IDs. Supports up to 100 IDs. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
Human Readable Output
fireeye-ex-download-quarantined-emails
Download quarantined emails.
Base Command
fireeye-ex-download-quarantined-emails
Input
| Argument Name | Description | Required |
|---|---|---|
| queue_id | The quarantined emails queue ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Name | String | The name of the email. |
| File.MD5 | String | The MD5 hash of the email. |
| File.SHA1 | String | The SHA1 hash of the email. |
| File.SHA256 | String | The SHA256 hash of the email. |
| File.Type | String | The file type. |
| File.Size | Number | The size of the email in bytes. |
| File.SSDeep | String | The SSDeep hash of the email. |
Command Example
!fireeye-ex-download-quarantined-emails queue_id=queue
Context Example
{
"File": {
"EntryID": "479@2c246757-e02c-458a-8620-dbc236283fb8",
"Extension": "eml",
"Info": "message/rfc822",
"MD5": "b0320e23db6da746c694b79a60dac111",
"Name": "queue.eml",
"SHA1": "af85d7ebeeb359d94ea9a4d363acc429845042cf",
"SHA256": "e543f92e16f3eab595c9167e8739afd38156065e1c7c41a27ed399e14cd4cf2e",
"SHA512": "28a34e0042efa0a7b7dc865c9ce8f178228ccdb9f6d7fde11addef0bdbed95837bd3de4cbda79575be1ce67740d5e23634a63667de5f2c5a4f3b1209f6fd0f1e",
"SSDeep": "6:tnWrw+bcnWd4jXQ93f9FfZPl1WbZiAi1rzfSY4SXfT8oERf:tnWrwWcnWd4M9fZfWbG4MfPE5",
"Size": 269,
"Type": "RFC 822 mail text, ASCII text"
}
}
Human Readable Output
fireeye-ex-get-reports
Returns reports on selected alerts.
Base Command
fireeye-ex-get-reports
Input
| Argument Name | Description | Required |
|---|---|---|
| report_type | The report type. Possible values are: empsEmailAVReport, empsEmailActivity, empsEmailExecutiveSummary, empsEmailHourlyStat, mpsCallBackServer, mpsExecutiveSummary, mpsInfectedHostsTrend, mpsMalwareActivity, mpsWebAVReport, alertDetailsReport. | Required |
| start_time | Specifies the start time of the search. This filter is optional. Syntax: start_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om or ‘1 day/month/year’. Default is 1 week. | Optional |
| end_time | Specifies the end time of the search. Default is now. Syntax: end_time=YYYY-MM-DDTHH:mm:ss.sss-OH:om or ‘1 day/month/year’. | Optional |
| limit | Sets the maximum number (N) of items covered by each report. This option is required only for IPS TopN reports. Default is 100. | Optional |
| interface | Sets ihe internet interface. Possible values are: A, B, AB. This option is required only for IPS reports. | Optional |
| alert_id | Alert ID. This argument is only relevant when retrieving a report of type alertDetailsReport. | Optional |
| infection_id | Infection ID. This argument is only relevant when retrieving a report of type alertDetailsReport in conjunction with the infection_type argument. | Optional |
| infection_type | Infection Type. This argument is only relevant when retrieving a report of type alertDetailsReport in conjunction with the infection_id argument. Possible values are: malware-object, malware-callback, infection-match, domain-match, web-infection. | Optional |
| timeout | Timeout to retrieve the reports. Default is 120 seconds. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.EntryID | string | The EntryID of the artifact file. |
| InfoFile.Extension | string | The extension of the artifact file. |
| InfoFile.Name | string | The name of the artifact file. |
| InfoFile.Info | string | The info of the artifact file. |
| InfoFile.Size | number | The size of the artifact file. |
| InfoFile.Type | string | The type of the artifact file. |
Command Example
!fireeye-ex-get-reports report_type=alertDetailsReport alert_id=3
Context Example
{
"InfoFile": {
"EntryID": "475@2c246757-e02c-458a-8620-dbc236283fb8",
"Extension": "pdf",
"Info": "application/pdf",
"Name": "report_alertDetailsReport_1623743836.790785.pdf",
"Size": 0,
"Type": "empty"
}
}
Human Readable Output
fireeye-ex-list-allowedlist
Lists the allowed sender domain by type.
Base Command
fireeye-ex-list-allowedlist
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| limit | The number of entries to return. Default is 20. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
Command Example
#### Human Readable Output
### fireeye-ex-create-allowedlist
***
Creates allowed sender domain.
#### Base Command
`fireeye-ex-create-allowedlist`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to create. | Required |
| matches | The number of matches for the domain name when compared against the incoming emails. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name against the incoming emails. |
#### Command Example
Human Readable Output
fireeye-ex-update-allowedlist
Updates allowed sender domain.
Base Command
fireeye-ex-update-allowedlist
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to update. | Required |
| matches | The number of matches for the domain name when compared against the incoming emails. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
Command Example
#### Human Readable Output
### fireeye-ex-delete-allowedlist
***
Deletes allowed sender domain.
#### Base Command
`fireeye-ex-delete-allowedlist`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to delete. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
#### Command Example
Human Readable Output
fireeye-ex-list-blockedlist
Lists the blocked sender domain by type.
Base Command
fireeye-ex-list-blockedlist
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| limit | The number of entries to return. Default is 20. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
Command Example
#### Human Readable Output
### fireeye-ex-create-blockedlist
***
Creates blocked sender domain.
#### Base Command
`fireeye-ex-create-blockedlist`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to create. | Required |
| matches | The number of matches for the domain name when compared against the incoming emails. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
#### Command Example
Human Readable Output
fireeye-ex-update-blockedlist
Updates blocked sender domain.
Base Command
fireeye-ex-update-blockedlist
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to update. | Required |
| matches | The number of matches for the domain name when compared against the incoming emails. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
Command Example
#### Human Readable Output
### fireeye-ex-delete-blockedlist
***
Deletes blocked sender domain.
#### Base Command
`fireeye-ex-delete-blockedlist`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| type | The type of objects to retrieve. Possible values are: sender_email_address, sender_domain, sender_ip_address, recipient_email_address, url, md5sum. | Required |
| entry_value | The entry value we want to delete. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeEX.name | string | The allowed domain name. |
| FireEyeEX.created-at | string | The time the domain name was added to the list. |
| FireEyeEX.matches | string | The number of matches for the domain name when compared against the incoming emails. |
#### Command Example
Human Readable Output
Known Limitations
Clicking the Test button of the Integration instance settings window verifies that the instance configuration is correct.
Due to a known limitation, clicking the Test button several times in quick succession may result in an “Unauthorized” error, even after a successful result was initially returned. It is enough to receive one success message to verify that the configuration is correct. “Unauthorized” error messages received from repeated clicking of the instance configuration Test button do not affect the validity of the instance if the initial response was successful.
Configuration parameters
url— Your server URL (required)credentials— Username (required)isFetch— Fetch incidentsmax_fetch— Max incidents to fetchfirst_fetch— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year)incidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalinfo_level— Info level for fetched alertsinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (17)
-
fireeye-ex-create-allowedlistCreates allowed sender domain.
-
fireeye-ex-create-blockedlistCreates the blocked sender domain.
-
fireeye-ex-delete-allowedlistDeletes the allowed sender domain.
-
fireeye-ex-delete-blockedlistDeletes the blocked sender domain.
-
fireeye-ex-delete-quarantined-emailsDeletes quarantined emails. This is not available when Email Security is in Drop mode.
-
fireeye-ex-download-quarantined-emailsDownload quarantined emails.
-
fireeye-ex-get-alert-detailsSearches and retrieves the details of a single alert.
-
fireeye-ex-get-alertsSearches and retrieves FireEye EX alerts based on several filters.
-
fireeye-ex-get-artifacts-by-uuidDownloads malware artifacts data for the specified UUID as a zip file.
-
fireeye-ex-get-artifacts-metadata-by-uuidGets artifacts metadata for the specified UUID.
-
fireeye-ex-get-quarantined-emailsSearches and retrieves quarantined emails.
-
fireeye-ex-get-reportsReturns reports on selected alerts.
-
fireeye-ex-list-allowedlistLists the allowed sender domain by type.
-
fireeye-ex-list-blockedlistLists the blocked sender domain by type.
-
fireeye-ex-release-quarantined-emailsReleases and deletes quarantined emails. This is not available when Email Security is in Drop mode.
-
fireeye-ex-update-allowedlistUpdates the allowed sender domain.
-
fireeye-ex-update-blockedlistUpdates the blocked sender domain.
# Disable insecure warnings import urllib3 from CommonServerPython import * urllib3.disable_warnings() """ CONSTANTS """ INTEGRATION_NAME = "FireEye Email Security" INTEGRATION_COMMAND_NAME = "fireeye-ex" INTEGRATION_CONTEXT_NAME = "FireEyeEX" DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR class Client: """ The integration's client """ def __init__(self, base_url: str, username: str, password: str, verify: bool, proxy: bool): self.fe_client: FireEyeClient = FireEyeClient( base_url=base_url, username=username, password=password, verify=verify, proxy=proxy ) @logger def run_test_module(client: Client) -> str: """ Test module by getting alerts from the last day. """ start_time = to_fe_datetime_converter("1 day") client.fe_client.get_alerts_request( { "info_level": "concise", "start_time": start_time, "duration": "24_hours", } ) return "ok" @logger def get_alerts(client: Client, args: Dict[str, Any]) -> CommandResults: def parse_request_params(args: Dict[str, Any]) -> Dict: alert_id = args.get("alert_id", "") start_time = args.get("start_time", "") if start_time: start_time = to_fe_datetime_converter(start_time) end_time = args.get("end_time") if end_time: end_time = to_fe_datetime_converter(end_time) duration = args.get("duration") callback_domain = args.get("callback_domain", "") dst_ip = args.get("dst_ip", "") src_ip = args.get("src_ip", "") file_name = args.get("file_name", "") file_type = args.get("file_type", "") malware_name = args.get("malware_name", "") malware_type = args.get("malware_type", "") recipient_email = args.get("recipient_email", "") sender_email = args.get("sender_email", "") url_ = args.get("url", "") request_params = {"info_level": args.get("info_level", "concise")} if start_time: request_params["start_time"] = start_time if end_time: request_params["end_time"] = end_time if duration: request_params["duration"] = duration if alert_id: request_params["alert_id"] = alert_id if callback_domain: request_params["callback_domain"] = callback_domain if dst_ip: request_params["dst_ip"] = dst_ip if src_ip: request_params["src_ip"] = src_ip if file_name: request_params["file_name"] = file_name if file_type: request_params["file_type"] = file_type if malware_name: request_params["malware_name"] = malware_name if malware_type: request_params["malware_type"] = malware_type if recipient_email: request_params["recipient_email"] = recipient_email if sender_email: request_params["sender_email"] = sender_email if url_: request_params["url"] = url_ return request_params request_params = parse_request_params(args) limit = int(args.get("limit", "20")) raw_response = client.fe_client.get_alerts_request(request_params) alerts = raw_response.get("alert") if not alerts: md_ = f"No alerts with the given arguments were found.\n Arguments {request_params!s}" else: alerts = alerts[:limit] headers = ["id", "occurred", "name", "action", "smtpMessage", "src", "dst", "alertUrl"] md_ = tableToMarkdown(name=f"{INTEGRATION_NAME} Alerts:", t=alerts, headers=headers, removeNull=True) return CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Alerts", outputs_key_field="uuid", outputs=alerts, raw_response=raw_response, ) @logger def get_alert_details(client: Client, args: Dict[str, Any]) -> List[CommandResults]: alert_ids = argToList(args.get("alert_id")) timeout = int(args.get("timeout", "30")) command_results: List[CommandResults] = [] headers = ["id", "occurred", "name", "action", "smtpMessage", "src", "dst", "alertUrl"] for alert_id in alert_ids: raw_response = client.fe_client.get_alert_details_request(alert_id, timeout) alert_details = raw_response.get("alert") if not alert_details: md_ = f"Alert {alert_id} was not found." else: md_ = tableToMarkdown(name=f"{INTEGRATION_NAME} Alerts:", t=alert_details, headers=headers, removeNull=True) command_results.append( CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Alerts", outputs_key_field="uuid", outputs=alert_details, raw_response=raw_response, ) ) return command_results @logger def get_artifacts_by_uuid(client: Client, args: Dict[str, Any]): uuids = argToList(args.get("uuid")) timeout = int(args.get("timeout", "120")) for uuid in uuids: artifact = client.fe_client.get_artifacts_by_uuid_request(uuid, timeout) demisto.results(fileResult(f"artifacts_{uuid}.zip", data=artifact, file_type=EntryType.ENTRY_INFO_FILE)) @logger def get_artifacts_metadata_by_uuid(client: Client, args: Dict[str, Any]) -> List[CommandResults]: uuids: List[str] = argToList(str(args.get("uuid"))) command_results: List[CommandResults] = [] for uuid in uuids: raw_response = client.fe_client.get_artifacts_metadata_by_uuid_request(uuid) outputs = raw_response outputs["uuid"] = uuid # type: ignore md_ = tableToMarkdown( name=f"{INTEGRATION_NAME} {uuid} Artifact metadata:", t=raw_response.get("artifactsInfoList"), removeNull=True ) command_results.append( CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Alerts", outputs_key_field="uuid", outputs=outputs, raw_response=raw_response, ) ) return command_results @logger def get_quarantined_emails(client: Client, args: Dict[str, Any]) -> CommandResults: start_time = to_fe_datetime_converter(args.get("start_time", "1 day")) end_time = to_fe_datetime_converter(args.get("end_time", "now")) from_ = args.get("from", "") subject = args.get("subject", "") appliance_id = args.get("appliance_id", "") limit = args.get("limit", "10000") raw_response = client.fe_client.get_quarantined_emails_request(start_time, end_time, from_, subject, appliance_id, limit) if not raw_response: md_ = "No emails with the given query arguments were found." else: headers = ["email_uuid", "from", "subject", "message_id", "completed_at"] md_ = tableToMarkdown(name=f"{INTEGRATION_NAME} Quarantined emails:", t=raw_response, headers=headers, removeNull=True) return CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.QuarantinedEmail", outputs_key_field="email_uuid", outputs=raw_response, raw_response=raw_response, ) @logger def release_quarantined_emails(client: Client, args: Dict[str, Any]) -> CommandResults: queue_ids = argToList(args.get("queue_ids", "")) raw_response = client.fe_client.release_quarantined_emails_request(queue_ids, "") if raw_response.text: # returns 200 either way. if operation is successful than resp is empty raise DemistoException(raw_response.json()) else: md_ = f"{INTEGRATION_NAME} released emails successfully." return CommandResults(readable_output=md_, raw_response="") @logger def delete_quarantined_emails(client: Client, args: Dict[str, Any]) -> CommandResults: queue_ids = argToList(args.get("queue_ids", "")) raw_response = client.fe_client.delete_quarantined_emails_request(queue_ids) if raw_response.text: # returns 200 either way. if operation is successful than resp is empty raise DemistoException(raw_response.json()) else: md_ = f"{INTEGRATION_NAME} deleted emails successfully." return CommandResults(readable_output=md_, raw_response="") @logger def download_quarantined_emails(client: Client, args: Dict[str, Any]): queue_id = args.get("queue_id", "") timeout = int(args.get("timeout", "120")) raw_response = client.fe_client.download_quarantined_emails_request(queue_id, timeout) demisto.results(fileResult(f"quarantined_email_{queue_id}.eml", data=raw_response, file_type=EntryType.FILE)) @logger def get_reports(client: Client, args: Dict[str, Any]): report_type = args.get("report_type", "") start_time = to_fe_datetime_converter(args.get("start_time", "1 week")) end_time = to_fe_datetime_converter(args.get("end_time", "now")) limit = args.get("limit", "100") interface = args.get("interface", "") alert_id = args.get("alert_id", "") infection_id = args.get("infection_id", "") infection_type = args.get("infection_type", "") timeout = int(args.get("timeout", "120")) if report_type == "alertDetailsReport": # validate arguments # can use either alert_id, or infection_type and infection_id err_str = "The alertDetailsReport can be retrieved using alert_id argument alone, or by infection_type and infection_id" if alert_id: if infection_id or infection_type: raise DemistoException(err_str) else: if not infection_id and not infection_type: raise DemistoException(err_str) try: raw_response = client.fe_client.get_reports_request( report_type, start_time, end_time, limit, interface, alert_id, infection_type, infection_id, timeout ) csv_reports = {"empsEmailAVReport", "empsEmailHourlyStat", "mpsCallBackServer", "mpsInfectedHostsTrend", "mpsWebAVReport"} prefix = "csv" if report_type in csv_reports else "pdf" demisto.results( fileResult( f"report_{report_type}_{datetime.now().timestamp()}.{prefix}", data=raw_response, file_type=EntryType.ENTRY_INFO_FILE, ) ) except Exception as err: if "WSAPI_REPORT_ALERT_NOT_FOUND" in str(err): return CommandResults(readable_output=f"Report {report_type} was not found with the given arguments.") else: raise @logger def list_allowedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") limit = int(args.get("limit", "20")) raw_response = client.fe_client.list_allowedlist_request(type_) allowed_list = [] if not raw_response: md_ = f"No allowed lists with the given type {type_} were found." else: allowed_list = raw_response[:limit] md_ = tableToMarkdown( name=f"{INTEGRATION_NAME} Allowed lists. showing {limit} of {len(raw_response)}:", t=allowed_list, removeNull=True ) return CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Allowedlists", outputs_key_field="name", outputs=allowed_list, raw_response=raw_response, ) @logger def create_allowedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") matches = int(args.get("matches", "0")) # check that the entry_value does not exist current_allowed_list = client.fe_client.list_allowedlist_request(type_) for entry in current_allowed_list: if entry_value == entry.get("name"): raise DemistoException( str(f"Cannot create the entry_value {entry_value} as it is already exist in the Allowedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.create_allowedlist_request(type_, entry_value, matches) return CommandResults(readable_output=f"Allowedlist entry {entry_value} of type {type_} was created.") @logger def update_allowedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") matches = int(args.get("matches", "0")) # check that the entry_value does exist exist = False current_allowed_list = client.fe_client.list_allowedlist_request(type_) for entry in current_allowed_list: if entry_value == entry.get("name"): exist = True if not exist: raise DemistoException( str(f"Cannot update the entry_value {entry_value} as it does not exist in the Allowedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.update_allowedlist_request(type_, entry_value, matches) return CommandResults(readable_output=f"Allowedlist entry {entry_value} of type {type_} was updated.") @logger def delete_allowedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") # check that the entry_value does exist exist = False current_allowed_list = client.fe_client.list_allowedlist_request(type_) for entry in current_allowed_list: if entry_value == entry.get("name"): exist = True if not exist: raise DemistoException( str(f"Cannot delete the entry_value {entry_value} as it does not exist in the Allowedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.delete_allowedlist_request(type_, entry_value) return CommandResults(readable_output=f"Allowedlist entry {entry_value} of type {type_} was deleted.") @logger def list_blockedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") limit = int(args.get("limit", "20")) raw_response = client.fe_client.list_blockedlist_request(type_) blocked_list = [] if not raw_response: md_ = f"No blocked lists with the given type {type_} were found." else: blocked_list = raw_response[:limit] md_ = tableToMarkdown( name=f"{INTEGRATION_NAME} Blocked lists. showing {limit} of {len(raw_response)}:", t=blocked_list, removeNull=True ) return CommandResults( readable_output=md_, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Blockedlists", outputs_key_field="name", outputs=blocked_list, raw_response=raw_response, ) @logger def create_blockedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") matches = int(args.get("matches", "0")) # check that the entry_value does not exist current_blocked_list = client.fe_client.list_blockedlist_request(type_) for entry in current_blocked_list: if entry_value == entry.get("name"): raise DemistoException( str(f"Cannot create the entry_value {entry_value} as it is already exist in the Blockedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.create_blockedlist_request(type_, entry_value, matches) return CommandResults(readable_output=f"Blockedlist entry {entry_value} of type {type_} was created.") @logger def update_blockedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") matches = int(args.get("matches", "0")) # check that the entry_value does exist exist = False current_allowed_list = client.fe_client.list_blockedlist_request(type_) for entry in current_allowed_list: if entry_value == entry.get("name"): exist = True if not exist: raise DemistoException( str(f"Cannot update the entry_value {entry_value} as it does not exist in the Blockedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.update_blockedlist_request(type_, entry_value, matches) return CommandResults(readable_output=f"Blockedlist entry {entry_value} of type {type_} was updated.") @logger def delete_blockedlist(client: Client, args: Dict[str, Any]) -> CommandResults: type_ = args.get("type", "") entry_value = args.get("entry_value", "") # check that the entry_value does exist exist = False current_allowed_list = client.fe_client.list_blockedlist_request(type_) for entry in current_allowed_list: if entry_value == entry.get("name"): exist = True if not exist: raise DemistoException( str(f"Cannot delete the entry_value {entry_value} as it does not exist in the Blockedlist of type {type_}.") ) # gets 200 back without content if successful client.fe_client.delete_blockedlist_request(type_, entry_value) return CommandResults(readable_output=f"Blockedlist entry {entry_value} of type {type_} was deleted.") @logger def fetch_incidents( client: Client, last_run: dict, first_fetch: str, max_fetch: int = 50, info_level: str = "concise" ) -> tuple[dict, list]: if not last_run: # if first time fetching next_run = {"time": to_fe_datetime_converter(first_fetch), "last_alert_ids": []} else: next_run = last_run demisto.info(f'{INTEGRATION_NAME} executing fetch with: {next_run.get("time")!s}') raw_response = client.fe_client.get_alerts_request( request_params={ "start_time": to_fe_datetime_converter(next_run["time"]), # type: ignore "info_level": info_level, "duration": "48_hours", } ) all_alerts = raw_response.get("alert") ten_minutes_date = dateparser.parse("10 minutes") assert ten_minutes_date is not None if not all_alerts: demisto.info(f"{INTEGRATION_NAME} no alerts were fetched from FireEye server at: {next_run!s}") # as no alerts occurred in the window of 48 hours from the given start time, update last_run window to the next # 48 hours. If it is later than now -10 minutes take the latter (to avoid missing events). two_days_from_last_search = dateparser.parse(next_run["time"]) + timedelta(hours=48) # type: ignore assert two_days_from_last_search is not None now_minus_ten_minutes = ten_minutes_date.astimezone(two_days_from_last_search.tzinfo) # type: ignore next_search = min(two_days_from_last_search, now_minus_ten_minutes) assert next_search is not None next_run = { "time": next_search.isoformat(), # type: ignore "last_alert_ids": [], } demisto.info(f"{INTEGRATION_NAME} setting next run to: {next_run!s}") return next_run, [] alerts = all_alerts[:max_fetch] last_alert_ids = last_run.get("last_alert_ids", []) incidents = [] for alert in alerts: alert_id = str(alert.get("id")) if alert_id not in last_alert_ids: # check that event was not fetched in the last fetch incident = { "name": f"{INTEGRATION_NAME} Alert: {alert_id}", "occurred": dateparser.parse( alert.get("occurred"), # type: ignore[union-attr] settings={"TO_TIMEZONE": "UTC"}, ).strftime(DATE_FORMAT), # type: ignore "severity": alert_severity_to_dbot_score(alert.get("severity")), "rawJSON": json.dumps(alert), } incidents.append(incident) last_alert_ids.append(alert_id) if not incidents: demisto.info(f"{INTEGRATION_NAME} no new alerts were collected at: {next_run!s}.") # As no incidents were collected, we know that all the fetched alerts for 48 hours starting in the 'start_time' # already exists in our system, thus update last_run time to look for the next 48 hours. If it is later than # now -10 minutes take the latter (to avoid missing events) two_days_from_last_incident = dateparser.parse(alerts[-1].get("occurred")) + timedelta(hours=48) # type: ignore now_minus_ten_minutes = ten_minutes_date.astimezone(two_days_from_last_incident.tzinfo) # type: ignore next_search = min(two_days_from_last_incident, now_minus_ten_minutes) next_run["time"] = next_search.isoformat() # type: ignore demisto.info(f'{INTEGRATION_NAME} Setting next_run to: {next_run["time"]}') return next_run, [] # as alerts occurred till now, update last_run time accordingly to the that of latest fetched alert next_run = { "time": alerts[-1].get("occurred"), "last_alert_ids": last_alert_ids, # save the alert IDs from the last fetch } demisto.info(f"{INTEGRATION_NAME} Fetched {len(incidents)}. last fetch at: {next_run!s}") return next_run, incidents def main() -> None: params = demisto.params() username = params.get("credentials").get("identifier") password = params.get("credentials").get("password") # there is also a v1.2.0 which holds different paths and params, we support only the newest API version base_url = urljoin(params.get("url"), "/wsapis/v2.0.0/") verify = not argToBoolean(params.get("insecure", "false")) proxy = argToBoolean(params.get("proxy")) # # fetch params max_fetch = int(params.get("max_fetch", "50")) first_fetch = params.get("first_fetch", "3 days").strip() info_level = params.get("info_level", "concise") command = demisto.command() args = demisto.args() LOG(f"Command being called is {command}") try: client = Client(base_url=base_url, username=username, password=password, verify=verify, proxy=proxy) commands = { f"{INTEGRATION_COMMAND_NAME}-get-alerts": get_alerts, f"{INTEGRATION_COMMAND_NAME}-get-alert-details": get_alert_details, f"{INTEGRATION_COMMAND_NAME}-get-artifacts-by-uuid": get_artifacts_by_uuid, f"{INTEGRATION_COMMAND_NAME}-get-artifacts-metadata-by-uuid": get_artifacts_metadata_by_uuid, f"{INTEGRATION_COMMAND_NAME}-get-quarantined-emails": get_quarantined_emails, f"{INTEGRATION_COMMAND_NAME}-release-quarantined-emails": release_quarantined_emails, f"{INTEGRATION_COMMAND_NAME}-delete-quarantined-emails": delete_quarantined_emails, f"{INTEGRATION_COMMAND_NAME}-download-quarantined-emails": download_quarantined_emails, f"{INTEGRATION_COMMAND_NAME}-list-allowedlist": list_allowedlist, f"{INTEGRATION_COMMAND_NAME}-create-allowedlist": create_allowedlist, f"{INTEGRATION_COMMAND_NAME}-update-allowedlist": update_allowedlist, f"{INTEGRATION_COMMAND_NAME}-delete-allowedlist": delete_allowedlist, f"{INTEGRATION_COMMAND_NAME}-list-blockedlist": list_blockedlist, f"{INTEGRATION_COMMAND_NAME}-create-blockedlist": create_blockedlist, f"{INTEGRATION_COMMAND_NAME}-update-blockedlist": update_blockedlist, f"{INTEGRATION_COMMAND_NAME}-delete-blockedlist": delete_blockedlist, } if command == "test-module": return_results(run_test_module(client)) elif command == "fetch-incidents": next_run, incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), first_fetch=first_fetch, max_fetch=max_fetch, info_level=info_level ) demisto.setLastRun(next_run) demisto.incidents(incidents) elif command == f"{INTEGRATION_COMMAND_NAME}-get-artifacts-by-uuid": get_artifacts_by_uuid(client, args) elif command == f"{INTEGRATION_COMMAND_NAME}-get-reports": get_reports(client, args) elif command == f"{INTEGRATION_COMMAND_NAME}-download-quarantined-emails": download_quarantined_emails(client, args) elif command in commands: return_results(commands[command](client, args)) else: raise NotImplementedError(f'Command "{command}" is not implemented.') except Exception as err: return_error(str(err), err) from FireEyeApiModule import * # noqa: E402 if __name__ in ("__main__", "__builtin__", "builtins"): main()