FraudWatch
Manage incidents via the Fraudwatch API. FraudWatch International provides a fully managed Enterprise Digital Brand Protection Suite, including online brand management & monitoring, as well as providing other brand protection solutions that protect organizations and their customers around the world against online brand-related abuse.
Data Enrichment & Threat Intelligence · FraudWatch PhishPortal
Details
| ID | FraudWatch |
|---|---|
| Provider | Netcraft |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Manage incidents via the Fraudwatch API. FraudWatch International provides a fully managed Enterprise Digital Brand Protection Suite, including online brand management & monitoring as well as providing other brand protection solutions that protect organizations and their customers around the world against online brand-related abuse.
This integration was integrated and tested with version v1 of FraudWatch Phishportal
Retrieve FraudWatch API token
- Navigate to the Phishportal site.
- Enter your Username and Password.
- On the left sidebar, click on ‘Portal API’.
- On the top of the page, you should see your API Token.
- If the API token is out of date, click on the Regenerate Token button adjacent to the API token, to generate a new token.
- Set the API token in the Password parameter.
NOTE: no need to set the Username parameter it can be left blank (visible only on 6.0.2 and lower versions).

Configure FraudWatch on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for FraudWatch.
-
Click Add instance to create and configure a new integration instance.
Parameter Description Required Fetch incidents False API Token (leave empty. Fill in the API token in the password field.) False Server URL URL of the server. True Brand Fetch incidents that match the specified brand. An error is encountered if the brand does not exist. A list of the existing brands can be retrieved by the ‘fraudwatch-brands-list’ command. False Status Fetch incidents that have the specified status. False Incident type False Incidents Fetch Interval False First fetch timestamp format: ( <number><time unit>, e.g., 12 hours, 1 day)False Maximum Incidents To Fetch False Trust any certificate (not secure) False Use system proxy settings False - Click Test to validate the URLs, token, and connection.
Fetch Incidents
Due to limitations in FraudWatch API, first fetch timestamp can be at most 1 day.
Commands
You can execute these commands from the Cortex XSOAR 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.
fraudwatch-incidents-list
Get a list of incidents from FraudWatch service.
Base Command
fraudwatch-incidents-list
Input
| Argument Name | Description | Required |
|---|---|---|
| brand | Retrieve incidents that match the specified brand. An error is encountered if the brand does not exist. A list of the existing brands can be retrieved by the ‘fraudwatch-brands-list’ command. | Optional |
| status | Retrieve incidents that have the specified status. Possible values are: active, new, monitor, reactive, onhold, closed, closedmonitor, rejected, duplicate. | Optional |
| limit | Number of incidents to retrieve. | Optional |
| page_size | The number of incidents in a page. Maximum value is 200. | Optional |
| page | Retrieve incidents by the given page number. | Optional |
| from | Retrieve alerts for which ‘date opened’ is higher or equal to the ‘from’ value. Supports ISO and time range (<number> <time unit>, e.g., 12 hours, 7 days) formats. If not specified, the default value of ‘to’ is the current time. | Optional |
| to | Retrieve alerts for which ‘date opened’ is lower or equal to the ‘to’ value. Supports ISO and time range (<number> <time unit>, e.g., 12 hours, 7 days) formats. If not specified, the default value of ‘from’ is 12 months before ‘to’. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.Incident.identifier | String | Incident identifier. |
| FraudWatch.Incident.reference_id | String | Incident reference ID. |
| FraudWatch.Incident.url | String | Main URL associated with the incident. |
| FraudWatch.Incident.status | String | Incident status. |
| FraudWatch.Incident.type | String | Incident type. |
| FraudWatch.Incident.brand | String | Incident brand. |
| FraudWatch.Incident.client | String | Incident client. |
| FraudWatch.Incident.content_ip | String | Incident content IP. |
| FraudWatch.Incident.host | String | Incident host. |
| FraudWatch.Incident.host_country | String | Incident host country. |
| FraudWatch.Incident.host_timezone | String | Incident host timezone. |
| FraudWatch.Incident.created_by | String | Who created the incident. |
| FraudWatch.Incident.discovered_by | String | Who discovered the incident. |
| FraudWatch.Incident.current_duration | String | Current duration of the incident. |
| FraudWatch.Incident.active_duration | Unknown | Current active duration of the incident. |
| FraudWatch.Incident.date_opened | Date | The date in which the incident was opened. |
| FraudWatch.Incident.date_closed | Date | The date in which the incident was closed. |
| FraudWatch.Incident.additional_urls | String | Additional URLs associated with the incident. |
| FraudWatch.Incident.link | String | Link to the incident page in the FraudWatch user interface. |
Command Example
!fraudwatch-incidents-list brand="Testing Brand 2" from="2020-12-12" limit=3 status=monitor
Context Example
{
"FraudWatch": {
"Incident": [
{
"active_duration": null,
"additional_urls": [
"http://www.malicious2.com",
"http://www.malicious3.com",
"http://www.malicious4.com",
"http://www.malicious5.com"
],
"brand": "Testing Brand 2",
"client": "Palo Alto",
"content_ip": null,
"created_by": "Client",
"current_duration": "85882",
"date_closed": null,
"date_opened": "2021-02-07T15:37:12.000Z",
"discovered_by": "client",
"host": null,
"host_country": null,
"host_timezone": null,
"identifier": "JJJ-595483",
"link": "https://www.phishportal.com/client/incident/JJJ-595483",
"reference_id": "abc1234",
"status": "monitor",
"type": "Vishing",
"url": "http://www.malicious.com"
},
{
"active_duration": null,
"additional_urls": [
"http://www.malicious2.com",
"http://www.malicious3.com",
"http://www.malicious4.com",
"http://www.malicious5.com"
],
"brand": "Testing Brand 2",
"client": "Palo Alto",
"content_ip": null,
"created_by": "Client",
"current_duration": "86649",
"date_closed": null,
"date_opened": "2021-02-07T15:24:25.000Z",
"discovered_by": "client",
"host": null,
"host_country": null,
"host_timezone": null,
"identifier": "JJJ-992295",
"link": "https://www.phishportal.com/client/incident/JJJ-992295",
"reference_id": "abc1234",
"status": "monitor",
"type": "Vishing",
"url": "http://www.malicious.com"
},
{
"active_duration": null,
"additional_urls": [
"abuse.com"
],
"brand": "Testing Brand 2",
"client": "Palo Alto",
"content_ip": "192.168.0.1",
"created_by": "Client",
"current_duration": "340758",
"date_closed": null,
"date_opened": "2021-02-04T16:49:16.000Z",
"discovered_by": "client",
"host": null,
"host_country": null,
"host_timezone": null,
"identifier": "JJJ-302171",
"link": "https://www.phishportal.com/client/incident/JJJ-302171",
"reference_id": "malicious1",
"status": "monitor",
"type": "Brand Abuse",
"url": "http://malicious.com"
}
]
}
}
Human Readable Output
FraudWatch Incidents
identifier reference_id url status type brand client content_ip created_by discovered_by current_duration date_opened additional_urls link JJJ-595483 abc1234 http://www.malicious.com monitor Vishing Testing Brand 2 Palo Alto Client client 85882 2021-02-07T15:37:12.000Z http://www.malicious2.com,
http://www.malicious3.com,
http://www.malicious4.com,
http://www.malicious5.comhttps://www.phishportal.com/client/incident/JJJ-595483 JJJ-992295 abc1234 http://www.malicious.com monitor Vishing Testing Brand 2 Palo Alto Client client 86649 2021-02-07T15:24:25.000Z http://www.malicious2.com,
http://www.malicious3.com,
http://www.malicious4.com,
http://www.malicious5.comhttps://www.phishportal.com/client/incident/JJJ-992295 JJJ-302171 malicious1 http://malicious.com monitor Brand Abuse Testing Brand 2 Palo Alto 192.168.0.1 Client client 340758 2021-02-04T16:49:16.000Z abuse.com https://www.phishportal.com/client/incident/JJJ-302171
fraudwatch-incident-report
Report an incident to FraudWatch service.
Base Command
fraudwatch-incident-report
Input
| Argument Name | Description | Required |
|---|---|---|
| brand | The brand associated with the reported incident. An error is encountered if the brand does not exist. A list of the existing brands can be retrieved by the ‘fraudwatch-brands-list’ command. | Required |
| type | The incident type to be associated with the reported incident. Possible values are: phishing, vishing, brand_abuse, malware, social_media_brand_abuse, mobile_app_unauthorized, pac_file, pharming, messaging, dmarc_email_server. | Required |
| reference_id | Reference ID to be associated with the reported incident. Should be unique. Reference ID can be used later on to retrieve a specific incident by its reference ID. | Optional |
| primary_url | Primary URL of the reported incident. | Required |
| urls | A Comma-separated list of additional URLs to be associated with the reported incident. | Optional |
| evidence | Evidence to be added (such as logs, etc…) to the reported incident. | Optional |
| instructions | Additional instructions to be added for the FraudWatch security team. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.Incident.identifier | String | Incident identifier. |
| FraudWatch.Incident.reference_id | String | Incident reference ID. |
| FraudWatch.Incident.url | String | Main URL associated with the incident. |
| FraudWatch.Incident.status | String | Incident status. |
| FraudWatch.Incident.type | String | Incident type. |
| FraudWatch.Incident.brand | String | Incident brand. |
| FraudWatch.Incident.client | String | Incident client. |
| FraudWatch.Incident.content_ip | String | Incident content IP. |
| FraudWatch.Incident.host | String | Incident host. |
| FraudWatch.Incident.host_country | String | Incident host contry. |
| FraudWatch.Incident.host_timezone | String | Incident host timezone. |
| FraudWatch.Incident.created_by | String | Who created the incident. |
| FraudWatch.Incident.discovered_by | String | Who discovered the incident. |
| FraudWatch.Incident.current_duration | String | Current duration of the incident. |
| FraudWatch.Incident.active_duration | Unknown | Current active duration of the incident. |
| FraudWatch.Incident.date_opened | Date | The date in which the incident was opened. |
| FraudWatch.Incident.date_closed | Date | The date in which the incident was closed. This field is expected to be empty because the incident was just created. |
| FraudWatch.Incident.additional_urls | String | Additional URLs associated with the incident. |
| FraudWatch.Incident.link | String | Link to the incident page in the FraudWatch user interface. |
Command Example
!fraudwatch-incident-report brand="Testing Brand 1" primary_url="http://www.maliciousaddress.com" type="vishing" reference_id="abc123" urls="http://abuse.com"
Context Example
{
"FraudWatch": {
"Incident": {
"active_duration": null,
"additional_urls": [
"http://abuse.com"
],
"brand": "Testing Brand 1",
"client": "Palo Alto",
"content_ip": null,
"created_by": "FraudWatch",
"current_duration": "0",
"date_closed": null,
"date_opened": "2021-02-08T15:28:37.000Z",
"discovered_by": "client",
"host": null,
"host_country": null,
"host_timezone": null,
"identifier": "JJJ-358877",
"link": "https://www.phishportal.com/client/incident/JJJ-358877",
"reference_id": "abc123",
"status": "monitor",
"type": "Vishing",
"url": "http://www.maliciousaddress.com"
}
}
}
Human Readable Output
Created FraudWatch Incident
additional_urls brand client created_by current_duration date_opened discovered_by identifier link reference_id status type url http://abuse.com Testing Brand 1 Palo Alto FraudWatch 0 2021-02-08T15:28:37.000Z client JJJ-358877 https://www.phishportal.com/client/incident/JJJ-358877 abc123 monitor Vishing http://www.maliciousaddress.com
fraudwatch-incident-update
Updates the incident associated with the ‘incident_id’ with the specified argument values.
Base Command
fraudwatch-incident-update
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident to be updated. The incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
| brand | Updates the incident associated with the ‘incident_id’ with the brand specified. An error is encountered if the brand does not exist. A list of the existing brands can be retrieved by the ‘fraudwatch-brands-list’ command. | Optional |
| reference_id | Updates the incident associated with the ‘incident_id’ with the reference ID specified. Reference ID should be unique, and can be used by the ‘fraudwatch-incident-get-by-identifier’ command to retrieve a specific incident by its reference id. | Optional |
| evidence | Evidence to be added (such as logs, etc…) to the incident. | Optional |
| instructions | Updates the incident associated with the ‘incident_id’ with additional instructions for the FraudWatch security team. | Optional |
Context Output
There is no context output for this command.
Command Example
!fraudwatch-incident-update incident_id=JJJ-504830 brand="Testing Brand 2" reference_id="reference123"
Human Readable Output
Incident with ID JJJ-504830 was updated successfully
fraudwatch-incident-get-by-identifier
Gets an incident from FraudWatch service by its reference ID or incident ID. Single values of ‘reference_id’ and ‘incident_id’ should be specified.
Base Command
fraudwatch-incident-get-by-identifier
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident to retrieve. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Optional |
| reference_id | Reference id of the incident to retrieve. If more than one incident is associated with ‘reference_id’ specified, returns the details of the incident with the latest ‘date opened’. Reference ID is the ‘reference_id’ field returned by the ‘fraudwatch-incidents-list’ command. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.Incident.identifier | String | Incident identifier. |
| FraudWatch.Incident.reference_id | String | Incident reference ID. |
| FraudWatch.Incident.url | String | Main URL associated with the incident. |
| FraudWatch.Incident.status | String | Incident status. |
| FraudWatch.Incident.type | String | Incident type. |
| FraudWatch.Incident.brand | String | Incident brand. |
| FraudWatch.Incident.client | String | Incident client. |
| FraudWatch.Incident.content_ip | String | Incident content IP. |
| FraudWatch.Incident.host | String | Incident host. |
| FraudWatch.Incident.host_country | String | Incident host country. |
| FraudWatch.Incident.host_timezone | String | Incident host timezone. |
| FraudWatch.Incident.created_by | String | Who created the incident. |
| FraudWatch.Incident.discovered_by | String | Who discovered the incident. |
| FraudWatch.Incident.current_duration | String | Current duration of the incident. |
| FraudWatch.Incident.active_duration | Unknown | Current active duration of the incident. |
| FraudWatch.Incident.date_opened | Date | The date in which the incident was opened. |
| FraudWatch.Incident.date_closed | Date | The date in which the incident was closed. |
| FraudWatch.Incident.additional_urls | String | Additional URLs associated with the incident. |
| FraudWatch.Incident.link | String | Link to the incident page in the FraudWatch user interface. |
Command Example
!fraudwatch-incident-get-by-identifier incident_id=JJJ-168840
Context Example
{
"FraudWatch": {
"Incident": {
"active_duration": null,
"additional_urls": [
"http://malicious1.com",
"http://malicious2.com"
],
"brand": "Testing Brand 1",
"client": "Palo Alto",
"content_ip": null,
"created_by": "Client",
"current_duration": "514313",
"date_closed": null,
"date_opened": "2021-02-02T16:36:50.000Z",
"discovered_by": "client",
"host": null,
"host_country": null,
"host_timezone": null,
"identifier": "JJJ-168840",
"link": "https://www.phishportal.com/client/incident/JJJ-168840",
"reference_id": null,
"status": "monitor",
"type": "Vishing",
"url": "test.com"
}
}
}
Human Readable Output
FraudWatch Incident
additional_urls brand client created_by current_duration date_opened discovered_by identifier link status type url http://malicious1.com,
http://malicious2.comTesting Brand 1 Palo Alto Client 514313 2021-02-02T16:36:50.000Z client JJJ-168840 https://www.phishportal.com/client/incident/JJJ-168840 monitor Vishing test.com
fraudwatch-incident-forensic-get
Gets the forensic data of the incident associated with the specified incident ID.
Base Command
fraudwatch-incident-forensic-get
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident for which to retrieve the forensic data. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.IncidentForensicData.host_provider.name | String | Name of the host provider. |
| FraudWatch.IncidentForensicData.host_provider.country | String | Country of the host provider. |
| FraudWatch.IncidentForensicData.host_nameservers | String | Names of the host servers. |
| FraudWatch.IncidentForensicData.host_domain_registrar.name | String | Host domain registrar name. |
| FraudWatch.IncidentForensicData.host_domain_registrar.email | String | Host domain registrar email. |
| FraudWatch.IncidentForensicData.host_domain_registrar.country | String | Host domain registrar country. |
| FraudWatch.IncidentForensicData.host_site_owner | Unknown | Host site owner. |
| FraudWatch.IncidentForensicData.host_site_admin | Unknown | Host site admin. |
| FraudWatch.IncidentForensicData.host_domain_admin | Unknown | Host domain admin. |
| FraudWatch.IncidentForensicData.host_ip_providier | Unknown | Host IP provider. |
| FraudWatch.IncidentForensicData.identifier | String | Identifier of the incident. |
Command Example
!fraudwatch-incident-forensic-get incident_id=JJJ-397266
Context Example
{
"FraudWatch": {
"IncidentForensicData": {
"host_domain_registrar": {
"country": "abuse@address.com",
"email": "http://www.abuseaddress.com",
"name": "Moniker Online Services LLC"
},
"host_nameservers": [
"NS1.IRAN.COM",
"NS2.IRAN.COM"
],
"identifier": "JJJ-397266"
}
}
}
Human Readable Output
FraudWatch Incident Forensic Data
host_domain_registrar host_nameservers identifier name: Moniker Online Services LLC
email: http://www.abuseaddress.com
country: abuse@address.comNS1.IRAN.COM,
NS2.IRAN.COMJJJ-397266
fraudwatch-incident-contact-emails-list
Provides a list of the messages related to the incident associated with the specified incident ID.
Base Command
fraudwatch-incident-contact-emails-list
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident for which to retrieve the related messages. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
| limit | Number of related messages to retrieve. | Optional |
| page_size | Maximum number of related messages in a page. Maximum value is 200. | Optional |
| page | Retrieve related messages by the specified page number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.IncidentContacts.noteId | String | Note ID of the related message. |
| FraudWatch.IncidentContacts.subject | String | Subject of the related message. |
| FraudWatch.IncidentContacts.creator | String | The creator of the related message. |
| FraudWatch.IncidentContacts.content | String | The content of the related message. |
| FraudWatch.IncidentContacts.date | Date | The date of the related message. |
Command Example
!fraudwatch-incident-contact-emails-list incident_id=JJJ-898410 limit=2
Context Example
{
"FraudWatch": {
"IncidentContacts": [
{
"content": "This incident is very malicious, please monitor it\r\n",
"creator": "Client",
"date": "2021-02-08T15:26:19.000Z",
"noteId": "11081853",
"subject": "Client Reply"
},
{
"content": "This incident is very malicious, please monitor it\r\n",
"creator": "Client",
"date": "2021-02-08T15:21:58.000Z",
"noteId": "11081828",
"subject": "Client Reply"
}
]
}
}
Human Readable Output
FraudWatch Incident Contacts Data
noteId subject creator content date 11081853 Client Reply Client This incident is very malicious, please monitor it 2021-02-08T15:26:19.000Z 11081828 Client Reply Client This incident is very malicious, please monitor it 2021-02-08T15:21:58.000Z
fraudwatch-incident-messages-add
Add a new related message to the incident associated with the specified incident ID.
Base Command
fraudwatch-incident-messages-add
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Add a related message to the incident with the specified incident ID. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
| message_content | Content of the related message. | Required |
Context Output
There is no context output for this command.
Command Example
!fraudwatch-incident-messages-add incident_id=JJJ-898410 message_content="This incident is very malicious, please monitor it"
Human Readable Output
Message for incident id JJJ-898410 was added successfully
fraudwatch-incident-urls-add
Adds additional URLs to the incident associated with the specified incident ID. Fails if one of the new urls already exists.
Base Command
fraudwatch-incident-urls-add
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident to add additional urls to. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
| urls | A comma-separated list of additional URLs to be added to the incident associated with the ‘incident_id’. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.IncidentUrls.success | String | Whether the URLs were added successfully. |
| FraudWatch.IncidentUrls.new_urls | String | The new URLs that were added. |
Command Example
!fraudwatch-incident-urls-add incident_id=JJJ-162968 urls=http://www.malicious1.com,http://www.malicious2.com
Context Example
{
"FraudWatch": {
"IncidentUrls": {
"new_urls": [
"http://www.malicious1.com",
"http://www.malicious2.com"
],
"success": "Add additional urls successfully"
}
}
}
Human Readable Output
FraudWatch Incident Urls
new_urls success http://www.malicious1.com,
http://www.malicious2.comAdd additional urls successfully
fraudwatch-incident-attachment-upload
Adds a new file attachment to the incident associated with the specified incident ID.
Base Command
fraudwatch-incident-attachment-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident to add a file attachment to. Incident ID is the ‘identifier’ field returned by the ‘fraudwatch-incidents-list’ command. | Required |
| entry_id | The entry id in Cortex XSOAR of the attachment to be added to the incident. | Required |
Context Output
There is no context output for this command.
Command Example
!fraudwatch-incident-attachment-upload entry_id=fmSNZSY2fSCA2WptU8rddf@d382f488-92db-400c-87ff-fdd71f3b7408 incident_id=JJJ-604206
Human Readable Output
File fraud_test.txt was uploaded successfully to incident with an incident id JJJ-604206
fraudwatch-brands-list
Gets a list of brands from FraudWatch service.
Base Command
fraudwatch-brands-list
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | Number of brands to retrieve. | Optional |
| page_size | Total number of brands in a page. Values range: 20-100. | Optional |
| page | Retrieve brands by the specified page number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FraudWatch.Brand.client | String | Brand client. |
| FraudWatch.Brand.alternate business name | String | Brand alternative business name. |
| FraudWatch.Brand.name | String | Brand name. |
| FraudWatch.Brand.active | Boolean | Wether the brand is active or not. |
| FraudWatch.Brand.services.name | String | Brand service name. |
| FraudWatch.Brand.services.action | String | Brand service action. |
Command Example
#### Context Example
```json
{
"FraudWatch": {
"Brand": [
{
"active": true,
"alternate business name": "",
"client": "Palo Alto",
"name": "Testing Brand 1",
"services": [
{
"action": "takedown",
"name": "Phishing"
},
{
"action": "monitor",
"name": "Vishing"
},
{
"action": "monitor",
"name": "Brand Abuse"
},
{
"action": "monitor",
"name": "Malware"
},
{
"action": "monitor",
"name": "Social Media Brand Abuse"
},
{
"action": "monitor",
"name": "Mobile App (Unauthorized)"
},
{
"action": "monitor",
"name": "PAC File"
},
{
"action": "monitor",
"name": "Messaging"
},
{
"action": "monitor",
"name": "DMARC Email Server"
}
]
},
{
"active": true,
"alternate business name": "",
"client": "Palo Alto",
"name": "Testing Brand 2",
"services": [
{
"action": "takedown",
"name": "Phishing"
},
{
"action": "monitor",
"name": "Vishing"
},
{
"action": "monitor",
"name": "Brand Abuse"
},
{
"action": "monitor",
"name": "Malware"
},
{
"action": "monitor",
"name": "Social Media Brand Abuse"
},
{
"action": "monitor",
"name": "Mobile App (Unauthorized)"
},
{
"action": "monitor",
"name": "PAC File"
},
{
"action": "monitor",
"name": "Messaging"
},
{
"action": "monitor",
"name": "DMARC Email Server"
}
]
}
]
}
}
Human Readable Output
FraudWatch Brands
name active client Testing Brand 1 true Palo Alto Testing Brand 2 true Palo Alto
Configuration parameters
isFetch— Fetch incidentscredentials— API Token (leave empty. Fill in the API token in the password field.)base_url— Server URL (required)brand— Brandstatus— StatusincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalfirst_fetch— First fetch timestampmax_fetch— Maximum Incidents To Fetchinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (10)
-
fraudwatch-brands-listGets a list of brands from FraudWatch service.
-
fraudwatch-incident-attachment-uploadAdds a new file attachment to the incident associated with the specified incident ID.
-
fraudwatch-incident-contact-emails-listProvides a list of the messages related to the incident associated with the specified incident ID.
-
fraudwatch-incident-forensic-getGets the forensic data of the incident associated with the specified incident ID.
-
fraudwatch-incident-get-by-identifierGets an incident from FraudWatch service by its reference ID or incident ID. Single values of 'reference_id' and 'incident_id' should be specified.
-
fraudwatch-incident-messages-addAdd a new related message to the incident associated with the specified incident ID.
-
fraudwatch-incident-reportReport an incident to FraudWatch service.
-
fraudwatch-incident-updateUpdates the incident associated with the 'incident_id' with the specified argument values.
-
fraudwatch-incident-urls-addAdds additional URLs to the incident associated with the specified incident ID. Fails if one of the new urls already exists.
-
fraudwatch-incidents-listGet a list of incidents from FraudWatch service.
import demistomock as demisto # noqa: F401 import pytz import urllib3 from CommonServerPython import * # noqa: F401 from requests import Response # disable insecure warnings urllib3.disable_warnings() """ CONSTANTS """ MINIMUM_POSITIVE_VALUE = 1 MAX_PAGE_SIZE_VALUE = 200 DEFAULT_PAGE_SIZE_VALUE = 50 MAX_PAGE_SIZE_BRANDS = 100 MINIMUM_PAGE_SIZE_BRANDS = 20 DEFAULT_URL = "https://www.phishportal.com/" FRAUD_WATCH_DATE_FORMAT = "%Y-%m-%d" INCIDENT_LIST_MARKDOWN_HEADERS = [ "identifier", "reference_id", "url", "status", "type", "brand", "client", "content_ip", "host", "host_country", "host_timezone", "created_by", "discovered_by", "current_duration", "active_duration", "date_opened", "date_closed", "additional_urls", "link", ] UTC_TIMEZONE = pytz.timezone("utc") """ CLIENT CLASS """ class Client(BaseClient): URL_ENCODED_HEADER = {"Content-Type": "application/x-www-form-urlencoded"} JSON_CONTENT_HEADER = {"Content-Type": "application/json"} def __init__(self, api_key: str, base_url: str, verify: bool, proxy: bool): self.api_key = api_key self.base_headers = {"Authorization": f"Bearer {api_key}", "Accept": "application/json"} super().__init__(base_url=base_url, verify=verify, proxy=proxy, headers=self.base_headers) def http_request( self, method: str, url_suffix: str, params: Optional[Dict] = None, data: Optional[Dict] = None, headers: Optional[Dict] = None, files: Optional[Dict] = None, ): """ Wrapper for Base Client http request. Uses error handler to catch errors returned by FraudWatch and returning an exception with more precise description for the exception Args: method (str): The HTTP method to perform ('POST', 'GET', 'PUT'). url_suffix (str): The url suffix of the API call. params (Optional[Dict]): Additional query params to be sent. data (Optional[Dict]): Additional data to be sent. headers (Optional[Dict]): Additional headers to be sent. files (Optional[Dict]): Additional files to be sent Returns: The HTTP response, or exception if exception occurred. """ return self._http_request( method=method, url_suffix=url_suffix, params=params, data=data, headers=headers, files=files, error_handler=fraud_watch_error_handler, ) def incidents_list( self, brand: Optional[str] = None, status: Optional[str] = None, page: Optional[int] = None, limit: Optional[int] = None, from_date: Optional[str] = None, to_date: Optional[str] = None, ): params = assign_params(brand=brand, status=status, page=page, limit=limit, to=to_date) # This is because 'from' is reserved word so it can't be used as key argument in assign_params. if from_date: params["from"] = from_date return self.http_request(method="GET", url_suffix="incidents", params=params) def incident_report( self, brand: str, incident_type: str, primary_url: str, reference_id: Optional[str] = None, urls: Optional[List[str]] = None, evidence: Optional[str] = None, instructions: Optional[str] = None, ): return self.http_request( method="POST", url_suffix="incidents", data=assign_params( brand=brand, type=incident_type, reference_id=reference_id, primary_url=primary_url, urls=urls, evidence=evidence, instructions=instructions, ), headers={**self.base_headers, **self.URL_ENCODED_HEADER}, ) def incident_update( self, incident_id: str, brand: Optional[str] = None, reference_id: Optional[str] = None, evidence: Optional[str] = None, instructions: Optional[str] = None, ): return self.http_request( method="PUT", url_suffix=f"incident/{incident_id}", data=assign_params(brand=brand, reference_id=reference_id, evidence=evidence, instructions=instructions), headers={**self.base_headers, **self.URL_ENCODED_HEADER}, ) def incident_list_by_id(self, incident_id: str): return self.http_request(method="GET", url_suffix=f"incident/{incident_id}") def incident_get_by_reference(self, reference_id: str): return self.http_request(method="GET", url_suffix=f"incident/reference/{reference_id}") def incident_forensic_get(self, incident_id: str): return self.http_request(method="GET", url_suffix=f"incident/{incident_id}/forensic") def incident_contact_emails_list(self, incident_id: str, page: Optional[int] = None, limit: Optional[int] = None): return self.http_request( method="GET", url_suffix=f"incident/{incident_id}/message", params=assign_params(page=page, limit=limit) ) def incident_messages_add(self, incident_id: str, message_content: Any): return self.http_request( method="POST", url_suffix=f"incident/{incident_id}/message/add", data=message_content, headers={**self.base_headers, **self.JSON_CONTENT_HEADER}, ) def incident_urls_add(self, incident_id: str, urls: Dict[str, List[str]]): return self.http_request( method="POST", url_suffix=f"incident/{incident_id}/urls/add", data=urls, headers={**self.base_headers, **self.URL_ENCODED_HEADER}, ) def attachment_upload_command(self, incident_id: str, file: Any): return self.http_request(method="POST", url_suffix=f"incident/{incident_id}/upload", files=file) def brands_list(self, page: Optional[int] = None, limit: Optional[int] = None): return self.http_request(method="GET", url_suffix="account/brands", params=assign_params(page=page, limit=limit)) """ HELPER FUNCTIONS """ def fraud_watch_error_handler(res: Response): """ FraudWatch error handler for any error occurred during the API request. This function job is to translate the known exceptions returned by FraudWatch to human readable exception to help the user understand why the request have failed. If error returned is not in the expected error format, raises the exception as is. Args: res (Any): The error response returned by FraudWatch. Returns: - raises DemistoException. """ err_msg = f"Error in API call [{res.status_code}] - {res.reason}" try: # Try to parse json error response error_entry = res.json() message = error_entry.get("message") errors = error_entry.get("errors") if res.status_code == 403: err_msg += "\nMake sure your API token is valid and up-to-date" elif not message and not errors: err_msg += f"\n{json.dumps(error_entry)}" else: if message and errors: fraud_watch_error_reason = f"{message}: {errors}" else: fraud_watch_error_reason = message if message else errors err_msg += f"\n{fraud_watch_error_reason}" raise DemistoException(err_msg, res=res) except ValueError: err_msg += f"\n{res.text}" raise DemistoException(err_msg, res=res) def get_and_validate_positive_int_argument( args: Dict, argument_name: str, lower_bound: int = MINIMUM_POSITIVE_VALUE, upper_bound: Optional[int] = None ) -> Optional[int]: """ Extracts int argument from Demisto arguments. If argument exists, validates that: - lower_bound <= argument's value. - argument's value <= maximum_bound if maximum_bound is not None. Args: args (Dict): Demisto arguments. argument_name (str): The name of the argument to extract. lower_bound (int): Lower number bound of the argument value. upper_bound (Optional[int]): Maximum number bound of the argument value, if given. Returns: - (int): If argument exists and is between 'lower_bound' and 'maximum_bound', returns argument. - (None): If argument does not exist, returns None. - (Exception): If argument exists and is lower than 'lower_bound' or higher than 'maximum_bound' (if 'maximum_bound' exists), raises DemistoException. """ argument_value = arg_to_number(args.get(argument_name), arg_name=argument_name) if not argument_value: return None if argument_value < lower_bound: raise DemistoException(f"{argument_name} should be equal or higher than {lower_bound}") if upper_bound and upper_bound < argument_value: raise DemistoException(f"{argument_name} should be equal or lower than {upper_bound}") return argument_value def get_time_parameter(arg: Optional[str]): """ parses arg into date time object with aware time zone if 'arg' exists. If no time zone is given, sets timezone to UTC. Returns the date time object created. Args: arg (str): The argument to turn into aware date time. Returns: - (None) If 'arg' is None, returns None. - (datetime): If 'arg' is exists, returns date time. """ maybe_unaware_date = arg_to_datetime(arg, is_utc=True) if not maybe_unaware_date: return None aware_time_date = maybe_unaware_date if maybe_unaware_date.tzinfo else UTC_TIMEZONE.localize(maybe_unaware_date) return aware_time_date """ COMMAND FUNCTIONS """ def get_page_and_limit_args( args: Dict, minimum_page_size: int = MINIMUM_POSITIVE_VALUE, maximum_page_size: int = MAX_PAGE_SIZE_VALUE ) -> tuple[int, int]: """ Receives demisto argument, and extract the relevant arguments for limits and paging: 'page', 'page_size', 'limit'. Follows the logic: - 'limit' argument cannot be specified with 'page' or 'page_size' argument. - 'page_size' argument is within its expected lower/upper bounds. - If 'limit' is not given, and 'page_size' is, sets 'limit' value to 'page_size' value. - If 'limit' is not given, and 'page_size' is not given, sets 'limit' value to 'DEFAULT_PAGE_SIZE_VALUE' value. Args: args (Dict): Demisto argument. minimum_page_size (int): lower_bound for page size, default is 'MINIMUM_POSITIVE_VALUE' (1). maximum_page_size (int): upper_bound for page size, default is 'MAX_PAGE_SIZE_VALUE' (200). Returns: - (int, int): 'page', 'limit' extracted, or their default values used. - (DemistoException): If arguments don't follow the expected logic mentioned. """ page = get_and_validate_positive_int_argument(args, "page") page_size = get_and_validate_positive_int_argument( args, "page_size", lower_bound=minimum_page_size, upper_bound=maximum_page_size ) limit = get_and_validate_positive_int_argument(args, "limit") if limit and (page_size or page): raise DemistoException("""Limit argument cannot be given with 'page_size' or 'page' argument.""") if not limit and page_size: limit = page_size if not limit: limit = DEFAULT_PAGE_SIZE_VALUE if not page: page = MINIMUM_POSITIVE_VALUE return page, limit def fetch_incidents_command(client: Client, params: Dict, last_run: Dict): """ Fetches new incidents from FraudWatch. Because of FraudWatch limitation, such as 'from_date' being accurate only by day, and incidents returned are not ordered by their date opened. 1) First_fetch time is limited to 1 day. 2) Every fetch_incidents call, we will fetch all the pages from the day of the time stamp saved in last run. 3) Filter all incidents that their date opened was earlier than last saved time stamp. 4) Sort the remained incidents by their date opened. 5) Return the first 'max_fetch' incidents in the sorted list. Limiting first_fetch is needed because we must traverse all incidents that might be relevant, therefore the list cannot be very large. Uses Demisto last run parameters in the following way: - 'last_fetch_time' - The latest time fetching was done. Keeps track of incidents to be fetched by their date. Args: client (Client): FraudWatch client to perform API call to fetch incidents. params (Dict): Demisto params. last_run (Dict): Demisto last run. Returns: (List[Dict], Dict): Incidents and new run parameters. """ brand = params.get("brand") status = params.get("status") limit = arg_to_number(params.get("max_fetch", DEFAULT_PAGE_SIZE_VALUE)) yesterday = get_time_parameter("1 day") first_fetch_time_string = params.get("first_fetch", "1 days").strip() minimum_date_opened_str = last_run.get("last_fetch_time", first_fetch_time_string) # Between yesterday date and last fetch date we choose the latest minimum_date_opened = max(get_time_parameter(minimum_date_opened_str), yesterday) from_date = minimum_date_opened.strftime(FRAUD_WATCH_DATE_FORMAT) incidents = [] # Need to fetch all incidents because FraudWatch does not sort incidents based on dates. current_page = 1 while True: raw_response = client.incidents_list( brand=brand, status=status, page=current_page, limit=MAX_PAGE_SIZE_VALUE, from_date=from_date ) if raw_response.get("error"): raise DemistoException(f"""Error occurred while pulling incidents from FraudWatch: {raw_response.get('error')}""") temp_incidents = raw_response.get("incidents", []) if not temp_incidents: break incidents += temp_incidents current_page += 1 incidents = [incident for incident in incidents if get_time_parameter(incident.get("date_opened")) > minimum_date_opened] incidents.sort(key=lambda incident: incident.get("date_opened")) incidents = incidents[:limit] incidents_obj_list: List[Dict[str, Any]] = [ { "name": f"""{incident.get('brand')}:{incident.get('identifier')}""", "type": "FraudWatch Incident", "occurred": incident.get("date_opened"), "rawJSON": json.dumps(incident), } for incident in incidents ] next_run = {"last_fetch_time": incidents[-1].get("date_opened") if incidents else minimum_date_opened_str} return incidents_obj_list, next_run def test_module(client: Client, params: Dict) -> str: """ Tests API connectivity and authentication. Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Raises exceptions if something goes wrong. Args: client (Client): FraudWatch client to perform the API call. params (Dict): Demisto params. Returns: (str): 'ok' if test passed, anything else will fail the test. """ try: fetch_incidents_command(client, params, {}) return "ok" except DemistoException as e: if "Forbidden" in str(e) or "Authorization" in str(e): message = "Authorization Error: make sure API Key is correctly set" e = DemistoException(message) raise e def fraud_watch_incidents_list_command(client: Client, args: Dict) -> CommandResults: """ Gets a list of incidents from FraudWatch service with the possible filters: - Brand: Retrieve incidents which corresponds to the given brand. throws Exception if brand does not exist. - Status: Retrieve incidents which corresponds to the given status. Unknown status will return empty incident list. - Limit: Total number of Incidents in a page. The default limit is 20 and the maximum number is 200. - Page: Retrieve incidents by the given page number. - From Date: Retrieve alerts that their date opened is higher or equal to 'from' value. Supports ISO and time range (<number> <time unit>, e.g., 12 hours, 7 days) formats. If 'to' argument is not given, default value for 'to' is current day. - To Date: Retrieve alerts that their date opened is lower or equal to 'to' value. Supports ISO and time range (<number> <time unit>, e.g., 12 hours, 7 days) formats. If 'from' argument is not given, default value for 'from' is 12 months before 'to'. Known errors that causes error to be returned by FraudWatch service: - Unknown brand. - Invalid 'to_date' or 'from_date' values. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ brand = args.get("brand") status = args.get("status") page, limit = get_page_and_limit_args(args) if from_date := get_time_parameter(args.get("from")): from_date = from_date.strftime(FRAUD_WATCH_DATE_FORMAT) if to_date := get_time_parameter(args.get("to")): to_date = to_date.strftime(FRAUD_WATCH_DATE_FORMAT) if from_date and not to_date: to_date = get_time_parameter("tomorrow").strftime(FRAUD_WATCH_DATE_FORMAT) raw_responses = [] outputs = [] count = limit while limit > 0: raw_response = client.incidents_list(brand, status, page, MAX_PAGE_SIZE_VALUE, from_date, to_date) incidents = raw_response.get("incidents", []) if not incidents: break if raw_response.get("error"): raise DemistoException(f"""Error occurred during the call to FraudWatch: {raw_response.get('error')}""") raw_responses.append(raw_response) outputs.extend(incidents) limit -= MAX_PAGE_SIZE_VALUE page += 1 final_raw_responses = raw_responses[:count] final_outputs = outputs[:count] return CommandResults( outputs_prefix="FraudWatch.Incident", outputs=final_outputs, outputs_key_field="identifier", raw_response=final_raw_responses, readable_output=tableToMarkdown("FraudWatch Incidents", final_outputs, INCIDENT_LIST_MARKDOWN_HEADERS, removeNull=True), ) def fraud_watch_incident_report_command(client: Client, args: Dict) -> CommandResults: """ Report an incident to FraudWatch service: - Brand(Required): The brand associated to the reported incident. - Incident Type(Required): The type of the incident to be associated to the reported incident. - possible values: ['phishing' => Phishing, 'vishing' => Vishing, 'brand_abuse' => Brand Abuse, 'malware' => Malware, 'social_media_brand_abuse' => Social Media, 'mobile_app_unauthorized' => Mobile App, 'pac_file' => PAC File, 'pharming' => Pharming, 'messaging' => Messaging, 'dmarc_email_server' => DMARC] left side is the parameter to be sent, right side is the way it will be shown in FraudWatch User Interface. - Reference ID: Reference ID to be associated to the reported incident. Should be unique. Reference ID can be used later to retrieve specific incident by its reference id. - Primary URL(Required): Primary URL of the reported incident. - Urls: Additional urls in addition to primary URL to be associated to the reported incident. - Evidence: Evidence to be added (such as logs, etc...) to the reported incident. - Instructions: Additional instructions to be added for FraudWatch Security Team. Known errors that causes error to be returned by FraudWatch service: - Not given or unknown brand. - Not given or unknown incident type. - Not given primary url. - No data given. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ brand: str = args.get("brand") # type: ignore incident_type: str = args.get("type") # type: ignore primary_url: str = args.get("primary_url") # type: ignore reference_id = args.get("reference_id") urls = args.get("urls") evidence = args.get("evidence") instructions = args.get("instructions") raw_response = client.incident_report(brand, incident_type, primary_url, reference_id, urls, evidence, instructions) return CommandResults( outputs_prefix="FraudWatch.Incident", outputs=raw_response, outputs_key_field="identifier", raw_response=raw_response, readable_output=tableToMarkdown("Created FraudWatch Incident", raw_response, removeNull=True), ) def fraud_watch_incident_update_command(client: Client, args: Dict) -> CommandResults: """ Updates the incident ID corresponding to the given incident_id with given arguments values: - Incident ID(Required): The ID of the incident to be updated. - Brand: Updates this to be the brand associated to the incident which corresponds to given incident id. - Reference ID: Reference ID to be associated to the incident which corresponds to given incident id. Should be unique. Reference ID can be used later to retrieve specific incident by its reference id. - Evidence: Evidence to be added (such as logs, etc...) to the incident. - Instructions: Add Additional instructions to be added for FraudWatch Security Team to the incident which corresponds to given incident id. At least one of 'Brand', 'Reference ID', 'Evidence', 'Instructions' must be given. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. - Not given or unknown brand. - No data given. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore brand = args.get("brand") reference_id = args.get("reference_id") evidence = args.get("evidence") instructions = args.get("instructions") if all(argument is None for argument in [brand, reference_id, evidence, instructions]): return CommandResults(readable_output=f"### Could not update incident: {incident_id} - No data was given.") raw_response = client.incident_update(incident_id, brand, reference_id, evidence, instructions) return CommandResults( raw_response=raw_response, readable_output=f"### Incident with ID {incident_id} was updated successfully" ) def fraud_watch_incident_get_by_identifier_command(client: Client, args: Dict) -> CommandResults: """ Gets an incident from FraudWatch service by its reference ID or incident ID: - Incident ID: The ID of the incident to be retrieved. - Reference ID: Reference id of the incident to be retrieved. In case more than one incident has the corresponding reference id, FraudWatch service returns the incident with the latest 'date_opened' field. Exactly one of 'Incident ID', 'Reference ID' should be given, else DemistoException will be raised. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. - Unknown reference_id id. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore reference_id: str = args.get("reference_id") # type: ignore if (incident_id and reference_id) or (not incident_id and not reference_id): raise DemistoException("Exactly one of reference id or incident id must be given.") if incident_id: raw_response = client.incident_list_by_id(incident_id) else: raw_response = client.incident_get_by_reference(reference_id) return CommandResults( outputs_prefix="FraudWatch.Incident", outputs=raw_response, outputs_key_field="identifier", raw_response=raw_response, readable_output=tableToMarkdown("FraudWatch Incident", raw_response, removeNull=True), ) def fraud_watch_incident_forensic_get_command(client: Client, args: Dict) -> CommandResults: """ Gets forensic data of an incident which corresponds to the given incident ID: - Incident ID (Required): The ID of the incident to have its forensic data retrieved. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore raw_response = client.incident_forensic_get(incident_id) outputs = remove_empty_elements(raw_response) if outputs: outputs["identifier"] = incident_id return CommandResults( outputs_prefix="FraudWatch.IncidentForensicData", outputs=outputs, outputs_key_field="identifier", raw_response=raw_response, readable_output=tableToMarkdown("FraudWatch Incident Forensic Data", outputs, removeNull=True), ) def fraud_watch_incident_contact_emails_list_command(client: Client, args: Dict) -> CommandResults: """ Provides contact emails for the incident which corresponds to the given incident ID: - Incident ID (Required): The ID of the incident to have its email contacts data retrieved. - Limit: Total number of contact emails in a page. The default limit is 20 and the maximum number is 200. - Page: Retrieve contact emails by the given page number. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. - Page index out of bounds. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore page, limit = get_page_and_limit_args(args) raw_responses = [] count = limit try: while limit > 0: raw_response = client.incident_contact_emails_list(incident_id, page, MAX_PAGE_SIZE_VALUE) if not raw_response: break raw_responses.extend(raw_response) limit -= MAX_PAGE_SIZE_VALUE page += 1 except DemistoException as e: if "Contact email not found" in str(e): page_error_msg = f"""Make sure page index: {page} is within bounds.""" if page else "" unknown_incident_msg = f"""Make sure incident id: {incident_id} is correct.""" raise DemistoException(f"Error occurred. {page_error_msg} {unknown_incident_msg}") raise e outputs = [dict(output, identifier=incident_id) for output in raw_responses] final_raw_responses = raw_responses[:count] final_outputs = outputs[:count] return CommandResults( outputs_prefix="FraudWatch.IncidentContacts", outputs=final_outputs, outputs_key_field="noteId", raw_response=final_raw_responses, readable_output=tableToMarkdown( "FraudWatch Incident Contacts Data", final_outputs, ["noteId", "incident_id", "subject", "creator", "content", "date"], removeNull=True, ), ) def fraud_watch_incident_messages_add_command(client: Client, args: Dict): """ Add a new message to be associated to the incident which corresponds to the given incident ID: - Incident ID (Required): The ID of the incident to add a message to its email contacts. - Message Content (Required): Content of the message. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore message_content = args.get("message_content") raw_response = client.incident_messages_add(incident_id, message_content) human_readable = f"### Message for incident id {incident_id} was added successfully." return CommandResults(raw_response=raw_response, readable_output=human_readable) def fraud_watch_incident_urls_add_command(client: Client, args: Dict) -> CommandResults: """ Adds additional urls to the incident which corresponds to the given incident ID: - Incident ID (Required): The ID of the incident to add additional urls to. - Urls: Additional urls to be added to the incident that matches 'Incident ID'. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore urls: Dict[str, List[str]] = {"urls[]": argToList(args.get("urls"))} raw_response = client.incident_urls_add(incident_id, urls) return CommandResults( outputs_prefix="FraudWatch.IncidentUrls", outputs=raw_response, raw_response=raw_response, readable_output=tableToMarkdown("FraudWatch Incident Urls", raw_response, removeNull=True), ) def fraud_watch_attachment_upload_command(client: Client, args: Dict): """ Adds a new file attachment to the incident which corresponds to the given incident ID. - Incident ID (Required): The ID of the incident to add additional urls to. - File Attachment: Entry id of the attachment to be added to the incident which corresponds to Incident ID. Known errors that causes error to be returned by FraudWatch service: - Unknown incident id. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ incident_id: str = args.get("incident_id") # type: ignore entry_id = args.get("entry_id") try: # entry id of uploaded file to war room file_info = demisto.getFilePath(entry_id) file = open(file_info["path"], "rb") except Exception: raise DemistoException(f"Entry {entry_id} does not contain a file.") files = [("incident_attachment", (file_info["name"], file))] raw_response = client.attachment_upload_command(incident_id, files) return CommandResults( raw_response=raw_response, # change to name and not entry ID readable_output=f"""### File {file_info['name']} was uploaded successfully to incident: {incident_id}""", ) def fraud_watch_brands_list_command(client: Client, args: Dict) -> CommandResults: """ Gets a list of brands from FraudWatch service: - Limit: Total number of brands in a page. The default limit is 20, minimum number is also 20 and the maximum number is 100. - Page: Retrieve brands by the given page number. Args: client (Client): FraudWatch client to perform the API calls. args (Dict): Demisto arguments. Returns: CommandResults. """ page, limit = get_page_and_limit_args( args, minimum_page_size=MINIMUM_PAGE_SIZE_BRANDS, maximum_page_size=MAX_PAGE_SIZE_BRANDS ) raw_responses = [] outputs = [] count = limit while limit > 0: raw_response = client.brands_list(page, MAX_PAGE_SIZE_BRANDS) brands_list = raw_response.get("brands", []) if not brands_list: break raw_responses.append(raw_response) outputs.extend(brands_list) limit -= MAX_PAGE_SIZE_BRANDS page += 1 final_raw_responses = raw_responses[:count] final_outputs = outputs[:count] return CommandResults( outputs_prefix="FraudWatch.Brand", outputs=final_outputs, outputs_key_field="name", raw_response=final_raw_responses, readable_output=tableToMarkdown("FraudWatch Brands", final_outputs, ["name", "active", "client"], removeNull=True), ) """ MAIN FUNCTION """ def main() -> None: """ Main function, parses params and runs command functions. """ command = demisto.command() params = demisto.params() args = demisto.args() verify_certificate = not params.get("insecure", False) proxy = params.get("proxy", False) credentials = params.get("credentials") api_key = credentials.get("password") if not api_key: raise DemistoException("API token was not given. Please insert your API token. See documentation for further info") base_url = urljoin(params.get("base_url", DEFAULT_URL), "v1/") demisto.debug(f"Command being called is {command}") try: client = Client(api_key=api_key, base_url=base_url, verify=verify_certificate, proxy=proxy) if command == "test-module": return_results(test_module(client, params)) elif command == "fetch-incidents": incidents, next_run = fetch_incidents_command(client, params, demisto.getLastRun()) demisto.setLastRun(next_run) demisto.incidents(incidents) elif command == "fraudwatch-incidents-list": return_results(fraud_watch_incidents_list_command(client, args)) elif command == "fraudwatch-incident-report": return_results(fraud_watch_incident_report_command(client, args)) elif command == "fraudwatch-incident-update": return_results(fraud_watch_incident_update_command(client, args)) elif command == "fraudwatch-incident-get-by-identifier": return_results(fraud_watch_incident_get_by_identifier_command(client, args)) elif command == "fraudwatch-incident-forensic-get": return_results(fraud_watch_incident_forensic_get_command(client, args)) elif command == "fraudwatch-incident-contact-emails-list": return_results(fraud_watch_incident_contact_emails_list_command(client, args)) elif command == "fraudwatch-incident-messages-add": return_results(fraud_watch_incident_messages_add_command(client, args)) elif command == "fraudwatch-incident-urls-add": return_results(fraud_watch_incident_urls_add_command(client, args)) elif command == "fraudwatch-incident-attachment-upload": return_results(fraud_watch_attachment_upload_command(client, args)) elif command == "fraudwatch-brands-list": return_results(fraud_watch_brands_list_command(client, args)) else: raise NotImplementedError(f"Command {command} is not implemented.") # Log exceptions and return errors except Exception as e: return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()