Cofense Vision
The Cofense Vision integration provides commands to initiate advanced search jobs to hunt suspicious emails matching IOCs. It also contains commands to quarantine emails, download messages and their attachments, and aids to manage IOCs in the local repository to keep up with upcoming emerging threats.
Data Enrichment & Threat Intelligence · Cofense Vision
Details
| ID | Cofense Vision |
|---|---|
| Provider | Cofense |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.2.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
The Cofense Vision integration provides commands to initiate advanced search jobs to hunt suspicious emails matching IOCs. It also contains commands to quarantine emails, download messages and their attachments, and aids to manage IOCs in the local repository to keep up with upcoming emerging threats.
This integration was integrated and tested with version 4 of Cofense Vision and version 1 of Cofense IOC Repository.
Configure Cofense Vision in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | Server URL to connect to Cofense Vision. | True |
| Client ID | True | |
| Client Secret | True | |
| Threat levels to be marked as Good | Mapping of Cofense Vision threat level to XSOAR DbotScore. For ‘Good’, DbotScore will be 1 and default threat level value is ‘low’. Comma separated values are supported. |
False |
| Threat levels to be marked as Suspicious | Mapping of Cofense Vision threat level to XSOAR DbotScore. For ‘Suspicious’, DbotScore will be 2 and default threat level values are ‘suspicious’, ‘moderate’, ‘substantial’. Comma separated values are supported. |
False |
| Threat levels to be marked as Bad | Mapping of Cofense Vision threat level to XSOAR DbotScore. For ‘Bad’, DbotScore will be 3 and default threat level values are ‘malicious’, ‘severe’, ‘critical’, ‘high’. Comma separated values are supported. |
False |
| Trust any certificate (not secure) | Indicates whether to allow connections without verifying SSL certificate’s validity. | False |
| Use system proxy settings | Indicates whether to use XSOAR’s system proxy settings to connect to the API. | 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.
cofense-message-token-get
Retrieves a one-time token that can be used to get an email’s content.
Base Command
cofense-message-token-get
Input
| Argument Name | Description | Required |
|---|---|---|
| internet_message_id | Unique identifier of the email, enclosed in angle brackets. Example: <AC6CAE11-779E-4044-BB25-110171AB0301@example.com> Note: Users can get the ID by executing the “cofense-message-search-results-get” command. |
Required |
| recipient_address | Email address of the recipient of the email. Note: The email address can be a carbon copy (Cc) or blind carbon copy (Bcc) recipient but cannot be a shared mailbox or a distribution list. Note: Users can get the recipient address by executing the “cofense-message-search-results-get” command. |
Required |
| password | Password to protect the zip file containing the email. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Message.token | String | One-time token to access an email content. |
| Cofense.Message.internetMessageId | String | ID of an email assigned by the message transfer agent. |
| Cofense.Message.recipients.address | String | Email address of the recipient. |
Command example
!cofense-message-token-get internet_message_id="<1216208547.160.1658930322668@6d14a4fa9032>" recipient_address="abc@example.com"
Context Example
{
"Cofense": {
"Message": {
"internetMessageId": "<1216208547.160.1658930322668@6d14a4fa9032>",
"recipient": {
"address": "abc@example.com"
},
"token": "de7475a4-3802-46c1-8e4c-2665912445c0"
}
}
}
Human Readable Output
One-time token
Internet Message ID Recipient’s Address Token <1216208547.160.1658930322668@6d14a4fa9032> abc@example.com de7475a4-3802-46c1-8e4c-2665912445c0
cofense-message-metadata-get
Retrieves the full content of a message that matches the specified Internet message ID and recipient email address of an email.
Base Command
cofense-message-metadata-get
Input
| Argument Name | Description | Required |
|---|---|---|
| internet_message_id | Unique identifier of the email, enclosed in angle brackets. Example: <AC6CAE11-779E-4044-BB25-110171AB0301@example.com> Note: Users can get the internet message ID by executing the “cofense-message-search-results-get” command. |
Required |
| recipient_address | Email address of the recipient of an email. The email address can be a carbon copy (Cc) or blind carbon copy (Bcc) recipient but cannot be a shared mailbox or a distribution list. Note: Users can get the recipient address by executing the “cofense-message-search-results-get” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Message.id | Number | ID of the message in cofense vision. |
| Cofense.Message.storageUri | String | Storage URI of an email. |
| Cofense.Message.subject | String | Subject of the email. |
| Cofense.Message.receivedOn | Date | Date and time an email was received by the recipient. |
| Cofense.Message.sentOn | Date | Date and time an email was sent to the recipient. |
| Cofense.Message.deliveredOn | Date | Date and time an email was delivered to the recipient. |
| Cofense.Message.processedOn | Date | Date and time cofense vision ingested the email. |
| Cofense.Message.textBody | String | Body of an email in text format. |
| Cofense.Message.htmlBody | String | Body of an email in HTML format. |
| Cofense.Message.md5 | String | MD5 hash of the message. |
| Cofense.Message.sha1 | String | SHA1 hash of the message. |
| Cofense.Message.sha256 | String | SHA256 hash of the message. |
| Cofense.Message.internetMessageId | String | ID of an email assigned by the message transfer agent. |
| Cofense.Message.from.id | Number | ID of the sender. |
| Cofense.Message.from.personal | String | Personal email of the sender. |
| Cofense.Message.from.address | String | An email address of the sender. |
| Cofense.Message.headers.name | String | The name of the key in the header. |
| Cofense.Message.headers.value | String | The value of the key in the header. |
| Cofense.Message.recipients.id | Number | ID of the recipient. |
| Cofense.Message.recipients.personal | String | Personal email of the recipient. |
| Cofense.Message.recipients.address | String | Email address of the recipient. |
| Cofense.Message.recipients.recipientType | String | Type of the recipient. |
| Cofense.Message.attachments.size | Number | The size of the attachment file. |
| Cofense.Message.attachments.filename | String | The name of the attachment file. |
| Cofense.Message.attachments.contentType | String | The content type present in the header. |
| Cofense.Message.attachments.detectedContentType | String | The detected content type of the attachment. |
| Cofense.Message.attachments.md5 | String | The MD5 hash of the attachment. |
| Cofense.Message.attachments.sha256 | String | The SHA256 hash of the attachment. |
| Cofense.Message.attachments.id | Number | The ID of the attachment. |
| Cofense.Message.matchingIOCs | Unknown | MD5 hash of one or more matching IOCs. |
| Cofense.Message.matchingSources | Unknown | One or more matching IOC sources. |
Command example
!cofense-message-metadata-get internet_message_id="<1216208547.160.1658930322668@6d14a4fa9032>" recipient_address="abc@example.com"
Context Example
{
"Cofense": {
"Message": {
"attachments": [
{
"contentType": "text/plain",
"detectedContentType": "text/plain",
"filename": "fileNum-Thread[mailer-011,5,main]-text-file-163.txt",
"id": 1673289,
"md5": "3d0e1d68f12afee22ae3e79e01027c7a",
"sha256": "ca68f5eecd5822783911ed392fbff3c171d3a1854c0f992364d038ee447f8ac3",
"size": 59173
},
{
"contentType": "application/zip",
"detectedContentType": "application/zip",
"filename": "fileNum-Thread[mailer-011,5,main]-text-file-146.txt.zip",
"id": 1673290,
"md5": "5c602ca45faac3bb128a5ecbf977f9f1",
"sha256": "6018b7cc402e6368d4542c0f6c129a99e35c80ae9001ec338e7621df2f8ac51f",
"size": 14563
},
{
"detectedContentType": "text/plain",
"filename": "text-file-146.txt",
"id": 1673291,
"md5": "c5aa88f949574a0a5e75a795dc507da7",
"sha256": "d3a070977ae0ae561bae2215526c187d5c46c54dd8899eefb8fe21ed0e6c1303",
"size": 27842
}
],
"from": [
{
"address": "abc@example.com",
"id": 760623,
"personal": "abc"
}
],
"headers": [
{
"name": "From",
"value": "abc@example.com"
},
{
"name": "To",
"value": "pqr@example.com"
},
{
"name": "CC",
"value": "abc@example.com"
},
{
"name": "Subject",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Topic",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Index",
"value": "AQHYocD7Ut113z4F00uSjzqlEM2clw=="
},
{
"name": "Date",
"value": "Wed, 27 Jul 2022 13:58:43 +0000"
},
{
"name": "Message-ID",
"value": "<1216208547.160.1658930322668@6d14a4fa9032>"
}
],
"id": 760623,
"internetMessageId": "<1216208547.160.1658930322668@6d14a4fa9032>",
"md5": "a486b023cd82f45f7b099a41dc3776a6",
"processedOn": "2022-07-27T13:58:46.271+00:00",
"receivedOn": "2022-07-27T13:58:44.000+00:00",
"recipients": [
{
"address": "abc@example.com",
"id": 7606409,
"personal": "abc",
"recipientType": "cc"
},
{
"address": "pqr@example.com",
"id": 7606410,
"personal": "pqr",
"recipientType": "to"
}
],
"sentOn": "2022-07-27T13:58:43.000+00:00",
"sha1": "0b744bed73106d5d613d83c71b9d9884f48690f4",
"sha256": "2d7bad3fe37c9e4089e6231784f51354ef2fd9689fe7fae6d46cb70d279da8e0",
"subject": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
}
}
}
Human Readable Output
Message Metadata
ID Subject Received On Sent On Processed On Sender Recipients MD5 SHA1 SHA256 Internet Message ID 760623 craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646 27/07/2022, 01:58 PM UTC 27/07/2022, 01:58 PM UTC 27/07/2022, 01:58 PM UTC abc@example.com abc@example.com
pqr@example.coma486b023cd82f45f7b099a41dc3776a6 0b744bed73106d5d613d83c71b9d9884f48690f4 2d7bad3fe37c9e4089e6231784f51354ef2fd9689fe7fae6d46cb70d279da8e0 <1216208547.160.1658930322668@6d14a4fa9032>
cofense-message-get
Fetches full content of an email and returns it as a zip file using a token.
Base Command
cofense-message-get
Input
| Argument Name | Description | Required |
|---|---|---|
| token | A one-time token to access the content of an email in a zip file. Note: Users can get the token by executing the “cofense-message-token-get” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | Number | The size of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Extension | String | The file extension. |
Command example
!cofense-message-get token="fbbeff70-2c17-4d67-a741-3d8a7e394005"
Context Example
{
"File": {
"EntryID": "603@cc18bdc4-7c64-494c-879c-23c3aee60818",
"Info": "text/plain",
"MD5": "97ee1d575640245abadbba15c0672eec",
"Name": "13311",
"SHA1": "13395876300d0a575812878446e15b9bbddda0b2",
"SHA256": "19d9c63bf4067a897950cfb72c14e8d05d8dcab0655979c6b60b925fb91e329f",
"SHA512": "31df48f235cc82247c6edc05850f910d6a057717d5d5f6ce84a4bc6c6fc3cc1f6ebae706ac592ace106b0559753928a838a1aee7018bec5b4316b90d95f55bcf",
"SSDeep": "24:nDBTBpJG4hbUWBFcXekJPkJ1WkJM8PWkJKckJvV/WskJvV28BesR1zvX0:nDNrHb1BWXekJPkJ1WkJfPWkJDkJvV/n",
"Size": 988,
"Type": "ASCII text, with CRLF line terminators"
}
}
Human Readable Output
EntryID Info MD5 Name SHA1 SHA256 SHA512 SSDeep Size Type 603@cc18bdc4-7c64-494c-879c-23c3aee60818 text/plain 97ee1d575640245abadbba15c0672eec 13311 13395876300d0a575812878446e15b9bbddda0b2 19d9c63bf4067a897950cfb72c14e8d05d8dcab0655979c6b60b925fb91e329f 31df48f235cc82247c6edc05850f910d6a057717d5d5f6ce84a4bc6c6fc3cc1f6ebae706ac592ace106b0559753928a838a1aee7018bec5b4316b90d95f55bcf 24:nDBTBpJG4hbUWBFcXekJPkJ1WkJM8PWkJKckJvV/WskJvV28BesR1zvX0:nDNrHb1BWXekJPkJ1WkJfPWkJDkJvV/n 988 ASCII text, with CRLF line terminators
cofense-message-attachment-get
Fetches the full content of an email and returns a zip file.
Base Command
cofense-message-attachment-get
Input
| Argument Name | Description | Required |
|---|---|---|
| md5 | The hex-encoded string that represents an attachment’s MD5 hash. Note: The md5 hash can be retrieved by using the command “cofense-message-search-results-get”. |
Required |
| sha256 | The hex-encoded string that represents an attachment’s SHA256 hash. Note: The sha256 hash can be retrieved by using the command “cofense-message-search-results-get”. |
Optional |
| file_name | Provide a name to the file with the extension that needs to be downloaded. Note: The file name can be retrieved by using the command “cofense-message-search-results-get”. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | Number | The size of the file in bytes. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Extension | String | The file extension. |
Command example
!cofense-message-attachment-get md5="3d0e1d68f12afee22ae3e79e01027c7a" file_name="attachment.txt"
Context Example
{
"File": {
"EntryID": "603@cc18bdc4-7c64-494c-879c-23c3aee60818",
"Info": "text/plain",
"MD5": "97ee1d575640245abadbba15c0672eec",
"Name": "13311",
"SHA1": "13395876300d0a575812878446e15b9bbddda0b2",
"SHA256": "19d9c63bf4067a897950cfb72c14e8d05d8dcab0655979c6b60b925fb91e329f",
"SHA512": "31df48f235cc82247c6edc05850f910d6a057717d5d5f6ce84a4bc6c6fc3cc1f6ebae706ac592ace106b0559753928a838a1aee7018bec5b4316b90d95f55bcf",
"SSDeep": "24:nDBTBpJG4hbUWBFcXekJPkJ1WkJM8PWkJKckJvV/WskJvV28BesR1zvX0:nDNrHb1BWXekJPkJ1WkJfPWkJDkJvV/n",
"Size": 988,
"Type": "ASCII text, with CRLF line terminators"
}
}
Human Readable Output
EntryID Info MD5 Name SHA1 SHA256 SHA512 SSDeep Size Type 603@cc18bdc4-7c64-494c-879c-23c3aee60818 text/plain 97ee1d575640245abadbba15c0672eec 13311 13395876300d0a575812878446e15b9bbddda0b2 19d9c63bf4067a897950cfb72c14e8d05d8dcab0655979c6b60b925fb91e329f 31df48f235cc82247c6edc05850f910d6a057717d5d5f6ce84a4bc6c6fc3cc1f6ebae706ac592ace106b0559753928a838a1aee7018bec5b4316b90d95f55bcf 24:nDBTBpJG4hbUWBFcXekJPkJ1WkJM8PWkJKckJvV/WskJvV28BesR1zvX0:nDNrHb1BWXekJPkJ1WkJfPWkJDkJvV/n 988 ASCII text, with CRLF line terminators
cofense-quarantine-jobs-list
Filters and returns a paginated list of matching quarantine jobs.
Base Command
cofense-quarantine-jobs-list
Input
| Argument Name | Description | Required |
|---|---|---|
| exclude_quarantine_emails | Whether to remove (true) or not remove (false) quarantined emails from the response. Possible values are: True, False. Default is False. | Optional |
| page | Start page of the results. The value must be a positive integer or 0. Default is 0. | Optional |
| size | The number of results to retrieve per page. The value must be a positive integer up to 2000. Default is 50. | Optional |
| sort | The name-value pair defining the order of the response. Comma separated values are supported. Supported format: propertyName1:sortOrder1,propertyName2:sortOrder2 Supported values for propertyName are: id, createdBy, createdDate, modifiedBy, modifiedDate, stopRequested. Supported values for sortOrder are: asc, desc. Default is id:asc. |
Optional |
| auto_quarantine | Whether to include auto quarantine jobs (true) or not include auto quarantine jobs (false). Possible values are: True, False. | Optional |
| include_status | Filters quarantine jobs by including emails with the specified status. Supports comma-separated values. Supported values are: NEW, PENDING_APPROVAL, QUEUED, RUNNING, COMPLETED, FAILED. Where, NEW: Job was created but is not yet queued. PENDING_APPROVAL: Job was created from an auto quarantine action and is waiting for approval to run. QUEUED: Job is queued but has not yet run. RUNNING: Job is currently running. COMPLETED: Job run finished and emails were quarantined or restored. FAILED: Job run finished but some emails to be quarantined or restored are in an error state. Cofense Vision retries failed jobs until the retry limit is reached. |
Optional |
| exclude_status | Filters quarantine jobs by excluding emails with the specified status. Supports comma-separated values. Supported values are: NEW, PENDING_APPROVAL, QUEUED, RUNNING, COMPLETED, FAILED. Where, NEW: Job was created but is not yet queued. PENDING_APPROVAL: Job was created from an auto quarantine action and is waiting for approval to run. QUEUED: Job is queued but has not yet run. RUNNING: Job is currently running. COMPLETED: Job run finished and emails were quarantined or restored. FAILED: Job run finished but some emails to be quarantined or restored are in an error state. Cofense Vision retries failed jobs until the retry limit is reached. |
Optional |
| iocs | Unique MD5 hash identifier of one or more IOCs. Comma separated values are supported. Example: 07fa1e91f99050521a87edc784e83fd5,07123459050525189160784e83fd5. |
Optional |
| modified_date_after | Emails modified after this date and time. The date and time must be in UTC. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ For example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Optional |
| sources | One or more configured IOC sources. Comma separated values are supported. Example: Intelligence, Triage-1. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.createdBy | String | Client that created the quarantine job. |
| Cofense.QuarantineJob.createdDate | Date | Date and time the quarantine job was created. The timestamp is in UTC. |
| Cofense.QuarantineJob.modifiedBy | String | Client that last updated the quarantine job. |
| Cofense.QuarantineJob.modifiedDate | Date | Date and time the quarantine job was last modified. The timestamp is in UTC. |
| Cofense.QuarantineJob.stopRequested | Boolean | Whether a request was issued (true) or was not issued (false) to stop the quarantine job. |
| Cofense.QuarantineJob.emailCount | Number | Number of emails quarantined. |
| Cofense.QuarantineJob.quarantineEmails.createdDate | Date | Date the quarantine job was created. |
| Cofense.QuarantineJob.quarantineEmails.errorMessage | String | Error message. |
| Cofense.QuarantineJob.quarantineEmails.ewsMessageId | String | ID of the email in EWS. |
| Cofense.QuarantineJob.quarantineEmails.id | Number | ID in cofense vision. |
| Cofense.QuarantineJob.quarantineEmails.internetMessageID | String | ID of the email assigned by the message transfer agent. |
| Cofense.QuarantineJob.quarantineEmails.originalFolderId | String | ID of the EWS folder where the email was located before it was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.quarantinedDate | Date | The date when an email was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.recipientAddress | String | Email address of the account containing the emails to be quarantined. |
| Cofense.QuarantineJob.quarantineEmails.status | String | Status of the email. |
| Cofense.QuarantineJob.quarantineJobRuns.completedDate | Date | Date the quarantine job completed. |
| Cofense.QuarantineJob.quarantineJobRuns.error | Number | Total number of errors in the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.id | Number | ID of the quarantine job in Cofense Vision. |
| Cofense.QuarantineJob.quarantineJobRuns.jobRunType | String | Type of Job depending on the operation being performed against the emails. |
| Cofense.QuarantineJob.quarantineJobRuns.startedDate | Date | Date the quarantine job started. |
| Cofense.QuarantineJob.quarantineJobRuns.status | String | Status of the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.total | Number | Total number of emails in the quarantine job. |
| Cofense.QuarantineJob.autoQuarantine | Boolean | Whether the quarantine job was part of an auto quarantine action (true) or was not part of an auto quarantine action (false). |
| Cofense.QuarantineJob.matchingIOCs | Unknown | MD5 hash of one or more matching IOCs. |
| Cofense.QuarantineJob.matchingSources | Unknown | One or more IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.QuarantineJob.matchingIocInfo.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.source | Unknown | Data that the IOC source reads and writes. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expires_at | Date | Date and time in UTC, after which this IOC expires. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.first_quarantined_at | Date | Date and time Cofense Vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.last_quarantined_at | Date | Date and time Cofense Vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.QuarantineJob.searchId | Number | ID that Cofense Vision assigned to the search, if any. |
Command example
!cofense-quarantine-jobs-list size=2
Context Example
{
"Cofense": {
"QuarantineJob": [
{
"autoQuarantine": false,
"createdBy": "testuser",
"createdDate": "2022-07-07T07:36:09.097744",
"emailCount": 1,
"id": 8,
"modifiedBy": "system",
"modifiedDate": "2022-07-20T05:37:41.585128",
"quarantineEmails": [
{
"createdDate": "2022-07-07T07:29:23.535483",
"errorMessage": "No primary addresses were found for 3/xxxxx@muczynskicofense.onmicrosoft.com",
"id": 3,
"internetMessageId": "<1341250439.1013918.1657064008682@af226d4cfbab>",
"recipientAddress": "abc@example.com",
"status": "NOT_FOUND"
}
],
"quarantineJobRuns": [
{
"completedDate": "2022-07-07T07:36:20.616526",
"error": 1,
"id": 14,
"jobRunType": "QUARANTINE",
"startedDate": "2022-07-07T07:36:20.035786",
"status": "COMPLETED",
"total": 1
},
{
"completedDate": "2022-07-20T05:37:42.31125",
"error": 0,
"id": 440,
"jobRunType": "RESTORE",
"startedDate": "2022-07-20T05:37:41.585443",
"status": "COMPLETED",
"total": 1
}
],
"stopRequested": true
},
{
"autoQuarantine": false,
"createdBy": "testuser",
"createdDate": "2022-07-07T09:19:07.29997",
"emailCount": 1,
"id": 12,
"modifiedBy": "system",
"modifiedDate": "2022-08-09T11:23:22.074202",
"quarantineEmails": [
{
"createdDate": "2022-07-07T06:46:34.76681",
"errorMessage": "No primary addresses were found for 1/xxxxx@muczynskicofense.onmicrosoft.com",
"ewsMessageId": "AAMkADgyNjJmMzg0LTI1NjgtNDkzMi04OWM4LTQ0YmMxZGMyNjViOABGAAAAAAA2/UgfwINITKjcFdr2xiIPBwDd+41JQMRFTYDq3CRJ00qJAABhEUxVAADd+41JQMRFTYDq3CRJ00qJAABoQNd2AAA=",
"id": 1,
"internetMessageId": "<999389937.952188.1657035399834@af226d4cfbab>",
"originalFolderId": "AQMkADgyNjJmMzg0LTI1NjgtNDkzMi04OWM4LTQ0AGJjMWRjMjY1YjgALgAAAzb9SB/Ag0hMqNwV2vbGIg8BAN37jUlAxEVNgOrcJEnTSokAAAIBJAAAAA==",
"quarantinedDate": "2022-07-15T09:24:59.469491",
"recipientAddress": "pqr@example.com",
"status": "NOT_FOUND"
}
],
"quarantineJobRuns": [
{
"completedDate": "2022-07-07T09:19:22.014868",
"error": 1,
"id": 45,
"jobRunType": "QUARANTINE",
"startedDate": "2022-07-07T09:19:21.583128",
"status": "COMPLETED",
"total": 1
},
{
"completedDate": "2022-08-09T11:23:22.578602",
"error": 0,
"id": 839,
"jobRunType": "RESTORE",
"startedDate": "2022-08-09T11:23:22.076621",
"status": "COMPLETED",
"total": 1
}
],
"stopRequested": false
}
]
}
}
Human Readable Output
Quarantine Job
ID Created By Created Date Last Modified By Last Modified Date Last Action Status Completed Date Messages 8 testuser 07/07/2022, 07:36 AM system 20/07/2022, 05:37 AM RESTORE COMPLETED 20/07/2022, 05:37 AM 1 12 testuser 07/07/2022, 09:19 AM system 09/08/2022, 11:23 AM RESTORE COMPLETED 09/08/2022, 11:23 AM 1
cofense-quarantine-job-create
Creates a new quarantine job.
Base Command
cofense-quarantine-job-create
Input
| Argument Name | Description | Required |
|---|---|---|
| quarantine_emails | A comma-separated string of quarantine emails, specifying the internet message ID and the recipient address of the email. Supported format: internetMessageID1:recipientAddress1, internetMessageID2:recipientAddress2 Where, internetMessageID: IDs of any emails in the particular account to be quarantined, with each internet message ID enclosed in angle brackets. recipientAddress: Email address of the account containing the emails to be quarantined. Example: <513C8CD8-E593-4DC4-82BF6202E8AC95CB>:mail054@example.com, <41348CD8-E593-4DC4-82BF6202E8AC95CB>:ma32il054@example.com Note: Users can get the internet message ID and recipient address by executing the “cofense-message-search-results-get” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.createdBy | String | Client that created the quarantine job. |
| Cofense.QuarantineJob.createdDate | Date | Date and time the quarantine job was created. The timestamp is in UTC. |
| Cofense.QuarantineJob.modifiedBy | String | Client that last updated the quarantine job. |
| Cofense.QuarantineJob.modifiedDate | Date | Date and time the quarantine job was last modified. The timestamp is in UTC. |
| Cofense.QuarantineJob.stopRequested | Boolean | Whether a request was issued (true) or was not issued (false) to stop the quarantine job. |
| Cofense.QuarantineJob.emailCount | Number | Number of emails quarantined. |
| Cofense.QuarantineJob.quarantineEmails.createdDate | Date | Date the quarantine job was created. |
| Cofense.QuarantineJob.quarantineEmails.errorMessage | String | Error message. |
| Cofense.QuarantineJob.quarantineEmails.ewsMessageId | String | ID of the email in EWS. |
| Cofense.QuarantineJob.quarantineEmails.id | Number | ID in cofense vision. |
| Cofense.QuarantineJob.quarantineEmails.internetMessageID | String | ID of the email assigned by the message transfer agent. |
| Cofense.QuarantineJob.quarantineEmails.originalFolderId | String | ID of the EWS folder where the email was located before it was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.quarantinedDate | Date | Date the email was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.recipientAddress | String | Email address of the account containing the emails to be quarantined. |
| Cofense.QuarantineJob.quarantineEmails.status | String | Status of the email. |
| Cofense.QuarantineJob.quarantineJobRuns.completedDate | Date | Date the quarantine job completed. |
| Cofense.QuarantineJob.quarantineJobRuns.error | Number | Total number of errors in the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.id | Number | ID of the quarantine job in Cofense Vision. |
| Cofense.QuarantineJob.quarantineJobRuns.jobRunType | String | Type of Job depending on the operation being performed against the emails. |
| Cofense.QuarantineJob.quarantineJobRuns.startedDate | Date | Date the quarantine job started. |
| Cofense.QuarantineJob.quarantineJobRuns.status | String | Status of the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.total | Number | Total number of emails in the quarantine job. |
| Cofense.QuarantineJob.autoQuarantine | Boolean | Whether the quarantine job was part of an auto quarantine action (true) or was not part of an auto quarantine action (false). |
| Cofense.QuarantineJob.matchingIOCs | Unknown | MD5 hash of one or more matching IOCs. |
| Cofense.QuarantineJob.matchingSources | Unknown | One or more IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.QuarantineJob.matchingIocInfo.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.source | Unknown | Data that the IOC source reads and writes. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.first_quarantined_at | Date | Date and time Cofense Vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.last_quarantined_at | Date | Date and time Cofense Vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.QuarantineJob.searchId | Number | ID that Cofense Vision assigned to the search, if any. |
Command example
!cofense-quarantine-job-create quarantine_emails="<test-id>:test@example.com"
Context Example
{
"Cofense": {
"QuarantineJob": {
"autoQuarantine": false,
"createdBy": "testuser",
"createdDate": "2022-08-10T04:23:57.442172557",
"emailCount": 1,
"id": 431,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-10T04:23:57.442172557",
"quarantineEmails": [
{
"createdDate": "2022-08-08T09:15:46.921796",
"errorMessage": "No primary addresses were found for 5578/xxxxx@example.com",
"id": 5578,
"internetMessageId": "<test-id>",
"recipientAddress": "test@example.com",
"status": "UNKNOWN_MAILBOX"
}
],
"quarantineJobRuns": [
{
"error": 0,
"id": 860,
"jobRunType": "QUARANTINE",
"status": "NEW",
"total": 1
}
],
"stopRequested": false
}
}
}
Human Readable Output
Quarantine job create
Quarantine job has been created successfully
ID Created By Created Date Last Modified By Last Modified Date Messages 431 testuser 10/08/2022, 04:23 AM testuser 10/08/2022, 04:23 AM 1
cofense-quarantine-job-delete
Deletes the quarantine job identified by its unique ID.
Base Command
cofense-quarantine-job-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the quarantine job in cofense vision to be deleted. Note: Users can get the list of IDs by executing the “cofense-quarantine-jobs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.isDeleted | Boolean | Whether the quarantine job is successfully deleted(true) or not(false). |
Command example
!cofense-quarantine-job-delete id=266
Context Example
{
"Cofense": {
"QuarantineJob": {
"id": "266",
"isDeleted": true
}
}
}
Human Readable Output
Quarantine Job with ID 266 is successfully deleted
cofense-quarantine-job-get
Retrieves quarantine job identified by its unique ID.
Base Command
cofense-quarantine-job-get
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the quarantine job in cofense vision to be retrieved. Note: Users can get the list of IDs by executing the “cofense-quarantine-jobs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.createdBy | String | Client that created the quarantine job. |
| Cofense.QuarantineJob.createdDate | Date | Date and time the quarantine job was created. The timestamp is in UTC. |
| Cofense.QuarantineJob.modifiedBy | String | Client that last updated the quarantine job. |
| Cofense.QuarantineJob.modifiedDate | Date | Date and time the quarantine job was last modified. The timestamp is in UTC. |
| Cofense.QuarantineJob.stopRequested | Boolean | Whether a request was issued (true) or was not issued (false) to stop the quarantine job. |
| Cofense.QuarantineJob.emailCount | Number | Number of emails quarantined. |
| Cofense.QuarantineJob.quarantineEmails.createdDate | Date | Date the quarantine job was created. |
| Cofense.QuarantineJob.quarantineEmails.errorMessage | String | Error message. |
| Cofense.QuarantineJob.quarantineEmails.ewsMessageId | String | ID of the email in EWS. |
| Cofense.QuarantineJob.quarantineEmails.id | Number | ID in cofense vision. |
| Cofense.QuarantineJob.quarantineEmails.internetMessageID | String | ID of the email assigned by the message transfer agent. |
| Cofense.QuarantineJob.quarantineEmails.originalFolderId | String | ID of the EWS folder where the email was located before it was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.quarantinedDate | Date | Date the email was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.recipientAddress | String | Email address of the account containing the emails to be quarantined. |
| Cofense.QuarantineJob.quarantineEmails.status | String | Status of the email. |
| Cofense.QuarantineJob.quarantineJobRuns.completedDate | Date | Date the quarantine job completed. |
| Cofense.QuarantineJob.quarantineJobRuns.error | Number | Total number of errors in the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.id | Number | ID of the quarantine job in Cofense Vision. |
| Cofense.QuarantineJob.quarantineJobRuns.jobRunType | String | Type of Job depending on the operation being performed against the emails. |
| Cofense.QuarantineJob.quarantineJobRuns.startedDate | Date | Date the quarantine job started. |
| Cofense.QuarantineJob.quarantineJobRuns.status | String | Status of the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.total | Number | Total number of emails in the quarantine job. |
| Cofense.QuarantineJob.autoQuarantine | Boolean | Whether the quarantine job was part of an auto quarantine action (true) or was not part of an auto quarantine action (false). |
| Cofense.QuarantineJob.matchingIOCs | Unknown | MD5 hash of one or more matching IOCs. |
| Cofense.QuarantineJob.matchingSources | Unknown | One or more IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.QuarantineJob.matchingIocInfo.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.source | Unknown | Data that the IOC source reads and writes. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expires_at | Date | Date and time in UTC, after which this IOC expires. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.first_quarantined_at | Date | Date and time Cofense Vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.last_quarantined_at | Date | Date and time Cofense Vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.QuarantineJob.searchId | Number | ID that Cofense Vision assigned to the search, if any. |
Command example
!cofense-quarantine-job-get id=100
Context Example
{
"Cofense": {
"QuarantineJob": {
"autoQuarantine": false,
"createdBy": "testuser",
"createdDate": "2022-07-08T15:49:19.302416",
"emailCount": 10,
"id": 100,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-09T11:36:35.996422",
"quarantineEmails": [
{
"createdDate": "2022-07-08T15:49:16.87704",
"ewsMessageId": "AAMkAGJhMGUzOTc2LTYxNjEtNDRlYi1hNWRmLWQyMGE5ZWZkY2JlOQBGAAAAAACYdf11Yr3QRIC86wUeQZguBwAMKVxfPrXHRbB4YDM6zXqKAABm5hr/AAAMKVxfPrXHRbB4YDM6zXqKAABm5h7VAAA=",
"id": 67,
"internetMessageId": "<1178768708.1512835.1657295339501@af226d4cfbab>",
"originalFolderId": "AQMkAGJhMGUzOTc2LTYxNjEtNDQAZWItYTVkZi1kMjBhOWVmZGNiZTkALgAAA5h1/XVivdBEgLzrBR5BmC4BAAwpXF8+tcdFsHhgMzrNeooAAAIBDAAAAA==",
"quarantinedDate": "2022-07-08T15:49:38.563419",
"recipientAddress": "abc@example.com",
"status": "NOT_FOUND"
},
{
"createdDate": "2022-07-08T15:49:16.89515",
"ewsMessageId": "AAMkADBkODY5OTkzLTFhMDMtNDUxZC05MTY4LTU1MWMzYmU2ZGM0YgBGAAAAAADHqxFyD0K3TI6sCxIePsQSBwALsQhDVRPPQpNK3uNfrckFAABmyPjPAAALsQhDVRPPQpNK3uNfrckFAABmyPylAAA=",
"id": 76,
"internetMessageId": "<1178768708.1512835.1657295339501@af226d4cfbab>",
"originalFolderId": "AQMkADBkODY5OQEzLTFhMDMtNDUxZC05MTY4LTU1ADFjM2JlNmRjNGIALgAAA8erEXIPQrdMjqwLEh4+xBIBAAuxCENVE89Ck0re41+tyQUAAAIBDAAAAA==",
"quarantinedDate": "2022-07-08T15:49:34.372725",
"recipientAddress": "pqr@example.com",
"status": "NOT_FOUND"
}
],
"quarantineJobRuns": [
{
"completedDate": "2022-07-08T15:49:41.865254",
"error": 0,
"id": 232,
"jobRunType": "QUARANTINE",
"startedDate": "2022-07-08T15:49:25.956206",
"status": "COMPLETED",
"total": 10
},
{
"completedDate": "2022-08-09T11:36:29.566425",
"error": 0,
"id": 841,
"jobRunType": "RESTORE",
"startedDate": "2022-08-09T11:36:22.344285",
"status": "COMPLETED",
"total": 10
}
],
"searchId": 402,
"stopRequested": true
}
}
}
Human Readable Output
Quarantine Job
ID Search ID Created By Created Date Last Modified By Last Modified Date Last Action Status Completed Date Messages 100 402 testuser 08/07/2022, 03:49 PM testuser 09/08/2022, 11:36 AM RESTORE COMPLETED 09/08/2022, 11:36 AM 10
cofense-quarantine-job-restore
Restores emails quarantined by the job identified by its unique ID.
Base Command
cofense-quarantine-job-restore
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the quarantine job in cofense vision to be restored. Note: Users can get the list of ID by executing the “cofense-quarantine-jobs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.isRestored | Boolean | Whether the quarantine job is successfully restored(true) or not(false). |
Command example
!cofense-quarantine-job-restore id=100
Context Example
{
"Cofense": {
"QuarantineJob": {
"id": "100",
"isRestored": true
}
}
}
Human Readable Output
Emails quarantined by the quarantine job ID 100 have been successfully restored
cofense-quarantine-job-approve
Approves the quarantine job identified by its unique ID. When the “Auto Quarantine” feature is configured which requires manual approvals, this command can approve all the pending quarantine jobs.
Base Command
cofense-quarantine-job-approve
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the quarantine job in cofense vision to be approved. Note: Users can get the list of IDs by executing the “cofense-quarantine-jobs-list” command. |
Required |
| message_count | Number of emails containing IOC matches to be quarantined. When message_count is present, cofense vision quarantines a subset of the total number of emails containing IOC matches. The value must be a non-zero and positive integer. If message_count is not present, all messages will be approved. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.isApproved | Boolean | Whether the quarantine job is successfully approved(true) or not(false). |
Command example
!cofense-quarantine-job-approve id=430 message_count=1
Context Example
{
"Cofense": {
"QuarantineJob": {
"id": "430",
"isApproved": true
}
}
}
Human Readable Output
Quarantine Job with ID 430 has been approved successfully
cofense-quarantine-job-stop
Issues a request to stop the quarantine job identified by its unique ID.
Base Command
cofense-quarantine-job-stop
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the quarantine job in cofense vision to be stopped. Note: Users can get the list of IDs by executing the “cofense-quarantine-jobs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.QuarantineJob.id | Number | ID of the quarantine job in cofense vision. |
| Cofense.QuarantineJob.createdBy | String | Client that created the quarantine job. |
| Cofense.QuarantineJob.createdDate | Date | Date and time the quarantine job was created. The timestamp is in UTC. |
| Cofense.QuarantineJob.modifiedBy | String | Client that last updated the quarantine job. |
| Cofense.QuarantineJob.modifiedDate | Date | Date and time the quarantine job was last modified. The timestamp is in UTC. |
| Cofense.QuarantineJob.stopRequested | Boolean | Whether a request was issued (true) or was not issued (false) to stop the quarantine job. |
| Cofense.QuarantineJob.emailCount | Number | Number of emails quarantined. |
| Cofense.QuarantineJob.quarantineEmails.createdDate | Date | Date the quarantine job was created. |
| Cofense.QuarantineJob.quarantineEmails.errorMessage | String | Error message. |
| Cofense.QuarantineJob.quarantineEmails.ewsMessageId | String | ID of the email in EWS. |
| Cofense.QuarantineJob.quarantineEmails.id | Number | ID in cofense vision. |
| Cofense.QuarantineJob.quarantineEmails.internetMessageID | String | ID of the email assigned by the message transfer agent. |
| Cofense.QuarantineJob.quarantineEmails.originalFolderId | String | ID of the EWS folder where the email was located before it was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.quarantinedDate | Date | Date the email was quarantined. |
| Cofense.QuarantineJob.quarantineEmails.recipientAddress | String | Email address of the account containing the emails to be quarantined. |
| Cofense.QuarantineJob.quarantineEmails.status | String | Status of the email. |
| Cofense.QuarantineJob.quarantineJobRuns.completedDate | Date | Date the quarantine job completed. |
| Cofense.QuarantineJob.quarantineJobRuns.error | Number | Total number of errors in the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.id | Number | ID of the quarantine job in Cofense Vision. |
| Cofense.QuarantineJob.quarantineJobRuns.jobRunType | String | Type of Job depending on the operation being performed against the emails. |
| Cofense.QuarantineJob.quarantineJobRuns.startedDate | Date | Date the quarantine job started. |
| Cofense.QuarantineJob.quarantineJobRuns.status | String | Status of the quarantine job. |
| Cofense.QuarantineJob.quarantineJobRuns.total | Number | Total number of emails in the quarantine job. |
| Cofense.QuarantineJob.autoQuarantine | Boolean | Whether the quarantine job was part of an auto quarantine action (true) or was not part of an auto quarantine action (false). |
| Cofense.QuarantineJob.matchingIOCs | Unknown | MD5 hash of one or more matching IOCs. |
| Cofense.QuarantineJob.matchingSources | Unknown | One or more IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.QuarantineJob.matchingIocInfo.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.QuarantineJob.matchingIocInfo.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.source | Unknown | Data that the IOC source reads and writes. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expires_at | Date | Date and time in UTC, after which this IOC expires. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.first_quarantined_at | Date | Date and time Cofense Vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.last_quarantined_at | Date | Date and time Cofense Vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.QuarantineJob.matchingIocInfo.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.QuarantineJob.searchId | Number | ID that Cofense Vision assigned to the search, if any. |
Command example
!cofense-quarantine-job-stop id=100
Context Example
{
"Cofense": {
"QuarantineJob": {
"autoQuarantine": false,
"createdBy": "testuser",
"createdDate": "2022-07-08T15:49:19.302416",
"emailCount": 10,
"id": 100,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-10T04:24:37.004847",
"quarantineEmails": [
{
"createdDate": "2022-07-08T15:49:16.87704",
"ewsMessageId": "AAMkAGJhMGUzOTc2LTYxNjEtNDRlYi1hNWRmLWQyMGE5ZWZkY2JlOQBGAAAAAACYdf11Yr3QRIC86wUeQZguBwAMKVxfPrXHRbB4YDM6zXqKAABm5hr/AAAMKVxfPrXHRbB4YDM6zXqKAABm5h7VAAA=",
"id": 67,
"internetMessageId": "<1178768708.1512835.1657295339501@af226d4cfbab>",
"originalFolderId": "AQMkAGJhMGUzOTc2LTYxNjEtNDQAZWItYTVkZi1kMjBhOWVmZGNiZTkALgAAA5h1/XVivdBEgLzrBR5BmC4BAAwpXF8+tcdFsHhgMzrNeooAAAIBDAAAAA==",
"quarantinedDate": "2022-07-08T15:49:38.563419",
"recipientAddress": "abc@example.com",
"status": "NOT_FOUND"
},
{
"createdDate": "2022-07-08T15:49:16.89515",
"ewsMessageId": "AAMkADBkODY5OTkzLTFhMDMtNDUxZC05MTY4LTU1MWMzYmU2ZGM0YgBGAAAAAADHqxFyD0K3TI6sCxIePsQSBwALsQhDVRPPQpNK3uNfrckFAABmyPjPAAALsQhDVRPPQpNK3uNfrckFAABmyPylAAA=",
"id": 76,
"internetMessageId": "<1178768708.1512835.1657295339501@af226d4cfbab>",
"originalFolderId": "AQMkADBkODY5OQEzLTFhMDMtNDUxZC05MTY4LTU1ADFjM2JlNmRjNGIALgAAA8erEXIPQrdMjqwLEh4+xBIBAAuxCENVE89Ck0re41+tyQUAAAIBDAAAAA==",
"quarantinedDate": "2022-07-08T15:49:34.372725",
"recipientAddress": "pqr@example.com",
"status": "NOT_FOUND"
}
],
"quarantineJobRuns": [
{
"completedDate": "2022-07-08T15:49:41.865254",
"error": 0,
"id": 232,
"jobRunType": "QUARANTINE",
"startedDate": "2022-07-08T15:49:25.956206",
"status": "COMPLETED",
"total": 10
},
{
"completedDate": "2022-07-08T15:49:58.163195",
"error": 0,
"id": 233,
"jobRunType": "RESTORE",
"startedDate": "2022-07-08T15:49:56.006024",
"status": "COMPLETED",
"total": 10
},
{
"error": 0,
"id": 861,
"jobRunType": "RESTORE",
"startedDate": "2022-08-10T04:24:24.432429",
"status": "RUNNING",
"total": 10
}
],
"searchId": 402,
"stopRequested": true
}
}
}
Human Readable Output
Quarantine job with ID 100 has been successfully stopped
ID Created By Created Date Last Modified By Last Modified Date Last Action Status Messages Stopped Quarantine 100 testuser 08/07/2022, 03:49 PM testuser 10/08/2022, 04:24 AM RESTORE RUNNING 10 true
cofense-message-searches-list
Retrieves the list of searches.
Base Command
cofense-message-searches-list
Input
| Argument Name | Description | Required |
|---|---|---|
| page | The start page of the results. The value must be a positive integer or 0. Default is 0. | Optional |
| size | The number of results to retrieve per page. The value must be a positive integer up to 2000. Default is 50. | Optional |
| sort | The name-value pair defining the order of the response. Comma separated values are supported. Supported format: propertyName1:sortOrder1,propertyName2:sortOrder2 Supported values for propertyName are: id, createdBy, createdDate, modifiedBy, modifiedDate, receivedAfterDate, receivedBeforeDate. Supported values for sortOrder are: asc, desc. Default is id:asc. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Search.id | String | ID that Cofense Vision assigned to the search. |
| Cofense.Search.createdBy | String | Username of the client that created the search. |
| Cofense.Search.createdDate | Date | Date and time the search was created. The timestamp is in UTC. |
| Cofense.Search.modifiedBy | String | Username of the last client that updated the search. |
| Cofense.Search.modifiedDate | Date | Date and time the search was last modified. The timestamp is in UTC. |
| Cofense.Search.subjects | Unknown | List of email subjects. |
| Cofense.Search.senders | Unknown | List of sender’s email addresses. |
| Cofense.Search.recipient | String | Email address of the recipient. |
| Cofense.Search.attachmentNames | Unknown | List of attachment file names. |
| Cofense.Search.attachmentHashCriteria.type | String | The type of matching for attachment hash. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashType | String | The type of hash. Either MD5 or SHA256. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashString | String | The hash of the attachment file. |
| Cofense.Search.domainCriteria.type | String | The type of matching for domains. |
| Cofense.Search.domainCriteria.domains | Unknown | List of domains. |
| Cofense.Search.domainCriteria.domains.whiteListUrls | Unknown | List of URLs to white list. |
| Cofense.Search.attachmentMimeTypes | Unknown | List of MIME types. |
| Cofense.Search.attachmentExcludeMimeTypes | Unknown | List of MIME types to exclude. |
| Cofense.Search.receivedAfterDate | Date | Filters for emails received on or after this date and time. |
| Cofense.Search.receivedBeforeDate | Date | Filters for emails received before or on this date and time. |
| Cofense.Search.url | String | The URL to search for. |
| Cofense.Search.internetMessageId | String | Unique identifier of the email. |
| Cofense.Search.headers.key | String | The name of the key in the header. |
| Cofense.Search.headers.values | String | The value of the key in the header. |
| Cofense.Search.partialIngest | Boolean | Indicates whether to search partially ingested emails or not. |
Command example
!cofense-message-searches-list size=2
Context Example
{
"Cofense": {
"Search": [
{
"attachmentHashCriteria": {
"type": "ANY"
},
"createdBy": "testuser",
"createdDate": "2022-07-11T07:41:25.184255",
"domainCriteria": {
"type": "ANY"
},
"id": 430,
"modifiedBy": "testuser",
"modifiedDate": "2022-07-11T07:41:25.184255",
"recipient": "abc@example.com"
},
{
"attachmentHashCriteria": {
"type": "ANY"
},
"createdBy": "testuser",
"createdDate": "2022-07-11T07:42:58.176356",
"domainCriteria": {
"type": "ANY"
},
"id": 431,
"modifiedBy": "testuser",
"modifiedDate": "2022-07-11T07:42:58.176356",
"recipient": "pqr@example.com",
"subjects": [
"chalk1 time 1657035399833"
]
}
]
}
}
Human Readable Output
Message Searches
ID Created By Created Date Modified By Modified Date Recipient Subjects 430 testuser 11/07/2022, 07:41 AM testuser 11/07/2022, 07:41 AM abc@example.com 431 testuser 11/07/2022, 07:42 AM testuser 11/07/2022, 07:42 AM pqr@example.com chalk1 time 1657035399833
cofense-message-search-get
Retrieves the result of the search identified by an ID.
Base Command
cofense-message-search-get
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The unique ID that cofense vision has assigned to a search. Note: The ID can be retrieved by using the command “cofense-message-searches-list”. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Search.id | String | ID that Cofense Vision assigned to the search. |
| Cofense.Search.createdBy | String | Username of the client that created the search. |
| Cofense.Search.createdDate | Date | Date and time the search was created. The timestamp is in UTC. |
| Cofense.Search.modifiedBy | String | Username of the last client that updated the search. |
| Cofense.Search.modifiedDate | Date | Date and time the search was last modified. The timestamp is in UTC. |
| Cofense.Search.subjects | Unknown | List of email subjects. |
| Cofense.Search.senders | Unknown | List of sender’s email addresses. |
| Cofense.Search.recipient | String | Email address of the recipient. |
| Cofense.Search.attachmentNames | Unknown | List of attachment file names. |
| Cofense.Search.attachmentHashCriteria.type | String | The type of matching for attachment hash. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashType | String | The type of hash. Either MD5 or SHA256. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashString | String | The hash of the attachment file. |
| Cofense.Search.domainCriteria.type | String | The type of matching for domains. |
| Cofense.Search.domainCriteria.domains | Unknown | List of domains. |
| Cofense.Search.domainCriteria.domains.whiteListUrls | Unknown | List of URLs to white list. |
| Cofense.Search.attachmentMimeTypes | Unknown | List of MIME types. |
| Cofense.Search.attachmentExcludeMimeTypes | Unknown | List of MIME types to exclude. |
| Cofense.Search.receivedAfterDate | Date | Filters the emails received on or after this date and time. |
| Cofense.Search.receivedBeforeDate | Date | Filters the emails received before or on this date and time. |
| Cofense.Search.url | String | The URL to be searched for. |
| Cofense.Search.internetMessageId | String | Unique identifier of the email. |
| Cofense.Search.headers.key | String | The name of the key in the header. |
| Cofense.Search.headers.values | String | The value of the key in the header. |
| Cofense.Search.partialIngest | Boolean | Indicates whether to search partially ingested emails or not. |
Command example
!cofense-message-search-get id=700
Context Example
{
"Cofense": {
"Search": {
"attachmentHashCriteria": {
"type": "ANY"
},
"createdBy": "testuser",
"createdDate": "2022-08-02T19:05:08.035549",
"domainCriteria": {
"type": "ANY"
},
"id": 700,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-02T19:05:08.035549"
}
}
}
Human Readable Output
Message Search
ID Created By Created Date Modified By Modified Date 700 testuser 02/08/2022, 07:05 PM testuser 02/08/2022, 07:05 PM
cofense-message-search-create
Creates a new search.
Base Command
cofense-message-search-create
Input
| Argument Name | Description | Required |
|---|---|---|
| subjects | A comma-separated string of subjects to create a search for an email’s subject. It supports the use of one or more wildcard characters (*) in any position of a subject. Note: The search can only have a maximum of 3 values. |
Optional |
| senders | A comma-separated string of senders to create a search for an email’s sender. It supports the use of one or more wildcard characters (*) in any position of a sender’s email address. Note: The search can only have a maximum of 3 values. |
Optional |
| attachment_names | A comma-separated string of attachment names to create a search for an email’s attachments. It supports the use of one or more wildcard characters (*) in any position of an attachment name. Note: The search can only have a maximum of 3 values. |
Optional |
| attachment_hash_match_criteria | The type of matching performed on the hashes specified in the attachment_hashes argument. Possible values are: ALL: Emails must include all listed attachment hashes. ANY: Emails must contain at least one of the listed attachment hash. Possible values are: ANY, ALL. Default is ANY. |
Optional |
| attachment_hashes | A comma-separated string of attachment hashes to create a search for an email’s attachment hashes. Supported format: hashtype1:hashvalue1, hashtype2:hashvalue2 Possible values for hashtype are: MD5, SHA256 Example: md5:938c2cc0dcc05f2b68c4287040cfcf71 Note: The search can only have a maximum of 3 values. |
Optional |
| attachment_mime_types | A comma-separated string of MIME types to create a search for an email’s attachment MIME type. Note: The search can only have a maximum of 3 values. |
Optional |
| attachment_exclude_mime_types | A comma-separated string of MIME types to create a search for excluding an email’s attachment MIME type. Note: The search can only have a maximum of 3 values. |
Optional |
| domain_match_criteria | The type of matching to perform on the domains specified in the domains argument. Possible values are: ALL: Emails must include all listed domains. ANY: Emails must contain at least one of the listed domains. Possible values are: ANY, ALL. Default is ANY. |
Optional |
| domains | A comma-separated string of domains to create a search for domains in an email’s body or its attachment. You can change the type of matching that happens on the specified domains using the domain_match_criteria argument. Note: The search can only have a maximum of 3 values. |
Optional |
| whitelist_urls | A comma-separated string of URLs to be whitelisted. Note: The search can only have a maximum of 3 values. |
Optional |
| headers | A comma-separated string of key-value pairs, defining the additional criteria to search for in the email header. Supported format: key1:value1, key2:value1:value2:value3 Example: Content-Type:application/json List of available headers to create a search can be retrieved by using the command “cofense-searchable-headers-list”. Note: The search can only have a maximum of 3 values. |
Optional |
| internet_message_id | The unique identifier of the email, enclosed in angle brackets. This argument is case-sensitive. Example: <513C8CD8-E593-4DC4-82BF6202E8AC95CB@example.com>. |
Optional |
| partial_ingest | Whether to create a search with partially ingested emails (true) or not with partially ingested emails (false). Possible values are: True, False. Default is False. | Optional |
| received_after_date | Date and time to create a search for emails to specify the received on or after the specified UTC date and time. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Optional |
| received_before_date | Date and time to create a search for emails to specify the received before or on the specified UTC date and time. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Optional |
| recipient | Create a search with the specified recipient. Supports one or more wildcard characters (*) in any position of a recipient’s email address. |
Optional |
| url | Create a search with the specified url. Supports one or more wildcard characters (*) in any position of the URL. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Search.id | String | ID that cofense vision assigned to the search. |
| Cofense.Search.createdBy | String | Username of the client that created the search. |
| Cofense.Search.createdDate | Date | Date and time the search was created. The timestamp is in UTC. |
| Cofense.Search.modifiedBy | String | Username of the last client that updated the search. |
| Cofense.Search.modifiedDate | Date | Date and time the search was last modified. The timestamp is in UTC. |
| Cofense.Search.subjects | Unknown | List of email subjects. |
| Cofense.Search.senders | Unknown | List of sender’s email addresses. |
| Cofense.Search.recipient | String | Email address of the recipient. |
| Cofense.Search.attachmentNames | Unknown | List of attachment file names. |
| Cofense.Search.attachmentHashCriteria.type | String | The type of matching for attachment hash. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashType | String | The type of hash. Either MD5 or SHA256. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashString | String | The hash of the attachment file. |
| Cofense.Search.domainCriteria.type | String | The type of matching for domains. |
| Cofense.Search.domainCriteria.domains | Unknown | List of domains. |
| Cofense.Search.domainCriteria.domains.whiteListUrls | Unknown | List of URLs to white list. |
| Cofense.Search.attachmentMimeTypes | Unknown | List of MIME types. |
| Cofense.Search.attachmentExcludeMimeTypes | Unknown | List of MIME types to exclude. |
| Cofense.Search.receivedAfterDate | Date | Filters for emails received on or after this date and time. |
| Cofense.Search.receivedBeforeDate | Date | Filters for emails received before or on this date and time. |
| Cofense.Search.url | String | The URL to search for. |
| Cofense.Search.internetMessageId | String | Unique identifier of the email. |
| Cofense.Search.headers.key | String | The name of the key in the header. |
| Cofense.Search.headers.values | String | The value of the key in the header. |
| Cofense.Search.partialIngest | Boolean | Indicates whether to search partially ingested emails or not. |
Command example
!cofense-message-search-create subjects="test" senders="abc@example.com, pqr@example.com"
Context Example
{
"Cofense": {
"Search": {
"attachmentHashCriteria": {
"type": "ANY"
},
"createdBy": "testuser",
"createdDate": "2022-08-10T04:25:00.626652162",
"domainCriteria": {
"type": "ANY"
},
"id": 1091,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-10T04:25:00.626652162",
"partialIngest": false,
"senders": [
"abc@example.com",
"pqr@example.com"
],
"subjects": [
"test"
]
}
}
}
Human Readable Output
Message search with ID 1091 has been created successfully
ID Created By Created Date Modified By Modified Date Senders Subjects Partial Ingest 1091 testuser 10/08/2022, 04:25 AM testuser 10/08/2022, 04:25 AM abc@example.com,
pqr@example.comtest false
cofense-message-search-results-get
Retrieves the results for the search identified by the search ID.
Base Command
cofense-message-search-results-get
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The unique ID that cofense vision has assigned to a search. Note: The ID can be retrieved by using the command “cofense-message-searches-list”. |
Required |
| page | The start page of the results. The value must be a positive integer or 0. Default is 0. | Optional |
| size | The number of results to retrieve per page. The value must be a positive integer up to 2000. Default is 50. | Optional |
| sort | The name-value pair defining the order of the response. Comma-separated values are supported. Supported format: propertyName1:sortOrder1,propertyName2:sortOrder2 Supported values for propertyName are: id, subject, createdOn, sentOn, htmlBody, md5, sha1, sha256. Supported values for sortOrder are: asc, desc. Default is id:asc. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Search.Message.id | Number | The ID of the message. |
| Cofense.Search.Message.storageUri | String | Storage URI of the search. |
| Cofense.Search.Message.subject | String | The subject of the message. |
| Cofense.Search.Message.receivedOn | Date | The date and time when the message was received by the recipient. |
| Cofense.Search.Message.sentOn | Date | The date and time when the message was sent by the sender. |
| Cofense.Search.Message.deliveredOn | Date | The date and time when the message was delivered. |
| Cofense.Search.Message.processedOn | Date | The date and time Cofense Vision ingested the email. |
| Cofense.Search.Message.textBody | String | Body of the email in text format. |
| Cofense.Search.Message.htmlBody | String | Body of the email in HTML format. |
| Cofense.Search.Message.md5 | String | The MD5 hash of the message. |
| Cofense.Search.Message.sha1 | String | The SHA1 hash of the message. |
| Cofense.Search.Message.sha256 | String | The SHA256 hash of the message. |
| Cofense.Search.Message.internetMessageId | String | Unique identifier of the email. |
| Cofense.Search.Message.from.id | Number | The ID of the sender. |
| Cofense.Search.Message.from.personal | String | The name of the sender. |
| Cofense.Search.Message.from.address | String | The email address of the sender. |
| Cofense.Search.Message.headers.id | Number | The ID of the header. |
| Cofense.Search.Message.headers.name | String | The name of the header key. |
| Cofense.Search.Message.headers.value | String | The value of the header key. |
| Cofense.Search.Message.headers.seq | Number | Sequence of header field. |
| Cofense.Search.Message.headers.partialIngest | String | “Null” if no partially ingested messages found; otherwise, one or more of the following to describe the source of the ingestion failure: PARSE, ATTACHMENT, URL, UNKNOWN. |
| Cofense.Search.Message.recipients.id | Number | The ID of the recipient. |
| Cofense.Search.Message.recipients.personal | String | The name of the recipient. |
| Cofense.Search.Message.recipients.address | String | The email address of the recipient. |
| Cofense.Search.Message.recipients.recipientType | String | The type of the recipient. Whether the recipient is in ‘to’, ‘cc’ or in ‘bcc’. |
| Cofense.Search.Message.attachments.size | Number | The size of the attachment file. |
| Cofense.Search.Message.attachments.filename | String | The name of the attachment file. |
| Cofense.Search.Message.attachments.contentType | String | The content type present in the header. |
| Cofense.Search.Message.attachments.detectedContentType | String | The detected content type of the attachment. |
| Cofense.Search.Message.attachments.md5 | String | The MD5 hash of the attachment. |
| Cofense.Search.Message.attachments.sha256 | String | The SHA256 hash of the attachment. |
| Cofense.Search.Message.attachments.id | Number | The ID of the attachment. |
| Cofense.Search.id | String | ID that cofense vision assigned to the search. |
| Cofense.Search.createdBy | String | Username of the client that created the search. |
| Cofense.Search.createdDate | Date | Date and time the search was created. The timestamp is in UTC. |
| Cofense.Search.modifiedBy | String | Username of the last client that updated the search. |
| Cofense.Search.modifiedDate | Date | Date and time the search was last modified. The timestamp is in UTC. |
| Cofense.Search.subjects | Unknown | List of email subjects. |
| Cofense.Search.senders | Unknown | List of sender’s email addresses. |
| Cofense.Search.recipient | String | Email address of the recipient. |
| Cofense.Search.attachmentNames | Unknown | List of attachment file names. |
| Cofense.Search.attachmentHashCriteria.type | String | The type of matching for attachment hash. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashType | String | The type of hash. Either MD5 or SHA256. |
| Cofense.Search.attachmentHashCriteria.attachmentHashes.hashString | String | The hash of the attachment file. |
| Cofense.Search.domainCriteria.type | String | The type of matching for domains. |
| Cofense.Search.domainCriteria.domains | Unknown | List of domains. |
| Cofense.Search.domainCriteria.domains.whiteListUrls | Unknown | List of URLs to white list. |
| Cofense.Search.attachmentMimeTypes | Unknown | List of MIME types. |
| Cofense.Search.attachmentExcludeMimeTypes | Unknown | List of MIME types to exclude. |
| Cofense.Search.receivedAfterDate | Date | Filters for emails received on or after this date and time. |
| Cofense.Search.receivedBeforeDate | Date | Filters for emails received before or on this date and time. |
| Cofense.Search.url | String | The url to search for. |
| Cofense.Search.internetMessageId | String | Unique identifier of the email. |
| Cofense.Search.headers.key | String | The name of the key in the header. |
| Cofense.Search.headers.values | String | The value of the key in the header. |
| Cofense.Search.partialIngest | Boolean | Indicates whether to search partially ingested emails or not. |
Command example
!cofense-message-search-results-get id=700 size=2
Context Example
{
"Cofense": {
"Search": {
"Message": [
{
"attachments": [
{
"contentType": "text/plain",
"detectedContentType": "text/plain",
"filename": "fileNum-Thread[mailer-011,5,main]-text-file-163.txt",
"id": 1673289,
"md5": "3d0e1d68f12afee22ae3e79e01027c7a",
"sha256": "ca68f5eecd5822783911ed392fbff3c171d3a1854c0f992364d038ee447f8ac3",
"size": 59173
},
{
"contentType": "application/zip",
"detectedContentType": "application/zip",
"filename": "fileNum-Thread[mailer-011,5,main]-text-file-146.txt.zip",
"id": 1673290,
"md5": "5c602ca45faac3bb128a5ecbf977f9f1",
"sha256": "6018b7cc402e6368d4542c0f6c129a99e35c80ae9001ec338e7621df2f8ac51f",
"size": 14563
},
{
"detectedContentType": "text/plain",
"filename": "text-file-146.txt",
"id": 1673291,
"md5": "c5aa88f949574a0a5e75a795dc507da7",
"sha256": "d3a070977ae0ae561bae2215526c187d5c46c54dd8899eefb8fe21ed0e6c1303",
"size": 27842
}
],
"from": [
{
"address": "abc@example.com",
"id": 760623,
"personal": "mailbox-08517"
}
],
"headers": [
{
"name": "From",
"value": "abc@example.com"
},
{
"name": "To",
"value": "pqr@example.com"
},
{
"name": "CC",
"value": "abc@example.com"
},
{
"name": "Subject",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Topic",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Index",
"value": "AQHYocD7Ut113z4F00uSjzqlEM2clw=="
},
{
"name": "Date",
"value": "Wed, 27 Jul 2022 13:58:43 +0000"
},
{
"name": "Message-ID",
"value": "<1216208547.160.1658930322668@6d14a4fa9032>"
}
],
"id": 760623,
"internetMessageId": "<1216208547.160.1658930322668@6d14a4fa9032>",
"md5": "a486b023cd82f45f7b099a41dc3776a6",
"processedOn": "2022-07-27T13:58:46.271+00:00",
"receivedOn": "2022-07-27T13:58:44.000+00:00",
"recipients": [
{
"address": "abc@example.com",
"id": 7606409,
"personal": "mailbox-00110",
"recipientType": "to"
},
{
"address": "pqr@example.com",
"id": 7606418,
"personal": "mailbox-00119",
"recipientType": "cc"
}
],
"sentOn": "2022-07-27T13:58:43.000+00:00",
"sha1": "0b744bed73106d5d613d83c71b9d9884f48690f4",
"sha256": "2d7bad3fe37c9e4089e6231784f51354ef2fd9689fe7fae6d46cb70d279da8e0",
"subject": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"attachments": [
{
"detectedContentType": "text/plain",
"filename": "text-file-146.txt",
"id": 1673291,
"md5": "c5aa88f949574a0a5e75a795dc507da7",
"sha256": "d3a070977ae0ae561bae2215526c187d5c46c54dd8899eefb8fe21ed0e6c1303",
"size": 27842
}
],
"from": [
{
"address": "abc@example.com",
"id": 760623,
"personal": "mailbox-08517"
}
],
"headers": [
{
"name": "From",
"value": "abc@example.com"
},
{
"name": "To",
"value": "pqr@example.com"
},
{
"name": "CC",
"value": "abc@example.com"
},
{
"name": "Subject",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Topic",
"value": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
},
{
"name": "Thread-Index",
"value": "AQHYocD7Ut113z4F00uSjzqlEM2clw=="
},
{
"name": "Date",
"value": "Wed, 27 Jul 2022 13:58:43 +0000"
},
{
"name": "Message-ID",
"value": "<1216208547.160.1658930322668@6d14a4fa9033>"
}
],
"id": 760624,
"internetMessageId": "<1216208547.160.1658930322668@6d14a4fa9033>",
"md5": "a486b023cd82f45f7b099a41dc3776a6",
"processedOn": "2022-07-27T13:58:46.271+00:00",
"receivedOn": "2022-07-27T13:58:44.000+00:00",
"recipients": [
{
"address": "abc@example.com",
"id": 7606409,
"personal": "mailbox-00110",
"recipientType": "to"
},
{
"address": "pqr@example.com",
"id": 7606418,
"personal": "mailbox-00119",
"recipientType": "cc"
}
],
"sentOn": "2022-07-27T13:58:43.000+00:00",
"sha1": "0b744bed73106d5d613d83c71b9d9884f48690f4",
"sha256": "2d7bad3fe37c9e4089e6231784f51354ef2fd9689fe7fae6d46cb70d279da8e0",
"subject": "craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646"
}
],
"attachmentHashCriteria": {
"type": "ANY"
},
"createdBy": "testuser",
"createdDate": "2022-08-02T19:05:08.035549",
"domainCriteria": {
"type": "ANY"
},
"id": 700,
"modifiedBy": "testuser",
"modifiedDate": "2022-08-02T19:05:08.035549"
}
}
}
Human Readable Output
Message Search
ID Created By Created Date Modified By Modified Date 700 testuser 02/08/2022, 07:05 PM testuser 02/08/2022, 07:05 PM
Message Search Results
Message ID Internet Message ID Subject Sent On Received On Sender Recipient Attachment File Names 760623 <1216208547.160.1658930322668@6d14a4fa9032> craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646 27/07/2022, 01:58 PM UTC 27/07/2022, 01:58 PM UTC abc@example.com abc@example.com,
abc@example.comFile Name: fileNum-Thread[mailer-011,5,main]-text-file-163.txt
MD5: 3d0e1d68f12afee22ae3e79e01027c7a
SHA256: ca68f5eecd5822783911ed392fbff3c171d3a1854c0f992364d038ee447f8ac3
File Name: fileNum-Thread[mailer-011,5,main]-text-file-146.txt.zip
MD5: 5c602ca45faac3bb128a5ecbf977f9f1
SHA256: 6018b7cc402e6368d4542c0f6c129a99e35c80ae9001ec338e7621df2f8ac51f
File Name: text-file-146.txt
MD5: c5aa88f949574a0a5e75a795dc507da7
SHA256: d3a070977ae0ae561bae2215526c187d5c46c54dd8899eefb8fe21ed0e6c1303760624 <1216208547.160.1658930322668@6d14a4fa9033> craftless plantable desulphurate iodized imbeds invoicing infrangibly prosers damn halberdiers refinedly unmoaned scatteredly11 time 1658930322646 27/07/2022, 01:58 PM UTC 27/07/2022, 01:58 PM UTC abc@example.com abc@example.com,
abc@example.comFile Name: text-file-146.txt
MD5: c5aa88f949574a0a5e75a795dc507da7
SHA256: d3a070977ae0ae561bae2215526c187d5c46c54dd8899eefb8fe21ed0e6c1303
cofense-iocs-list
Lists the IOCs stored in the local IOC Repository.
Base Command
cofense-iocs-list
Input
| Argument Name | Description | Required |
|---|---|---|
| source | A single IOC source value, to fetch the IOCs added or modified by that particular source. The value for source can contain uppercase letters, lowercase letters, numbers, and certain special characters (‘.’, ‘_’ and ‘~’). Examples: Triage-1,IOC_Source-2. |
Required |
| page | The start page of the results. The value must be a positive integer or 0. Default is 0. | Optional |
| size | The number of results to retrieve. Maximum value is ‘2000’. Default is 50. |
Optional |
| sort | The name-value pair defining the order of the response. Supported format: propertyName:sortOrder Supported value for propertyName is: updatedAt. Supported values for sortOrder are: asc, desc. |
Optional |
| include_expired | Whether to include expired IOCs or not. Possible values are: True, False. Default is False. | Optional |
| since | Include only IOCs that were added to the repository after the given UTC date and time. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | String that describes the severity of the threat. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source included the IOC for the first time. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time cofense vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time cofense vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-iocs-list source="Vision-UI" size=2
Context Example
{
"Cofense": {
"IOC": [
{
"attributes": {
"threat_type": "DOMAIN",
"threat_value": "qwe"
},
"id": "088dc5454129d776b4a1484b71bb71b0",
"metadata": {
"quarantine": {
"created_at": "2022-07-29T07:09:39.849+00:00",
"expired": false,
"expires_at": "2022-08-12T07:09:39.849+00:00",
"match_count": 0,
"quarantine_count": 0,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": {
"created_at": "2022-07-29T00:00:00.000+00:00",
"id": "e3026f0c154395767993f34cc71b13e3",
"requested_expiration": "2022-08-12T07:09:39.849+00:00",
"threat_level": "very_high",
"updated_at": "2022-07-29T00:00:00.000+00:00"
}
},
"type": "ioc"
},
{
"attributes": {
"threat_type": "DOMAIN",
"threat_value": "fgh"
},
"id": "1627363590bae65d9497e0e02bc412b4",
"metadata": {
"quarantine": {
"created_at": "2022-08-03T09:20:26.808+00:00",
"expired": false,
"expires_at": "2022-08-17T09:20:26.808+00:00",
"match_count": 0,
"quarantine_count": 0,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": {
"created_at": "2022-02-02T00:00:00.000+00:00",
"id": "709d185bd891a61dedbcea8040a24a95",
"requested_expiration": "2022-08-17T09:20:26.808+00:00",
"threat_level": "High",
"updated_at": "2022-08-03T00:00:00.000+00:00"
}
},
"type": "ioc"
}
]
}
}
Human Readable Output
IOC
ID Threat Type Threat Value Threat Level Updated At Created At Match Count Quarantine Count 088dc5454129d776b4a1484b71bb71b0 DOMAIN qwe very_high 29/07/2022, 07:09 AM UTC 29/07/2022, 07:09 AM UTC 0 0
IOC
ID Threat Type Threat Value Threat Level Updated At Created At Match Count Quarantine Count 1627363590bae65d9497e0e02bc412b4 DOMAIN fgh High 02/08/2022, 09:20 AM UTC 03/08/2022, 09:20 AM UTC 0 0
cofense-ioc-update
Updates the IOC identified by its unique MD5 ID.
Base Command
cofense-ioc-update
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the IOC to be updated. Note: Users can get the list of IDs by executing the “cofense-iocs-list” command. |
Required |
| expires_at | Expiration date and time of the IOC. The timestamp is in UTC. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | String that describes the severity of the threat. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source included the IOC for the first time. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time cofense vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time cofense vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.IOC.metadata.quarantine.wildcard | Boolean | Whether the wildcard matching is set (true) or not (false). |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-ioc-update id="bb78c7a2f8c9eea5b9c5a30eb8c9069b" expires_at="1 day"
Context Example
{
"Cofense": {
"IOC": {
"attributes": {
"threat_type": "DOMAIN",
"threat_value": "test.com"
},
"id": "bb78c7a2f8c9eea5b9c5a30eb8c9069b",
"metadata": {
"quarantine": {
"created_at": "2022-08-08T09:17:11.188+00:00",
"expired": false,
"expires_at": "2022-08-24T04:25:24.909+00:00",
"match_count": 0,
"quarantine_count": 0,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": null
},
"type": "ioc"
}
}
}
Human Readable Output
IOC with value bb78c7a2f8c9eea5b9c5a30eb8c9069b has been updated successfully
ID Threat Type Threat Value Created At Expires At bb78c7a2f8c9eea5b9c5a30eb8c9069b DOMAIN test.com 08/08/2022, 09:17 AM UTC 24/08/2022, 04:25 AM UTC
cofense-iocs-update
Updates one or more IOCs stored in the local IOC repository.
To update multiple IOCs use iocs_json argument.
Note: iocs_json parameter will take precedence over other parameters.
threat_type, threat_value, threat_level, created_at and source_id
are required parameters to update a single IOC.
Base Command
cofense-iocs-update
Input
| Argument Name | Description | Required |
|---|---|---|
| source | A single IOC source value, to fetch the IOCs added or modified by that particular source. The value for source can contain uppercase letters, lowercase letters, numbers, and certain special characters (“.” , “-“ , “_” , “~”). Example: “Traige-1” or “IOC_Source-2”. |
Required |
| iocs_json | List of JSON data containing ioc details to be updated in the IOC local repository. Supported format: [{ “threat_type”: “Domain”, “threat_value”:”test1.com”, “threat_level”: “Malicious”, “created_at”:”20/08/2022”, “source_id”:”test_source_1”, “updated_at”: “20/08/2022”, “requested_expiration”: “30/08/2022” }, { “threat_type”: “Domain”, “threat_value”:”test2.com”, “threat_level”: “Malicious”, “created_at”:”20/08/2022”, “source_id”:”test_source_2”, “updated_at”: “20/08/2022”, “requested_expiration”: “30/08/2022” }] Note: threat_type, threat_value, threat_level, created_at and source_id are required parameters. |
Optional |
| threat_type | Type of the IOC. Supported values: Domain, MD5, Sender, SHA256, Subject, or URL. Possible values are: Domain, MD5, Sender, SHA256, Subject, URL. |
Optional |
| threat_value | The actual value of the IOC match in the email. | Optional |
| threat_level | The severity of the IOC. Example: “Malicious”. |
Optional |
| source_id | The unique identifier assigned by the IOC source. Example: source1_id_00001. |
Optional |
| created_at | The UTC date and time, the IOC source included the IOC for the first time. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z. |
Optional |
| updated_at | The UTC date and time, the IOC source last updated the IOC. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z Default value will be the current UTC time. . |
Optional |
| requested_expiration | The expected UTC expiration date and time. The IOC repository calculates an expiration date and time for the new IOC by default 14 days after the IOC is delivered to the IOC repository. Supported formats: N minutes, N hours, N days, N weeks, N months, N years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ Example: 01 Mar 2021, 01 Feb 2021 04:45:33, 2022-04-17T14:05:44Z”. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | String that describes the severity of the threat. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source included the IOC for the first time. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time cofense vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time cofense vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.IOC.metadata.quarantine.wildcard | Boolean | Whether the wildcard matching is set (true) or not (false). |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-iocs-update source="Vision-UI" iocs_json="[{\"threat_type\":\"Domain\",\"threat_value\":\"test.com\",\"threat_level\":\"Malicious\",\"source_id\":\"test\",\"created_at\":\"1 day\",\"updated_at\":\"1 day\"}]"
Context Example
{
"Cofense": {
"IOC": {
"attributes": {
"threat_type": "DOMAIN",
"threat_value": "test.com"
},
"id": "bb78c7a2f8c9eea5b9c5a30eb8c9069b",
"metadata": {
"quarantine": {
"created_at": "2022-08-08T09:17:11.188+00:00",
"expired": false,
"expires_at": "2022-08-24T04:25:24.909+00:00",
"match_count": 0,
"quarantine_count": 0,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": {
"created_at": "2022-08-09T04:25:23.000+00:00",
"id": "test",
"requested_expiration": "2022-08-24T04:25:24.909+00:00",
"threat_level": "Malicious",
"updated_at": "2022-08-09T04:25:23.000+00:00"
}
},
"type": "ioc"
}
}
}
Human Readable Output
IOC bb78c7a2f8c9eea5b9c5a30eb8c9069b updated successfully
ID Threat Type Threat Value Threat Level Created At Updated At Requested Expiration bb78c7a2f8c9eea5b9c5a30eb8c9069b DOMAIN test.com Malicious 09/08/2022, 04:25 AM UTC 09/08/2022, 04:25 AM UTC 24/08/2022, 04:25 AM UTC
cofense-last-ioc-get
Synchronizes the update of data between the IOC source and the IOC repository. Retrieves the last updated IOC from the local IOC Repository. It may return an active or an expired IOC.
Base Command
cofense-last-ioc-get
Input
| Argument Name | Description | Required |
|---|---|---|
| source | A single IOC source value, to fetch the IOCs added or modified by that particular source. The value for source can contain uppercase letters, lowercase letters, numbers, and certain special characters (“.” , “-“ , “_” , “~”). Example: “Traige-1” or “IOC_Source-2”. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | String that describes the severity of the threat. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source included the IOC for the first time. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time cofense vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time cofense vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.IOC.metadata.quarantine.wildcard | Boolean | Whether the wildcard matching is set (true) or not (false). |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-last-ioc-get source="Vision-UI"
Context Example
{
"Cofense": {
"IOC": {
"attributes": {
"threat_type": "SUBJECT",
"threat_value": "test-subject"
},
"id": "bb931fec9d9672a9e307456133223b2e",
"metadata": {
"quarantine": {
"created_at": "2022-08-10T04:12:49.003+00:00",
"expired": false,
"expires_at": "2022-08-24T18:29:59.999+00:00",
"first_quarantined_at": "2022-08-10T04:12:49.424+00:00",
"last_quarantined_at": "2022-08-10T04:12:49.424+00:00",
"match_count": 1,
"quarantine_count": 10,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": {
"created_at": "2022-08-10T04:12:45.064+00:00",
"id": " ",
"requested_expiration": "2022-08-24T18:29:59.999+00:00",
"threat_level": "Low",
"updated_at": "2022-08-10T04:12:45.064+00:00"
}
},
"type": "ioc"
}
}
}
Human Readable Output
Last IOC
ID Threat Type Threat Value Created At Expires At Match Count Quarantine Count First Quarantined At Last Quarantined At bb931fec9d9672a9e307456133223b2e SUBJECT test-subject 10/08/2022, 04:12 AM UTC 24/08/2022, 06:29 PM UTC 1 10 10/08/2022, 04:12 AM UTC 10/08/2022, 04:12 AM UTC
cofense-ioc-delete
Deletes a single active or expired IOC from the local IOC Repository.
Base Command
cofense-ioc-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| source | A single IOC source value, to fetch the IOCs added or modified by that particular source. The value for source can contain uppercase letters, lowercase letters, numbers, and certain special characters (“.” , “-“ , “_” , “~”). Example: “Traige-1” or “IOC_Source-2”. |
Required |
| id | The ID of the IOC to be deleted. Note: Users can get the list of IDs by executing the “cofense-iocs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat type” and “threat value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | The threat level of the IOC. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source was first seen. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time the cofense vision quarantined the email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time the cofense vision last quarantined the email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of times the email was quarantined. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.IOC.deleted | Boolean | Indicates whether the IOC is deleted or not. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-ioc-delete source="Vision-UI" id=bb931fec9d9672a9e307456133223b2e
Context Example
{
"Cofense": {
"IOC": {
"attributes": {
"threat_type": "SUBJECT",
"threat_value": "test-subject"
},
"deleted": true,
"id": "bb931fec9d9672a9e307456133223b2e",
"metadata": {
"quarantine": {
"created_at": "2022-08-10T04:12:49.003+00:00",
"expired": false,
"expires_at": "2022-08-24T18:29:59.999+00:00",
"first_quarantined_at": "2022-08-10T04:12:49.424+00:00",
"last_quarantined_at": "2022-08-10T04:12:49.424+00:00",
"match_count": 1,
"quarantine_count": 10,
"source_names": [
"Vision-UI"
],
"wildcard": false
},
"source": {
"created_at": "2022-08-10T04:12:45.064+00:00",
"id": " ",
"requested_expiration": "2022-08-24T18:29:59.999+00:00",
"threat_level": "Low",
"updated_at": "2022-08-10T04:12:45.064+00:00"
}
},
"type": "ioc"
}
}
}
Human Readable Output
IOC with value “bb931fec9d9672a9e307456133223b2e” has been deleted successfully
ID Threat Type Threat Value Action Status bb931fec9d9672a9e307456133223b2e SUBJECT test-subject Success
cofense-ioc-get
Retrieves the IOC identified by its unique MD5 ID.
Base Command
cofense-ioc-get
Input
| Argument Name | Description | Required |
|---|---|---|
| source | A single IOC source value, to fetch the IOCs added or modified by that particular source. The value for source can contain uppercase letters, lowercase letters, numbers, and certain special characters (“.” , “-“ , “_” , “~”). Example: “Traige-1” or “IOC_Source-2”. |
Optional |
| id | The ID of the IOC. Note: Users can get the list of IDs by executing the “cofense-iocs-list” command. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.IOC.id | String | MD5 hash composed of the UTF-8 concatenation of “threat_type” and “threat_value” attributes. |
| Cofense.IOC.type | String | Type of the cofense resource which is always “ioc”. |
| Cofense.IOC.attributes.threat_type | String | Threat type of the IOC match. |
| Cofense.IOC.attributes.threat_value | String | Actual value of the IOC match in the email. |
| Cofense.IOC.metadata.source.threat_level | String | String that describes the severity of the threat. |
| Cofense.IOC.metadata.source.id | String | Unique identifier assigned by the IOC source. |
| Cofense.IOC.metadata.source.created_at | Date | Date and time the IOC source included the IOC for the first time. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.updated_at | Date | Date and time the IOC source last updated the IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.source.requested_expiration | Date | Expiration date and time for this IOC in UTC. |
| Cofense.IOC.metadata.quarantine.source_names | Unknown | Array containing the IOC sources. |
| Cofense.IOC.metadata.quarantine.expires_at | Date | Date and time, in UTC, after which this IOC expires. |
| Cofense.IOC.metadata.quarantine.created_at | Date | Date and time the quarantine data was created in the IOC repository. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.first_quarantined_at | Date | Date and time cofense vision quarantined the first email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.last_quarantined_at | Date | Date and time cofense vision quarantined the last email due to this IOC. The timestamp is in UTC. |
| Cofense.IOC.metadata.quarantine.match_count | Number | Number of unique emails that matched the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.quarantine_count | Number | Number of recipients who received emails matching the IOC while the IOC was active. |
| Cofense.IOC.metadata.quarantine.expired | Boolean | Whether the IOC is expired (true) or not expired (false). |
| Cofense.IOC.metadata.quarantine.wildcard | Boolean | Whether the wildcard matching is set (true) or not (false). |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| Domain.Name | String | The domain name. |
| Domain.Malicious.Description | String | A description of the malicious domain. |
| Domain.Malicious.Vendor | String | The vendor who reported the domain as malicious. |
| URL.Data | String | The URL. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Malicious.Vendor | String | The vendor who reported the URL as malicious. |
| Email.Address | String | The sender of the email. |
| Email.Malicious.Description | String | A description of the malicious email. |
| Email.Malicious.Vendor | String | The vendor who reported the email as malicious. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Malicious.Description | String | A description explaining why the file was determined to be malicious. |
| File.Malicious.Vendor | String | The vendor who reported the file as malicious. |
Command example
!cofense-ioc-get source="Vision-UI" id=bb931fec9d9672a9e307456133223b2e
Context Example
{
"Cofense": {
"IOC": {
"id": "0c7aff000d37b4a600eb676a473fa5b1",
"type": "ioc",
"attributes": {
"threat_type": "DOMAIN",
"threat_value": "test"
},
"metadata": {
"source": {
"threat_level": "minor",
"id": "test",
"created_at": "2022-12-09T00:00:00.000+00:00",
"updated_at": "2022-09-12T06:55:56.000+00:00",
"requested_expiration": "2022-09-26T06:55:57.305+00:00"
},
"quarantine": {
"source_names": [
"Vision-UI"
],
"expires_at": "2022-09-26T06:55:57.305+00:00",
"created_at": "2022-09-12T06:55:57.305+00:00",
"first_quarantined_at": null,
"last_quarantined_at": null,
"match_count": 0,
"quarantine_count": 0,
"expired": false,
"wildcard": false
}
}
}
}
}
Human Readable Output
IOC
ID Threat Type Threat Value Created At Expires At 0c7aff000d37b4a600eb676a473fa5b1 DOMAIN test 12/09/2022, 06:55 AM UTC 26/09/2022, 06:55 AM UTC
cofense-searchable-headers-get
Retrieves a list of configured header keys that can be used to create a message search.
Base Command
cofense-searchable-headers-get
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Config.name | String | Name of the configuration which is ‘searchableHeaders’. |
| Cofense.Config.value | Unknown | List of headers that are available to create a message search. |
Command example
#### Context Example
```json
{
"Cofense": {
"Config": {
"name": "searchableHeaders",
"value": [
"X-MS-Exchange-Organization-AuthSource"
]
}
}
}
Human Readable Output
Available headers to create a search
Headers X-MS-Exchange-Organization-AuthSource
Configuration parameters
url— Server URL (required)credentials— Client ID (required)threat_levels_good— Threat levels to be marked as Goodthreat_levels_suspicious— Threat levels to be marked as Suspiciousthreat_levels_bad— Threat levels to be marked as Badinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (22)
-
cofense-ioc-deleteDeletes a single active or expired IOC from the local IOC Repository.
-
cofense-ioc-getRetrieves the IOC identified by its unique MD5 ID.
-
cofense-ioc-updateUpdates the IOC identified by its unique MD5 ID.
-
cofense-iocs-listLists the IOCs stored in the local IOC Repository.
-
cofense-iocs-updateUpdates one or more IOCs stored in the local IOC repository. To update multiple IOCs use iocs_json argument. Note: iocs_json parameter will take precedence over other parameters. threat_type, threat_value, threat_level, created_at and source_id are required parameters to update a single IOC.
-
cofense-last-ioc-getSynchronizes the update of data between the IOC source and the IOC repository. Retrieves the last updated IOC from the local IOC Repository. It may return an active or an expired IOC.
-
cofense-message-attachment-getFetches the full content of an email and returns a zip file.
-
cofense-message-getFetches full content of an email and returns it as a zip file using a token.
-
cofense-message-metadata-getRetrieves the full content of a message that matches the specified Internet message ID and recipient email address of an email.
-
cofense-message-search-createCreates a new search.
-
cofense-message-search-getRetrieves the result of the search identified by an ID.
-
cofense-message-search-results-getRetrieves the results for the search identified by the search ID.
-
cofense-message-searches-listRetrieves the list of searches.
-
cofense-message-token-getRetrieves a one-time token that can be used to get an email's content.
-
cofense-quarantine-job-approveApproves the quarantine job identified by its unique ID. When the "Auto Quarantine" feature is configured which requires manual approvals, this command can approve all the pending quarantine jobs.
-
cofense-quarantine-job-createCreates a new quarantine job.
-
cofense-quarantine-job-deleteDeletes the quarantine job identified by its unique ID.
-
cofense-quarantine-job-getRetrieves quarantine job identified by its unique ID.
-
cofense-quarantine-job-restoreRestores emails quarantined by the job identified by its unique ID.
-
cofense-quarantine-job-stopIssues a request to stop the quarantine job identified by its unique ID.
-
cofense-quarantine-jobs-listFilters and returns a paginated list of matching quarantine jobs.
-
cofense-searchable-headers-listRetrieves a list of configured header keys that can be used to create a message search.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """Implementation file for Cofense Vision Integration.""" import traceback from collections.abc import Callable from typing import Any import urllib3 from requests import Response from CommonServerUserPython import * # noqa # Disable insecure warnings urllib3.disable_warnings() """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR HR_DATE_FORMAT = "%m/%d/%Y, %I:%M %p %Z" API_SUFFIX = "/api/v4" API_ENDPOINTS = { "AUTHENTICATION": "/uaa/oauth/token", "GET_ALL_SEARCHES": API_SUFFIX + "/searches", "GET_ATTACHMENT": API_SUFFIX + "/attachment", "GET_MESSAGE": API_SUFFIX + "/messages", "GET_MESSAGE_METADATA": API_SUFFIX + "/messages/metadata", "GET_QUARANTINE_JOBS": API_SUFFIX + "/quarantineJobs/filter", "GET_MESSAGE_TOKEN": API_SUFFIX + "/messages", "QUARANTINE_JOB": API_SUFFIX + "/quarantineJobs", "RESTORE_QUARANTINE_JOB": API_SUFFIX + "/quarantineJobs/{}/restore", "GET_MESSAGE_SEARCH": API_SUFFIX + "/searches/{}", "APPROVE_QUARANTINE_JOB": API_SUFFIX + "/quarantineJobs/{}/approve", "GET_SEARCH_RESULTS": API_SUFFIX + "/searches/{}/results", "IOC_REPOSITORY": "/iocrepository/v1/iocs", "STOP_QUARANTINE_JOB": API_SUFFIX + "/quarantineJobs/{}/stop", "CREATE_MESSAGE_SEARCH": API_SUFFIX + "/searches", "GET_LAST_IOC": "/iocrepository/v1/iocs/last", "GET_IOCS": "/iocrepository/v1/iocs", "GET_SEARCHABLE_HEADERS": API_SUFFIX + "/config/searchableHeaders", } ERROR_MESSAGE = { "INVALID_FORMAT": "{} is an invalid format for {}. Supported format is: {}", "INVALID_PAGE_VALUE": "Page number must be a non-zero and positive numeric value.", "INVALID_PAGE_SIZE_RANGE": "Page size should be in the range from 1 to 2000.", "UNSUPPORTED_FIELD": "{} is not a supported value for {}. Supported values for {} are: {}.", "UNSUPPORTED_FIELD_FOR_IOCS_LIST": "{} is not a supported value for {}. Supported value for {} is: {}.", "INVALID_REQUIRED_PARAMETER_HASH": "At least one of the hash values (md5 or sha256) is required.", "INVALID_ARGUMENT": "{} is an invalid value for {}.", "MISSING_REQUIRED_PARAM": "{} is a required parameter. Please provide correct value.", "INVALID_QUARANTINE_JOB_PARAM": "{} must be a non-zero positive integer number.", "INVALID_SEARCH_ID": "ID must be a non-zero positive integer number.", "INVALID_QUARANTINE_JOB_ID": "Quarantine Job ID must be a non-zero positive integer number.", "INVALID_SEARCH_LENGTH": "Maximum 3 values are allowed to create a search for {} parameter.", } IOC_TYPES = { "domain": DBotScoreType.DOMAIN, "md5": DBotScoreType.FILE, "sender": DBotScoreType.EMAIL, "sha256": DBotScoreType.FILE, "subject": DBotScoreType.CUSTOM, "url": DBotScoreType.URL, } SUPPORTED_HASH = ["MD5", "SHA256"] SUPPORTED_CRITERIA = ["ANY", "ALL"] SUPPORTED_HASH_VALUE_FORMAT = "hashtype1:hashvalue1,hashtype2:hashvalue2" SUPPORTED_QUARANTINE_EMAILS_FORMAT = "internetMessageID1:recipientAddress1,internetMessageID2:recipientAddress2" SUPPORTED_HEADERS_FORMAT = "key1:value1,key2:value1:value2:value3" SUPPORTED_SORT_FORMAT = "propertyName1:sortOrder1,propertyName2:sortOrder2" SUPPORTED_SORT_FORMAT_FOR_IOCS_LIST = "propertyName:sortOrder" STATUS = ["NEW", "PENDING_APPROVAL", "QUEUED", "RUNNING", "COMPLETED", "FAILED"] THREAT_TYPES = ["domain", "md5", "sender", "sha256", "subject", "url"] SUPPORTED_SORT = { "order_by": ["asc", "desc"], "quarantine_jobs_list": ["id", "createdBy", "createdDate", "modifiedBy", "modifiedDate", "stopRequested"], "message_searches_list": [ "id", "createdBy", "createdDate", "modifiedBy", "modifiedDate", "receivedAfterDate", "receivedBeforeDate", ], "message_search_result_get": ["id", "subject", "createdOn", "sentOn", "htmlBody", "md5", "sha1", "sha256"], "iocs_list": ["updatedAt"], } MAX_PAGE_SIZE = 2000 SPECIAL_CHARACTERS_MARKDOWN = [ "#", "*", "`", "<", ">", "_", "-", "(", ")", "[", "]", "!", "+", ".", "{", "}", "~", "=", "|", "\\", ] DEFAULT_SORT_VALUE = "id:asc" RECEIVED_ON = "Received On" SENT_ON = "Sent On" INTERNET_MESSAGE_ID = "Internet Message ID" MATCHING_IOCS = "Matching IOCs" MATCHING_SOURCES = "Matching Sources" CREATED_BY = "Created By" CREATED_DATE = "Created Date" MODIFIED_BY = "Modified By" MODIFIED_DATE = "Modified Date" SEARCH_ID = "Search ID" LAST_MODIFIED_BY = "Last Modified By" LAST_MODIFIED_DATE = "Last Modified Date" LAST_ACTION = "Last Action" COMPLETED_DATE = "Completed Date" THREAT_TYPE = "Threat Type" THREAT_VALUE = "Threat Value" THREAT_LEVEL = "Threat Level" CREATED_AT = "Created At" UPDATED_AT = "Updated At" EXPIRES_AT = "Expires At" MATCH_COUNT = "Match Count" QUARANTINE_COUNT = "Quarantine Count" FIRST_QUARANTINED_AT = "First Quarantined At" LAST_QUARANTINE_AT = "Last Quarantined At" QUARANTINE_JOB_OUTPUT_PREFIX = "Cofense.QuarantineJob" SEARCH_OUTPUT_PREFIX = "Cofense.Search" IOC_OUTPUT_PREFIX = "Cofense.IOC" ATTACHMENT_FILE_NAMES = "Attachment File Names" INCLUDED_MIME_TYPES = "Included MIME Types" EXCLUDED_MIME_TYPES = "Excluded MIME Types" HASH_TYPE = "Hash Type" WHITELIST_URLS = "Whitelist URLs" DATE_RANGE = "Date Range" HEADERS = "Header Key/Value" PARTIAL_INGEST = "Partial Ingest" APPLICATION_JSON = "application/json" """ CLIENT CLASS """ class VisionClient(BaseClient): """Client class to interact with the service API.""" def __init__( self, base_url: str, client_id: str, client_secret: str, verify: bool, proxy: bool, threat_levels_good: list, threat_levels_suspicious: list, threat_levels_bad: list, ) -> None: """ Prepare constructor for Client class. Calls the constructor of BaseClient class and updates the header with the authentication token. Args: base_url (str): The url of Cofense Vision instance. client_id (str): The Client ID to use for authentication. client_secret (str): The Client Secret to use for authentication. verify (bool): True if verify SSL certificate is checked in integration configuration, False otherwise. proxy (bool): True if proxy is checked in integration configuration, False otherwise. threat_levels_good (list): List of threat levels provided by user to map DbotScore as Good. threat_levels_suspicious (list): List of threat levels provided by user to map DbotScore as Suspicious. threat_levels_bad(list): List of threat levels provided by user to map DbotScore as Bad. """ super().__init__(base_url=base_url, verify=verify, proxy=proxy) # Setting up access token in headers. self._headers: dict[str, Any] = { "Authorization": f"Bearer {self.get_access_token(client_id=client_id, client_secret=client_secret)}" } self.threat_levels_good = [level.lower() for level in threat_levels_good] + ["low"] self.threat_levels_suspicious = [level.lower() for level in threat_levels_suspicious] + [ "suspicious", "moderate", "substantial", ] self.threat_levels_bad = [level.lower() for level in threat_levels_bad] + ["malicious", "severe", "critical", "high"] def authenticate(self, client_id: str, client_secret: str) -> tuple[str, int]: """ Get the access token from the Cofense API. Args: client_id (str): The Client ID to use for authentication. client_secret (str): The Client Secret to use for authentication. Returns: tuple[str,int]: The token and its expiration time in seconds received from the API. """ demisto.info("[CofenseVision] Generating new authentication token.") req_headers = { "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", } req_body = { "grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret, } response = self._http_request( method="POST", url_suffix=API_ENDPOINTS["AUTHENTICATION"], data=req_body, headers=req_headers, error_handler=error_handler, ) token = response.get("access_token") expires_in = response.get("expires_in") return token, expires_in def get_access_token(self, client_id: str, client_secret: str) -> str: """Return the token stored in integration context. If the token has expired or is not present in the integration context (in the first case), it calls the Authentication function, which generates a new token and stores it in the integration context. Args: client_id (str): The Client ID to use for authentication. client_secret (str): The Client Secret to use for authentication. Returns: str: Authentication token stored in integration context. """ integration_context = get_integration_context() token = integration_context.get("access_token") valid_until = integration_context.get("valid_until") time_now = int(time.time()) # If token exists and is valid, then return it. if (token and valid_until) and (time_now < valid_until): demisto.info("[CofenseVision] Token returned from integration context.") return token # Otherwise, generate a new token and store it. token, expires_in = self.authenticate(client_id=client_id, client_secret=client_secret) integration_context = { "access_token": token, "valid_until": time_now + expires_in, # Token expiration time - 30 mins } set_integration_context(integration_context) return token def get_attachment(self, md5: str | None = None, sha256: str | None = None) -> Response: """Get an attachment of an email from API. Args: md5(Optional[str]): MD5 hash of attachment file. sha256(Optional[str]): SHA256 hash of an attachment. Returns: Response: Response from API. """ params = assign_params(md5=md5, sha256=sha256) return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_ATTACHMENT"], resp_type="Response", params=params, error_handler=error_handler, ) def get_message(self, token: str) -> Response: """Get the message zip file, which contains the email's content. Args: token(str): One time token to access email content. Returns: Response: Response from API. """ return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_MESSAGE"], resp_type="response", params={"token": token}, error_handler=error_handler, ) def get_message_metadata(self, internet_message_id: str, recipient_address: str) -> dict[str, Any]: """Get content of message that matches specified ID and Recipient Address. Args: internet_message_id(str): ID of an email assigned by the message transfer agent. recipient_address(str): Email address of the recipient of an email. Returns: Dict[str, Any]: Response from API. """ params = assign_params(internetMessageId=internet_message_id, recipientAddress=recipient_address) return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_MESSAGE_METADATA"], params=params, error_handler=error_handler ) def get_message_token(self, internet_message_id: str, recipient_address: str, password: str = None) -> str: """Retrieve the one time message token from the Cofense Vision API. Args: internet_message_id (str): Unique identifier of the email address. recipient_address (str): Email address of the recipient of the email. password (str, optional): Password to protect the zip file containing the email. Defaults to None. Returns: str: One time token """ req_data = assign_params(internetMessageId=internet_message_id, recipientAddress=recipient_address, password=password) return self._http_request( method="POST", url_suffix=API_ENDPOINTS["GET_MESSAGE_TOKEN"], json_data=req_data, resp_type="text", error_handler=error_handler, ) def quarantine_jobs_list( self, page: int | None, size: int | None, sort: str, exclude_quarantine_emails: bool, body: dict ) -> dict[str, Any]: """Get quarantine jobs. Args: page: Page offset to start listing quarantine jobs from. size: The number of results to retrieve per page. sort: The name-value pair defining the order of the response. exclude_quarantine_emails: Whether to remove or not remove quarantined emails from the response. body: Body to send in API call. Returns: Dict: Response from API. """ query = f"?page={page}&size={size}&excludeQuarantineEmails={exclude_quarantine_emails}&{sort}" return self._http_request( method="POST", url_suffix=API_ENDPOINTS["GET_QUARANTINE_JOBS"] + query, json_data=body, error_handler=error_handler ) def delete_quarantine_job(self, job_id: str): """Delete the quarantine job specified by the user. Args: job_id: ID of the quarantine job to delete. """ self._http_request( method="DELETE", url_suffix=API_ENDPOINTS["QUARANTINE_JOB"] + "/" + str(job_id), empty_valid_codes=[200], return_empty_response=True, error_handler=error_handler, ) def create_quarantine_job(self, requests_body: dict[str, Any]) -> dict[str, Any]: """Create a quarantine job using internet message id and recipient's address of emails. Args: requests_body(Dict[str, Any]): Required body parameter. Returns: Dict[str, Any]: Response from API. """ headers = {"Content-Type": APPLICATION_JSON, **self._headers} return self._http_request( method="POST", url_suffix=API_ENDPOINTS["QUARANTINE_JOB"], headers=headers, json_data=requests_body, error_handler=error_handler, ) def create_search(self, requests_body: dict[str, Any]) -> dict[str, Any]: """Create a new search based on user specified arguments. Args: requests_body(Dict[str, Any]): Required body parameter to create a search. Returns: Dict[str, Any]: Response from API. """ return self._http_request( method="POST", url_suffix=API_ENDPOINTS["CREATE_MESSAGE_SEARCH"], json_data=requests_body, error_handler=error_handler ) def get_search(self, search_id: int) -> dict[str, Any]: """Get Search using search id provided by cofense vision. Args: search_id(int): search id provided by cofense vision. Returns: Dict[str, Any]: Response from API. """ return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_MESSAGE_SEARCH"].format(search_id), error_handler=error_handler ) def restore_quarantine_job(self, id: str) -> None: """Restore the emails quarantined by the job identified by id. Args: id (str): The id of the quarantine job. """ self._http_request( method="PUT", url_suffix=API_ENDPOINTS["RESTORE_QUARANTINE_JOB"].format(id), return_empty_response=True, empty_valid_codes=(200,), error_handler=error_handler, ) def list_searches(self, page: int = None, size: int = None, sort: str = None) -> dict[str, Any]: """List message searches. Args: page(int): Page offset to start listing quarantine jobs from. size(int): The number of results to retrieve per page. sort(str): The name-value pair defining the order of the response. Returns: Dict[str, Any]: Response from API. """ query = f"?page={page}&size={size}&{sort}" return self._http_request(method="GET", url_suffix=API_ENDPOINTS["GET_ALL_SEARCHES"] + query, error_handler=error_handler) def get_quarantine_job(self, job_id: str) -> dict[str, Any]: """Get the quarantine job with specified ID. Args: job_id: ID of an quarantine job. Returns: Dict: Response from API. """ return self._http_request( method="GET", url_suffix=API_ENDPOINTS["QUARANTINE_JOB"] + "/" + str(job_id), error_handler=error_handler ) def approve_quarantine_job(self, id: str, message_count: int = None) -> None: """Approve the quarantine job identified by its unique ID. Args: id (str): The unique ID of the quarantine job. message_count (int): The number of messages to approve. """ params = assign_params(messageCount=message_count) self._http_request( method="PUT", url_suffix=API_ENDPOINTS["APPROVE_QUARANTINE_JOB"].format(id), params=params, return_empty_response=True, empty_valid_codes=[200], error_handler=error_handler, ) def get_search_results(self, search_id: int, page: int = None, size: int = None, sort: str = None) -> dict[str, Any]: """List message searches. Args: search_id(int): ID of the search to retrieve result. page(int): Page offset to start listing quarantine jobs from. size(int): The number of results to retrieve per page. sort(str): The name-value pair defining the order of the response. Returns: Dict[str, Any]: Response from API. """ query = f"?page={page}&size={size}&{sort}" return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_SEARCH_RESULTS"].format(search_id) + query, error_handler=error_handler ) def delete_ioc(self, source, ioc_id): """Delete an IOC identified by hash value and specified source. Args: source: The source which ingested the IOC. ioc_id: ID as hash of the IOC to delete. Returns: Dict[str, Any]: Response from API. """ headers = {"X-Cofense-IOC-Source": source, **self._headers} return self._http_request( method="DELETE", url_suffix=API_ENDPOINTS["IOC_REPOSITORY"] + "/" + str(ioc_id), headers=headers, error_handler=error_handler, ) def stop_quarantine_job(self, id: str) -> dict[str, Any]: """Stop the quarantine job identified by the given id. Args: id (str): ID of the quarantine job to be stopped. Returns: dict[str, Any]: Response from API. """ return self._http_request( method="PUT", url_suffix=API_ENDPOINTS["STOP_QUARANTINE_JOB"].format(id), error_handler=error_handler ) def get_last_ioc(self, source: str) -> dict[str, Any]: """Get the last updated IOC from ioc-source. Args: source(str): IOC source to fetch last updated ioc. Returns: Dict[str, Any]: Response from API. """ headers = {"X-Cofense-IOC-Source": source, **self._headers} return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_LAST_IOC"], headers=headers, error_handler=error_handler ) def update_iocs(self, source, body) -> dict[str, Any]: """Update the IOC with specified source and ID. Args: source: Source of the IOC to update. body: The json_data to pass in API call. Returns: Dict: Response from API. """ headers = {"Content-Type": APPLICATION_JSON, "X-Cofense-IOC-Source": source, **self._headers} return self._http_request( method="PUT", url_suffix=API_ENDPOINTS["IOC_REPOSITORY"], headers=headers, json_data=body, error_handler=error_handler ) def update_ioc(self, md5_id, body) -> dict[str, Any]: """Update the IOC with specified ID. Args: md5_id: ID as hash of the IOC to update. body: The json_data to pass in API call. Returns: Dict: Response from API. """ headers = {"Content-Type": APPLICATION_JSON, **self._headers} return self._http_request( method="PUT", url_suffix=API_ENDPOINTS["IOC_REPOSITORY"] + "/" + str(md5_id), headers=headers, json_data=body, error_handler=error_handler, ) def list_iocs( self, source: str, page: int, size: int, include_expired: bool, since: str | None, sort_string: str | None ) -> dict[str, Any]: """List the IOCs from the source given by the user. Args: source (str): The name of the source. page (int): The page offset to start listing IOCs from. size (int): The number of results to retrieve per page. include_expired (bool): Whether to include expired IOCs or not. since (str): List the IOCs added after this particular date. sort_string (str): The name-value pair defining the order of the response. Returns: (dict[str, Any]): Response from the API. """ headers = {"X-Cofense-IOC-Source": source, **self._headers} query = f"?page={page}&size={size}&includeExpired={include_expired}" if since: query += f"&since={since}" if sort_string: query += f"&{sort_string}" return self._http_request( method="GET", url_suffix=API_ENDPOINTS["GET_IOCS"] + query, headers=headers, error_handler=error_handler ) def get_ioc(self, source, ioc_id): """Get an IOC identified by hash value. Args: source: The source which ingested the IOC. ioc_id: ID as hash of the IOC. Returns: Dict[str, Any]: Response from API. """ headers = {"X-Cofense-IOC-Source": source, **self._headers} return self._http_request( method="GET", url_suffix=API_ENDPOINTS["IOC_REPOSITORY"] + "/" + str(ioc_id), headers=headers, error_handler=error_handler, ) def list_searchable_headers(self) -> dict[str, Any]: """Get list of searchable header keys. Returns: Dict[str, Any]: Response from API. """ return self._http_request(method="GET", url_suffix=API_ENDPOINTS["GET_SEARCHABLE_HEADERS"], error_handler=error_handler) """ HELPER FUNCTIONS """ def trim_spaces_from_args(args: dict) -> dict: """Trim spaces from values of the args dict. Args: args(Dict): Dict to trim spaces from. Returns: Dict: Arguments after trim spaces. """ for key, val in args.items(): if isinstance(val, str): args[key] = val.strip() return args def error_handler(response: Response): """Error Handler function. Args: response(Response): Response object from API. """ err_msg = f"Error in API call [{response.status_code}]." try: error_entry = response.json() if response.status_code == 401: err_msg += "\n{} : {}.".format(error_entry.get("error"), error_entry.get("error_description")) else: err_msg += "\n{} : {}.".format(error_entry.get("status"), ". ".join(error_entry.get("details", []))) raise DemistoException(err_msg, res=response) except ValueError: err_msg += f"\n{response.text}" raise DemistoException(err_msg, res=response) def arg_to_list_with_filter_null_values(argument: Any | None) -> List: """Filter Null values from and convert string of args to python list. Args: argument: Argument provided by user. Returns: List: List of arguments. """ list_of_args: List = list(filter(None, argToList(argument))) return list(filter(None, arg_to_list(list_of_args))) def arg_to_list(argument: Any | None) -> List: """Convert a string representation of args to a python list. Args: argument: Argument provided by user. Returns: List: List of arguments. """ list_of_args = argToList(argument) arguments = [] arg = "" for argument in list_of_args: if argument and isinstance(argument, str): if argument[-1] != "\\": arguments.append(arg + argument) arg = "" else: arg += argument.replace("\\", ",") else: arguments.append(argument) if arg: arguments.append(arg) return arguments def validate_required_parameters(**kwargs) -> None: """ Raise an error for a required parameter. Enter your required parameters as keyword arguments to check whether they hold a value or not. Args: **kwargs: keyword arguments to check the required values for. Raises: ValueError: if the value of the parameter is "", [], (), {}, None. """ for key, value in kwargs.items(): if not value: raise ValueError(ERROR_MESSAGE["MISSING_REQUIRED_PARAM"].format(key)) def validate_quarantine_job_id(id: str): """ Validate the quarantine job id. Checks whether the provided id is a valid non-zero positive integer number or not. Args: id (str): Quarantine job id to validate. Raises: ValueError: If job id is negative or zero integer number. """ validate_required_parameters(id=id) if arg_to_number(id, arg_name="id") <= 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_QUARANTINE_JOB_PARAM"].format("id")) def validate_params_for_attachment_get(md5: str | None = None, sha256: str | None = None): """Validate arguments for cofense-message-attachment-get command. Args: md5(Optional[str]): MD5 hash of attachment file. sha256(Optional[str]): SHA256 hash of an attachment. """ if not md5 and not sha256: raise ValueError(ERROR_MESSAGE["INVALID_REQUIRED_PARAMETER_HASH"]) if md5 and get_hash_type(md5) != "md5": raise ValueError(ERROR_MESSAGE["INVALID_ARGUMENT"].format(md5, "md5 hash")) if sha256 and get_hash_type(sha256) != "sha256": raise ValueError(ERROR_MESSAGE["INVALID_ARGUMENT"].format(sha256, "sha256 hash")) def escape_special_characters(hr_dict: dict) -> dict: """Escape special characters to show in hr output. Args: hr_dict(Dict): Dictionary of human-readable response. Returns: Dict: human-readable response with escaped special characters. """ hr_output = {} for key, value in hr_dict.items(): if isinstance(value, str): hr_output[key] = "".join(["\\" + str(char) if char in SPECIAL_CHARACTERS_MARKDOWN else str(char) for char in value]) elif isinstance(value, list): hr_output[key] = [] # type: ignore for element in value: hr_output[key].append( # type: ignore[attr-defined] "".join( # type: ignore ["\\" + str(char) if char in SPECIAL_CHARACTERS_MARKDOWN else str(char) for char in element] ) ) else: hr_output[key] = value return hr_output def prepare_hr_for_message_metadata_get(message: dict[str, Any]) -> str: """Prepare Human Readable for cofense-message-metadata-get command. Args: message(Dict[str, Any]: Message response from API. Returns: str: Human readable output. """ hr_outputs = escape_special_characters( { "ID": message.get("id"), "Subject": message.get("subject"), RECEIVED_ON: None if not message.get("receivedOn") else arg_to_datetime(message.get("receivedOn")).strftime(HR_DATE_FORMAT), # type: ignore SENT_ON: None if not message.get("sentOn") else arg_to_datetime(message.get("sentOn")).strftime(HR_DATE_FORMAT), # type: ignore "Delivered On": None if not message.get("deliveredOn") else arg_to_datetime(message.get("deliveredOn")).strftime(HR_DATE_FORMAT), # type: ignore "Processed On": None if not message.get("processedOn") else arg_to_datetime(message.get("processedOn")).strftime(HR_DATE_FORMAT), # type: ignore "Sender": [sender.get("address") for sender in message.get("from", [])], "Recipients": [recipient.get("address") for recipient in message.get("recipients", [])], "MD5": message.get("md5"), "SHA1": message.get("sha1"), "SHA256": message.get("sha256"), INTERNET_MESSAGE_ID: message.get("internetMessageId"), MATCHING_IOCS: message.get("matchingIOCs"), MATCHING_SOURCES: message.get("matchingSources"), } ) headers = [ "ID", "Subject", RECEIVED_ON, SENT_ON, "Delivered On", "Processed On", "Sender", "Recipients", "MD5", "SHA1", "SHA256", INTERNET_MESSAGE_ID, MATCHING_IOCS, MATCHING_SOURCES, ] return tableToMarkdown("Message Metadata:", hr_outputs, headers=headers, removeNull=True) def prepare_hr_for_message_token_get(response: dict[str, Any]) -> str: """Prepare human-readable string for cofense-message-token-get command. Args: response (Dict[str, Any]): Response from the command function. Returns: str: Human readable string. """ hr_outputs = escape_special_characters( { INTERNET_MESSAGE_ID: response.get("internetMessageId"), "Recipient's Address": response.get("recipient", {}).get("address"), "Token": response.get("token"), } ) headers = [INTERNET_MESSAGE_ID, "Recipient's Address", "Token"] return tableToMarkdown("One-time token:", hr_outputs, headers=headers, removeNull=True) def validate_sort(sort_list: list, command: str): """Check for valid property name and sort order. Args: sort_list(List): List of PropertyName:Order for sorting results. command(str): Command name for sort. """ for sort_by in sort_list: # Checking whether the format is correct or not. if len(list(filter(None, sort_by.split(":")))) != 2: sort_by = sort_by if sort_by else "None" raise ValueError( ERROR_MESSAGE["INVALID_FORMAT"].format( sort_by, "sort", SUPPORTED_SORT_FORMAT_FOR_IOCS_LIST if command == "iocs_list" else SUPPORTED_SORT_FORMAT ) ) property_name, sort_order = sort_by.split(":") # Checking whether the property name and sort order values are correct or not. if (property_name[0].lower() + property_name[1:]) not in SUPPORTED_SORT[command]: message = ( ERROR_MESSAGE["UNSUPPORTED_FIELD_FOR_IOCS_LIST"] if command == "iocs_list" else ERROR_MESSAGE["UNSUPPORTED_FIELD"] ) raise ValueError(message.format(property_name, "property name", "property name", ", ".join(SUPPORTED_SORT[command]))) if sort_order.lower() not in SUPPORTED_SORT["order_by"]: raise ValueError( ERROR_MESSAGE["UNSUPPORTED_FIELD"].format( sort_order, "sort order", "sort order", ", ".join(SUPPORTED_SORT["order_by"]) ) ) def validate_page_size(page_size: int | None): """Validate that page size parameter is in numeric format or not. Args: page_size: This value will be checked to be numeric and within range. """ if not page_size or not str(page_size).isdigit() or int(page_size) <= 0 or int(page_size) > MAX_PAGE_SIZE: raise ValueError(ERROR_MESSAGE["INVALID_PAGE_SIZE_RANGE"]) def prepare_sort_query(sort_list: list, command: str) -> str: """Prepare sort query for list commands. Args: sort_list: List of PropertyName:Order for sorting results. command(str): Command name for sort. Returns: str: sort query to append in url. """ validate_sort(sort_list, command) sort_by = "" for sort_property_order in sort_list: sort_by += "sort=" + sort_property_order + "&" sort_by = sort_by[:-1] sort_by = sort_by.replace(":", ",") return sort_by def prepare_hr_for_message_searches_list(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-message-searches-list command. Args: response(Dict[str, Any]: Message response from API. Returns: str: Human readable output. """ hr_output = [] for search in response.get("searches", []): received_before_date = ( None if not response.get("receivedBeforeDate") else arg_to_datetime(response.get("receivedBeforeDate")).strftime(HR_DATE_FORMAT) # type: ignore ) received_after_date = ( None if not response.get("receivedAfterDate") else arg_to_datetime(response.get("receivedAfterDate")).strftime(HR_DATE_FORMAT) # type: ignore ) date_range = "" if received_after_date: date_range = date_range + f"From: {received_after_date}\n" if received_before_date: date_range = date_range + f"To: {received_before_date}" hr_output.append( escape_special_characters( { "ID": search.get("id"), CREATED_BY: search.get("createdBy"), CREATED_DATE: None if not search.get("createdDate") else arg_to_datetime(search.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore MODIFIED_BY: search.get("modifiedBy"), MODIFIED_DATE: None if not search.get("modifiedDate") else arg_to_datetime(search.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore "Senders": search.get("senders"), "Recipient": search.get("recipient"), "Subjects": search.get("subjects"), ATTACHMENT_FILE_NAMES: search.get("attachmentNames"), INCLUDED_MIME_TYPES: search.get("attachmentMimeTypes"), EXCLUDED_MIME_TYPES: search.get("attachmentExcludeMimeTypes"), HASH_TYPE: [ f"{attachmentHashes.get('hashType')}-{attachmentHashes.get('hashString')}" for attachmentHashes in search.get("attachmentHashCriteria", {}).get("attachmentHashes", []) ], "Domains": search.get("domainCriteria", {}).get("domains"), WHITELIST_URLS: search.get("domainCriteria", {}).get("whiteListUrls"), DATE_RANGE: date_range, "URL": search.get("url"), HEADERS: [f"{header.get('key')}: {header.get('values')}" for header in search.get("headers", [])], INTERNET_MESSAGE_ID: search.get("internetMessageId"), PARTIAL_INGEST: search.get("partialIngest"), } ) ) headers = [ "ID", CREATED_BY, CREATED_DATE, MODIFIED_BY, MODIFIED_DATE, "Senders", "Recipient", "Subjects", ATTACHMENT_FILE_NAMES, INCLUDED_MIME_TYPES, EXCLUDED_MIME_TYPES, HASH_TYPE, "Domains", WHITELIST_URLS, DATE_RANGE, "URL", HEADERS, INTERNET_MESSAGE_ID, PARTIAL_INGEST, ] return tableToMarkdown("Message Searches:", hr_output, headers, removeNull=True) def prepare_body_for_qurantine_jobs_list_command(args: dict[str, Any]) -> dict: """Prepare body to be passed in API request for cofense_quarantine_jobs_list_command. Args: args: Arguments provided by user. Returns: Dict: Body for API request. """ filter_options = {} if args.get("auto_quarantine"): filter_options["autoQuarantine"] = argToBoolean(args.get("auto_quarantine")) if args.get("include_status"): filter_options["includeStatus"] = arg_to_list(args.get("include_status")) for status in filter_options["includeStatus"]: if status not in STATUS: raise ValueError(ERROR_MESSAGE["UNSUPPORTED_FIELD"].format(status, "status", "status", ", ".join(STATUS))) if args.get("exclude_status"): filter_options["excludeStatus"] = arg_to_list(args.get("exclude_status")) for status in filter_options["excludeStatus"]: if status not in STATUS: raise ValueError(ERROR_MESSAGE["UNSUPPORTED_FIELD"].format(status, "status", "status", ", ".join(STATUS))) if args.get("iocs"): filter_options["iocs"] = arg_to_list(args.get("iocs")) if args.get("modified_date_after"): filter_options["modifiedDateAfter"] = arg_to_datetime(args.get("modified_date_after"), arg_name="modified_date_after") filter_options["modifiedDateAfter"] = filter_options["modifiedDateAfter"].strftime(DATE_FORMAT) # type: ignore if args.get("sources"): filter_options["sources"] = arg_to_list(args.get("sources")) return {"filterOptions": filter_options} def prepare_hr_for_quarantine_jobs_list(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-quarantine_jobs_list command. Args: response: Message response from API. Returns: str: Human readable output. """ hr_outputs = [] for quarantine_job in response.get("quarantineJobs", []): hr_outputs.append( escape_special_characters( { "ID": quarantine_job.get("id"), SEARCH_ID: quarantine_job.get("searchId"), CREATED_BY: quarantine_job.get("createdBy"), CREATED_DATE: None if not quarantine_job.get("createdDate") else arg_to_datetime(quarantine_job.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore LAST_MODIFIED_BY: quarantine_job.get("modifiedBy"), LAST_MODIFIED_DATE: None if not quarantine_job.get("modifiedDate") else arg_to_datetime(quarantine_job.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore LAST_ACTION: quarantine_job.get("quarantineJobRuns", [])[-1].get("jobRunType"), "Status": quarantine_job.get("quarantineJobRuns", [])[-1].get("status"), COMPLETED_DATE: None if not quarantine_job.get("quarantineJobRuns", [])[-1].get("completedDate") else arg_to_datetime(quarantine_job.get("quarantineJobRuns", [])[-1].get("completedDate")).strftime( # type: ignore HR_DATE_FORMAT ), "Messages": quarantine_job.get("emailCount"), MATCHING_IOCS: quarantine_job.get("matchingIOCs"), MATCHING_SOURCES: quarantine_job.get("matchingSources"), } ) ) headers = [ "ID", SEARCH_ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, LAST_ACTION, "Status", COMPLETED_DATE, "Messages", MATCHING_IOCS, MATCHING_SOURCES, ] return tableToMarkdown("Quarantine Job:", hr_outputs, headers=headers, removeNull=True) def prepare_requests_body_for_quarantine_job_create(quarantine_emails: List) -> dict[str, Any]: """Prepare requests body for cofence-quarantine-job-create command. Args: quarantine_emails(List): List of quarantine emails for job creation. Returns: Dict[str, Any]: Returns prepared requests body. """ data = [] for email in quarantine_emails: if len(list(filter(None, email.split(":")))) != 2: raise ValueError( ERROR_MESSAGE["INVALID_FORMAT"].format(email, "quarantine_emails", SUPPORTED_QUARANTINE_EMAILS_FORMAT) ) data.append({"recipientAddress": email.split(":")[1].strip(), "internetMessageId": email.split(":")[0].strip()}) return {"quarantineEmails": data} def prepare_hr_for_quarantine_job_create(response: dict[str, Any]) -> str: """Prepare Human Readable for cofence-quarantine-job-create command. Args: response(Dict[str, Any]): Response from API. Returns: str: Human readable output. """ hr_outputs = escape_special_characters( { "ID": response.get("id"), CREATED_BY: response.get("createdBy"), CREATED_DATE: None if not response.get("createdDate") else arg_to_datetime(response.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore LAST_MODIFIED_BY: response.get("modifiedBy"), LAST_MODIFIED_DATE: None if not response.get("modifiedDate") else arg_to_datetime(response.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore "Messages": response.get("emailCount"), MATCHING_IOCS: response.get("matchingIOCs"), MATCHING_SOURCES: response.get("matchingSources"), SEARCH_ID: response.get("searchId"), } ) headers = [ "ID", SEARCH_ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, "Messages", MATCHING_IOCS, MATCHING_SOURCES, ] heading = "Quarantine job create:\n#### Quarantine job has been created successfully." return tableToMarkdown(heading, hr_outputs, headers=headers, removeNull=True) def prepare_hr_for_ioc_delete(response: dict[str, Any]) -> str: """Prepare Human Readable for cofence-ioc-delete command. Args: response(Dict[str, Any]: Response from API. Returns: str: Human readable output. """ hr_outputs = escape_special_characters( { "ID": response.get("id"), THREAT_TYPE: response.get("attributes", {}).get("threat_type"), THREAT_VALUE: response.get("attributes", {}).get("threat_value"), "Action Status": "Success", } ) headers = ["ID", THREAT_TYPE, THREAT_VALUE, "Action Status"] heading = ' IOC with value "{}" has been deleted successfully.'.format(hr_outputs["ID"]) return tableToMarkdown(heading, hr_outputs, headers=headers, removeNull=True) def validate_search_id(search_id: int | None): """Validate Cofense Search ID. Args: search_id(Optional[int]): ID assigned by cofense vision. """ validate_required_parameters(id=search_id) if arg_to_number(search_id, arg_name="id") <= 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_SEARCH_ID"]) def prepare_hr_for_message_search_get(response: dict[str, Any]) -> str: """Prepare Human Readable output for cofense-message-search-get commnad. Args: response(Dict[str, Any]): Response from API. Returns: str: Human readable output. """ received_before_date = ( None if not response.get("receivedBeforeDate") else arg_to_datetime(response.get("receivedBeforeDate")).strftime(HR_DATE_FORMAT) # type: ignore ) received_after_date = ( None if not response.get("receivedAfterDate") else arg_to_datetime(response.get("receivedAfterDate")).strftime(HR_DATE_FORMAT) # type: ignore ) date_range = "" if received_after_date: date_range = date_range + f"From: {received_after_date}\n" if received_before_date: date_range = date_range + f"To: {received_before_date}" hr_outputs = escape_special_characters( { "ID": response.get("id"), CREATED_BY: response.get("createdBy"), CREATED_DATE: None if not response.get("createdDate") else arg_to_datetime(response.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore MODIFIED_BY: response.get("modifiedBy"), MODIFIED_DATE: None if not response.get("modifiedDate") else arg_to_datetime(response.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore "Senders": response.get("senders"), "Recipient": response.get("recipient"), "Subjects": response.get("subjects"), ATTACHMENT_FILE_NAMES: response.get("attachmentNames"), INCLUDED_MIME_TYPES: response.get("attachmentMimeTypes"), EXCLUDED_MIME_TYPES: response.get("attachmentExcludeMimeTypes"), HASH_TYPE: [ f"{attachmentHashes.get('hashType')}-{attachmentHashes.get('hashString')}" for attachmentHashes in response.get("attachmentHashCriteria", {}).get("attachmentHashes", []) ], "Domains": response.get("domainCriteria", {}).get("domains"), WHITELIST_URLS: response.get("domainCriteria", {}).get("whiteListUrls"), DATE_RANGE: date_range, "URL": response.get("url"), HEADERS: [f"{header.get('key')}: {header.get('values')}" for header in response.get("headers", [])], INTERNET_MESSAGE_ID: response.get("internetMessageId"), PARTIAL_INGEST: response.get("partialIngest"), } ) headers = [ "ID", CREATED_BY, CREATED_DATE, MODIFIED_BY, MODIFIED_DATE, "Senders", "Recipient", "Subjects", ATTACHMENT_FILE_NAMES, INCLUDED_MIME_TYPES, EXCLUDED_MIME_TYPES, HASH_TYPE, "Domains", WHITELIST_URLS, DATE_RANGE, "URL", HEADERS, INTERNET_MESSAGE_ID, PARTIAL_INGEST, ] return tableToMarkdown("Message Search:", hr_outputs, headers, removeNull=True) def prepare_hr_for_quarantine_job_get(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-quarantine_jobs_get command. Args: response: Message response from API. Returns: str: Human readable output. """ hr_outputs = escape_special_characters( { "ID": response.get("id"), SEARCH_ID: response.get("searchId"), CREATED_BY: response.get("createdBy"), CREATED_DATE: None if not response.get("createdDate") else arg_to_datetime(response.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore LAST_MODIFIED_BY: response.get("modifiedBy"), LAST_MODIFIED_DATE: None if not response.get("modifiedDate") else arg_to_datetime(response.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore LAST_ACTION: response.get("quarantineJobRuns", [])[-1].get("jobRunType"), "Status": response.get("quarantineJobRuns", [])[-1].get("status"), COMPLETED_DATE: None if not response.get("quarantineJobRuns", [])[-1].get("completedDate") else arg_to_datetime( # type: ignore response.get("quarantineJobRuns", [])[-1].get("completedDate") # type: ignore ).strftime(HR_DATE_FORMAT), # type: ignore "Messages": response.get("emailCount"), MATCHING_IOCS: response.get("matchingIOCs"), MATCHING_SOURCES: response.get("matchingSources"), } ) headers = [ "ID", SEARCH_ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, LAST_ACTION, "Status", COMPLETED_DATE, "Messages", MATCHING_IOCS, MATCHING_SOURCES, ] return tableToMarkdown("Quarantine Job:", hr_outputs, headers=headers, removeNull=True) def prepare_hr_for_quarantine_job_delete(job_id: str) -> str: """Prepare Human Readable for cofense-quarantine-job-delete command. Args: job_id: ID of the quarantine job that is deleted. Returns: str: Human readable output. """ return f"## Quarantine Job with ID {job_id} is successfully deleted." def prepare_context_for_message_search_results_get_command(response: dict[str, Any]) -> dict[str, Any]: """Prepare context data for cofense-message-search-results-get command. Args: response(Dict[str, Any]): Response from API. Returns: Dict[str, Any]: Context data. """ context_data = {"Message": response.get("messages", []), **response.get("search", {})} return remove_empty_elements(context_data) def prepare_hr_for_message_search_results_get_command(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-message-search-results-get command. Args: response(Dict[str, Any]): Response from API. Returns: str: Human readable output. """ search = response.get("search", {}) hr_outputs_results = [] for message in response.get("messages", []): attachments = [] for attachment in message.get("attachments", []): attachments.append( f"File Name: {attachment.get('filename')}\nMD5: {attachment.get('md5')}\nSHA256: {attachment.get('sha256')}" ) hr_output_results = escape_special_characters( { "Database ID": message.get("id"), INTERNET_MESSAGE_ID: message.get("internetMessageId"), "Subject": message.get("subject"), SENT_ON: None if not message.get("sentOn") else arg_to_datetime(message.get("sentOn")).strftime(HR_DATE_FORMAT), # type: ignore RECEIVED_ON: None if not message.get("receivedOn") else arg_to_datetime(message.get("receivedOn")).strftime(HR_DATE_FORMAT), # type: ignore "Sender": [sender.get("address") for sender in message.get("from", [])], "Recipient": [recipient.get("address") for recipient in message.get("recipients", [])], } ) hr_output_results["Attachments"] = "\n\n\n".join(attachments) hr_outputs_results.append(hr_output_results) headers_for_results = [ "Database ID", INTERNET_MESSAGE_ID, "Subject", SENT_ON, RECEIVED_ON, "Sender", "Recipient", "Attachments", ] return ( prepare_hr_for_message_search_get(search) + "\n" + tableToMarkdown("Message Search Results:", hr_outputs_results, headers_for_results, removeNull=True) ) def prepare_hr_for_quarantine_job_stop(response: dict[str, Any]) -> str: """Prepare human-readable string for cofense-quarantine-job-stop command. Args: response (dict[str, Any]): Response from the API. Returns: str: Human-readable markdown string. """ created_date = response.get("createdDate") modified_date = response.get("modifiedDate") completed_date = response.get("quarantineJobRuns", [])[-1].get("completedDate") if created_date: created_date = arg_to_datetime(created_date).strftime(HR_DATE_FORMAT) # type: ignore if modified_date: modified_date = arg_to_datetime(modified_date).strftime(HR_DATE_FORMAT) # type: ignore if completed_date: completed_date = arg_to_datetime(completed_date).strftime(HR_DATE_FORMAT) # type: ignore hr_output = escape_special_characters( { "ID": response.get("id"), CREATED_BY: response.get("createdBy"), CREATED_DATE: created_date, LAST_MODIFIED_BY: response.get("modifiedBy"), LAST_MODIFIED_DATE: modified_date, LAST_ACTION: response.get("quarantineJobRuns", [])[-1].get("jobRunType"), "Status": response.get("quarantineJobRuns", [])[-1].get("status"), COMPLETED_DATE: completed_date, "Messages": response.get("emailCount"), MATCHING_IOCS: response.get("matchingIOCs"), MATCHING_SOURCES: response.get("matchingSources"), "Stopped Quarantine": response.get("stopRequested"), } ) headers = [ "ID", CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, LAST_ACTION, "Status", COMPLETED_DATE, "Messages", MATCHING_IOCS, MATCHING_SOURCES, "Stopped Quarantine", ] title = f"Quarantine job with ID {response.get('id')} has been successfully stopped." return tableToMarkdown(title, hr_output, headers=headers, removeNull=True) def validate_create_search_parameter_allowed_search_length(**kwargs: List | None): """Validate search values length should not be greater than three. Args: kwargs(Optional[List]): Dictionary of arguments for validating it's length. """ for key, value in kwargs.items(): if len(value) > 3: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_SEARCH_LENGTH"].format(key)) def validate_arguments_for_message_search_create(**kwargs): """Validate Arguments for cofense-message-search-create command. Args: kwargs: Dictionary of arguments for validation. """ validate_create_search_parameter_allowed_search_length( subjects=kwargs.get("subjects"), senders=kwargs.get("senders"), attachment_names=kwargs.get("attachment_names"), attachment_hashes=kwargs.get("attachment_hashes"), attachment_mime_types=kwargs.get("attachment_mime_types"), attachment_exclude_mime_types=kwargs.get("attachment_exclude_mime_types"), domains=kwargs.get("domains"), whitelist_urls=kwargs.get("whitelist_urls"), headers=kwargs.get("headers"), ) # validate supported options for attachment_hash_criteria attachment_hash_criteria = kwargs.get("attachment_hash_criteria", "ANY") if attachment_hash_criteria.upper() not in SUPPORTED_CRITERIA: raise ValueError( ERROR_MESSAGE["UNSUPPORTED_FIELD"].format( attachment_hash_criteria, "attachment_hash_match_criteria", "attachment_hash_match_criteria", SUPPORTED_CRITERIA ) ) # validate supported options for domain_match_criteria domain_match_criteria = kwargs.get("domain_match_criteria", "ANY") if domain_match_criteria.upper() not in SUPPORTED_CRITERIA: raise ValueError( ERROR_MESSAGE["UNSUPPORTED_FIELD"].format( domain_match_criteria, "domain_match_criteria", "domain_match_criteria", SUPPORTED_CRITERIA ) ) # validate attachment_hashes format attachment_hashes = kwargs.get("attachment_hashes", []) for attachment_hash in attachment_hashes: if len(list(filter(None, attachment_hash.split(":")))) != 2: raise ValueError( ERROR_MESSAGE["INVALID_FORMAT"].format(attachment_hash, "attachment_hashes", SUPPORTED_HASH_VALUE_FORMAT) ) hash_type = attachment_hash.split(":")[0] hash_value = attachment_hash.split(":")[1] if hash_type.upper() not in SUPPORTED_HASH: raise ValueError(ERROR_MESSAGE["UNSUPPORTED_FIELD"].format(hash_type, "hash", "hash", SUPPORTED_HASH)) if hash_type.lower() != get_hash_type(hash_value): raise ValueError(ERROR_MESSAGE["INVALID_ARGUMENT"].format(hash_value, hash_type)) # validate headers format headers = kwargs.get("headers", []) for header in headers: if len(list(filter(None, header.split(":")))) < 2: raise ValueError(ERROR_MESSAGE["INVALID_FORMAT"].format(header, "headers", SUPPORTED_HEADERS_FORMAT)) def prepare_requests_body_for_message_search_create(**kwargs) -> dict[str, Any]: """Prepare required body parameter for cofense-message-search-create command. Args: kwargs: Arguments to prepare request body. Returns: Dict[str, Any]: Required body parameter. """ attachment_hashes = [] for attachment_hash in kwargs.get("attachment_hashes", []): attachment_hashes.append( {"hashType": attachment_hash.split(":", 1)[0].upper(), "hashString": attachment_hash.split(":", 1)[1]} ) attachment_hash_criteria = { "type": kwargs.get("attachment_hash_match_criteria", "ANY").upper(), "attachmentHashes": attachment_hashes, } domain_criteria = { "type": kwargs.get("domain_match_criteria", "ANY").upper(), "domains": kwargs.get("domains"), "whiteListUrls": kwargs.get("whitelist_urls"), } headers = [] for header in kwargs.get("headers", []): headers.append({"key": header.split(":", 1)[0], "values": argToList(header.split(":", 1)[1], ":")}) return assign_params( subjects=kwargs.get("subjects"), senders=kwargs.get("senders"), attachmentNames=kwargs.get("attachment_names"), attachmentHashCriteria=attachment_hash_criteria, attachmentMimeTypes=kwargs.get("attachment_mime_types"), attachmentExcludeMimeTypes=kwargs.get("attachment_exclude_mime_types"), domainCriteria=domain_criteria, headers=headers, internetMessageId=kwargs.get("internet_message_id"), partialIngest=kwargs.get("partial_ingest"), receivedAfterDate=kwargs.get("received_after_date"), receivedBeforeDate=kwargs.get("received_before_date"), recipient=kwargs.get("recipient"), url=kwargs.get("url"), ) def prepare_hr_for_message_search_create_command(response: dict[str, Any]) -> str: """Prepare Human Readable output for cofense-message-search-create command. Args: response: Response from API. Returns: str: Human readable output. """ received_before_date = ( None if not response.get("receivedBeforeDate") else arg_to_datetime(response.get("receivedBeforeDate")).strftime(HR_DATE_FORMAT) # type: ignore ) received_after_date = ( None if not response.get("receivedAfterDate") else arg_to_datetime(response.get("receivedAfterDate")).strftime(HR_DATE_FORMAT) # type: ignore ) date_range = "" if received_after_date: date_range = date_range + f"From: {received_after_date}\n" if received_before_date: date_range = date_range + f"To: {received_before_date}" hr_outputs = escape_special_characters( { "ID": response.get("id"), CREATED_BY: response.get("createdBy"), CREATED_DATE: None if not response.get("createdDate") else arg_to_datetime(response.get("createdDate")).strftime(HR_DATE_FORMAT), # type: ignore MODIFIED_BY: response.get("modifiedBy"), MODIFIED_DATE: None if not response.get("modifiedDate") else arg_to_datetime(response.get("modifiedDate")).strftime(HR_DATE_FORMAT), # type: ignore "Senders": response.get("senders"), "Recipient": response.get("recipient"), "Subjects": response.get("subjects"), ATTACHMENT_FILE_NAMES: response.get("attachmentNames"), INCLUDED_MIME_TYPES: response.get("attachmentMimeTypes"), EXCLUDED_MIME_TYPES: response.get("attachmentExcludeMimeTypes"), HASH_TYPE: [ f"{attachmentHashes.get('hashType')}-{attachmentHashes.get('hashString')}" for attachmentHashes in response.get("attachmentHashCriteria", {}).get("attachmentHashes", []) ], "Domains": response.get("domainCriteria", {}).get("domains"), WHITELIST_URLS: response.get("domainCriteria", {}).get("whiteListUrls"), DATE_RANGE: date_range, "URL": response.get("url"), HEADERS: [f"{header.get('key')}: {header.get('values')}" for header in response.get("headers", [])], INTERNET_MESSAGE_ID: response.get("internetMessageId"), PARTIAL_INGEST: response.get("partialIngest"), } ) headers = [ "ID", CREATED_BY, CREATED_DATE, MODIFIED_BY, MODIFIED_DATE, "Senders", "Recipient", "Subjects", ATTACHMENT_FILE_NAMES, INCLUDED_MIME_TYPES, EXCLUDED_MIME_TYPES, HASH_TYPE, "Domains", WHITELIST_URLS, DATE_RANGE, "URL", HEADERS, INTERNET_MESSAGE_ID, PARTIAL_INGEST, ] heading = f"Message search with ID {response.get('id')} has been created successfully." return tableToMarkdown(heading, hr_outputs, headers, removeNull=True) def prepare_hr_for_last_ioc_get_command(response: dict[str, Any]) -> str: """Prepare Human Readable for cofence-last-updated-ioc-get command. Args: response(Dict[str, Any]): Response from API. Returns: str: Human readable output. """ data = response.get("data", {}) metadata = data.get("metadata", {}).get("quarantine", {}) hr_outputs = escape_special_characters( { "ID": data.get("id"), THREAT_TYPE: data.get("attributes", {}).get("threat_type"), THREAT_VALUE: data.get("attributes", {}).get("threat_value"), CREATED_AT: None if not metadata.get("created_at") else arg_to_datetime(metadata.get("created_at")).strftime(HR_DATE_FORMAT), # type: ignore EXPIRES_AT: None if not metadata.get("expires_at") else arg_to_datetime(metadata.get("expires_at")).strftime(HR_DATE_FORMAT), # type: ignore MATCH_COUNT: metadata.get("match_count"), QUARANTINE_COUNT: metadata.get("quarantine_count"), FIRST_QUARANTINED_AT: None if not metadata.get("first_quarantined_at") else arg_to_datetime(metadata.get("first_quarantined_at")).strftime(HR_DATE_FORMAT), # type: ignore LAST_QUARANTINE_AT: None if not metadata.get("last_quarantined_at") else arg_to_datetime(metadata.get("last_quarantined_at")).strftime(HR_DATE_FORMAT), # type: ignore } ) headers = [ "ID", THREAT_TYPE, THREAT_VALUE, CREATED_AT, EXPIRES_AT, MATCH_COUNT, QUARANTINE_COUNT, FIRST_QUARANTINED_AT, LAST_QUARANTINE_AT, ] return tableToMarkdown("Last IOC:", hr_outputs, headers, removeNull=True) def prepare_and_validate_body_for_iocs_update(request_body: List) -> dict[str, Any]: """Prepare and validate body parameters to be passed in API request for cofense_iocs_update_command. Args: request_body(List): Request body parameter passed by user. Returns: Dict: Body for API request. """ data = [] for body in request_body: threat_type = body.get("threat_type") if threat_type and threat_type.lower() not in THREAT_TYPES: raise ValueError(ERROR_MESSAGE["UNSUPPORTED_FIELD"].format(threat_type, "threat type", "threat type", THREAT_TYPES)) threat_value = body.get("threat_value") threat_level = body.get("threat_level") source_id = body.get("source_id") created_at = body.get("created_at") if created_at: created_at = arg_to_datetime(created_at, arg_name="created_at").strftime(DATE_FORMAT) # type: ignore updated_at = body.get("updated_at") if updated_at: updated_at = arg_to_datetime(updated_at, arg_name="updated_at").strftime(DATE_FORMAT) # type: ignore else: updated_at = datetime.now().strftime(DATE_FORMAT) requested_expiration = body.get("requested_expiration") if requested_expiration: requested_expiration = arg_to_datetime(requested_expiration, arg_name="requested_expiration").strftime( # type: ignore DATE_FORMAT ) validate_required_parameters( threat_type=threat_type, threat_value=threat_value, threat_level=threat_level, source_id=source_id, created_at=created_at, updated_at=updated_at, ) updated_ioc = { "type": "ioc", "attributes": {"threat_type": threat_type, "threat_value": threat_value}, "metadata": { "source": { "threat_level": threat_level, "id": source_id, "requested_expiration": requested_expiration, "created_at": created_at, "updated_at": updated_at, }, }, } data.append(remove_empty_elements(updated_ioc)) return {"data": data} def prepare_body_for_ioc_update(expires_at: str) -> dict[str, Any]: """Prepare body to be passed in API request for cofense_ioc_update_command. Args: expires_at: Expiration date and time. Returns: Dict: Body for API request. """ updated_iocs = { "type": "ioc", "metadata": { "quarantine": {"expires_at": expires_at}, }, } return {"data": updated_iocs} def prepare_hr_for_update_iocs(response: dict) -> str: """Prepare Human Readable for cofense-iocs-update command. Args: response: Message response from API. Returns: str: Human readable output. """ threat_value = response.get("attributes", {}).get("threat_value") threat_level = response.get("metadata", {}).get("source", {}).get("threat_level") hr_outputs = escape_special_characters( { "ID": response.get("id"), THREAT_TYPE: response.get("attributes", {}).get("threat_type"), THREAT_VALUE: threat_value, THREAT_LEVEL: threat_level, CREATED_AT: None if not response.get("metadata", {}).get("source", {}).get("created_at") else arg_to_datetime( # type: ignore response.get("metadata", {}).get("source", {}).get("created_at") # type: ignore ).strftime(HR_DATE_FORMAT), # type: ignore UPDATED_AT: None if not response.get("metadata", {}).get("source", {}).get("updated_at") else arg_to_datetime( response.get("metadata", {}) .get( # type: ignore "source", {} ) .get("updated_at") ).strftime(HR_DATE_FORMAT), "Requested Expiration": arg_to_datetime( # type: ignore response.get("metadata", {}).get("source", {}).get("requested_expiration") ).strftime(HR_DATE_FORMAT), # type: ignore } ) headers = ["ID", THREAT_TYPE, THREAT_VALUE, THREAT_LEVEL, CREATED_AT, UPDATED_AT, "Requested Expiration"] return tableToMarkdown( "IOC {} updated successfully.".format(response.get("id")), hr_outputs, headers=headers, removeNull=True ) def prepare_hr_for_update_ioc(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-ioc-update command. Args: response: Message response from API. Returns: str: Human readable output. """ ioc_id = response.get("id") threat_value = response.get("attributes", {}).get("threat_value") hr_output = escape_special_characters( { "ID": response.get("id"), THREAT_TYPE: response.get("attributes", {}).get("threat_type"), THREAT_VALUE: threat_value, CREATED_AT: None if not response.get("metadata", {}).get("quarantine", {}).get("created_at") else arg_to_datetime( response.get("metadata", {}) .get( # type: ignore "quarantine", {} ) .get("created_at") ).strftime(HR_DATE_FORMAT), # type: ignore EXPIRES_AT: None if not response.get("metadata", {}).get("quarantine", {}).get("expires_at") else arg_to_datetime( # type: ignore response.get("metadata", {}).get("quarantine", {}).get("expires_at") # type: ignore ).strftime(HR_DATE_FORMAT), # type: ignore } ) headers = ["ID", THREAT_TYPE, THREAT_VALUE, CREATED_AT, EXPIRES_AT] return tableToMarkdown(f"IOC with value {ioc_id} has been updated successfully.", hr_output, headers=headers, removeNull=True) def prepare_hr_for_get_ioc(response: dict[str, Any]) -> str: """Prepare Human Readable for cofense-ioc-get command. Args: response: Message response from API. Returns: str: Human readable output. """ threat_value = response.get("attributes", {}).get("threat_value") hr_output = escape_special_characters( { "ID": response.get("id"), THREAT_TYPE: response.get("attributes", {}).get("threat_type"), THREAT_VALUE: threat_value, CREATED_AT: None if not response.get("metadata", {}).get("quarantine", {}).get("created_at") else arg_to_datetime( # type: ignore response.get("metadata", {}).get("quarantine", {}).get("created_at") # type: ignore ).strftime(HR_DATE_FORMAT), # type: ignore EXPIRES_AT: None if not response.get("metadata", {}).get("quarantine", {}).get("expires_at") else arg_to_datetime( # type: ignore response.get("metadata", {}).get("quarantine", {}).get("expires_at") # type: ignore ).strftime(HR_DATE_FORMAT), # type: ignore } ) headers = ["ID", THREAT_TYPE, THREAT_VALUE, CREATED_AT, EXPIRES_AT] return tableToMarkdown("IOC:", hr_output, headers=headers, removeNull=True) def validate_arguments_for_iocs_list(source: str, page: int | None, size: int | None) -> None: """Validate arguments for cofense-iocs-list command. Args: source (str): The name of the source. page (Optional[int]): page offset to start listing quarantine jobs from. size (Optional[int]): The number of results to retrieve per page. """ validate_required_parameters(source=source) validate_page_size(page_size=size) if int(page) < 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_PAGE_VALUE"]) def prepare_hr_for_iocs_list(response: dict[str, Any]) -> str: """Prepare human-readable string for cofense-iocs-list command. Args: response (dict[str, Any]): Response from the API. Returns: str: Human-readable markdown string for cofense-iocs-list command. """ created_at = response.get("metadata", {}).get("source", {}).get("created_at") expires_at = response.get("metadata", {}).get("source", {}).get("expires_at") updated_at = response.get("metadata", {}).get("source", {}).get("updated_at") first_quarantined_at = response.get("metadata", {}).get("quarantine", {}).get("first_quarantined_at") last_quarantined_at = response.get("metadata", {}).get("quarantine", {}).get("last_quarantined_at") if created_at: created_at = arg_to_datetime(created_at).strftime(HR_DATE_FORMAT) # type: ignore if expires_at: expires_at = arg_to_datetime(expires_at).strftime(HR_DATE_FORMAT) # type: ignore if updated_at: updated_at = arg_to_datetime(updated_at).strftime(HR_DATE_FORMAT) # type: ignore if first_quarantined_at: first_quarantined_at = arg_to_datetime(first_quarantined_at).strftime(HR_DATE_FORMAT) # type: ignore if last_quarantined_at: last_quarantined_at = arg_to_datetime(last_quarantined_at).strftime(HR_DATE_FORMAT) # type: ignore hr_outputs = escape_special_characters( { "ID": response.get("id"), THREAT_TYPE: response.get("attributes", {}).get("threat_type"), THREAT_VALUE: response.get("attributes", {}).get("threat_value"), THREAT_LEVEL: response.get("metadata", {}).get("source", {}).get("threat_level"), UPDATED_AT: updated_at, CREATED_AT: created_at, EXPIRES_AT: expires_at, MATCH_COUNT: response.get("metadata", {}).get("quarantine", {}).get("match_count"), QUARANTINE_COUNT: response.get("metadata", {}).get("quarantine", {}).get("quarantine_count"), FIRST_QUARANTINED_AT: first_quarantined_at, LAST_QUARANTINE_AT: last_quarantined_at, } ) headers = [ "ID", THREAT_TYPE, THREAT_VALUE, THREAT_LEVEL, UPDATED_AT, CREATED_AT, EXPIRES_AT, MATCH_COUNT, QUARANTINE_COUNT, FIRST_QUARANTINED_AT, LAST_QUARANTINE_AT, ] return tableToMarkdown("IOC:", hr_outputs, headers, removeNull=True) def get_standard_context(client: VisionClient, ioc: dict) -> Common.Indicator | None: """Get the standard context for IOC. Args: client(VisionClient): VisionClient to be used. ioc(Dict): ioc details returned from API. Returns: Optional[Common.Indicator]: Standard context. """ if not ioc or not ioc.get("id"): return None ioc = remove_empty_elements(ioc) threat_type = ioc.get("attributes", {}).get("threat_type", "").lower() threat_value = ioc.get("attributes", {}).get("threat_value", "") threat_level = ioc.get("metadata", {}).get("source", {}).get("threat_level") score = 0 if threat_level: if threat_level.lower() in client.threat_levels_bad: score = 3 elif threat_level.lower() in client.threat_levels_suspicious: score = 2 elif threat_level.lower() in client.threat_levels_good: score = 1 dbot_score = Common.DBotScore( indicator=ioc["id"], indicator_type=IOC_TYPES[threat_type], integration_name="Cofense Vision", score=score ) if threat_type == "url": return Common.URL(url=threat_value, dbot_score=dbot_score) elif threat_type == "domain": return Common.Domain(domain=threat_value, dbot_score=dbot_score) elif threat_type == "sender": return Common.EMAIL(address=threat_value, dbot_score=dbot_score) elif threat_type == "md5": return Common.File(md5=threat_value, dbot_score=dbot_score) elif threat_type == "sha256": return Common.File(sha256=threat_value, dbot_score=dbot_score) return None """ COMMAND FUNCTIONS """ def test_module(client: VisionClient) -> 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 (VisionClient): client to use for testing. Returns: 'ok' if test passed, anything else will fail the test. """ client.list_searches(size=2) return "ok" def cofense_message_metadata_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Retrieve the full content of a message. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard Command Result. """ internet_message_id = args.get("internet_message_id", "") recipient_address = args.get("recipient_address", "") response = client.get_message_metadata(internet_message_id, recipient_address) hr_output = prepare_hr_for_message_metadata_get(remove_empty_elements(response)) return CommandResults( outputs_prefix="Cofense.Message", outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, ) def cofense_message_get_command(client: VisionClient, args: dict[str, Any]) -> dict: """Fetch full content of an email and returns a zip file of an email using a token. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: Dict: A Demisto war room entry. """ token = args.get("token", "") response = client.get_message(token) return fileResult(filename="message.zip", data=response.content) def cofense_message_attachment_get_command(client: VisionClient, args: dict[str, Any]) -> dict: """Fetch an attachment by using its MD5 or SHA256 hash and returns the attachment. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: Dict: A Demisto war room entry. """ file_name = args.get("file_name") md5 = args.get("md5") sha256 = args.get("sha256") validate_required_parameters(file_name=file_name, md5=md5) validate_params_for_attachment_get(md5, sha256) response = client.get_attachment(md5, sha256) return fileResult(filename=file_name, data=response.content) def cofense_message_token_get_command(client: VisionClient, args: dict[str, str]) -> CommandResults: """ Command function for cofense-message-token-get command. Retrieve the one time token required for getting the message from the Cofense API. Args: client (VisionClient): The client object to be used for API call. args (dict[str, str]): The arguments required for the command. Returns: CommandResults: Standard CommandResults object. """ internet_message_id: str = args.get("internet_message_id", "") recipient_address: str = args.get("recipient_address", "") password: str = args.get("password", "") validate_required_parameters(internet_message_id=internet_message_id, recipient_address=recipient_address) token = client.get_message_token( internet_message_id=internet_message_id, recipient_address=recipient_address, password=password ) context_data = { "token": token, "internetMessageId": internet_message_id, "recipient": {"address": recipient_address}, } hr_output = prepare_hr_for_message_token_get(response=context_data) return CommandResults( outputs_prefix="Cofense.Message", outputs=remove_empty_elements(context_data), outputs_key_field="internetMessageId", readable_output=hr_output, ) def cofense_quarantine_job_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """ Retrieve quarantine job identified by its unique ID. Args: client (VisionClient): The client object to be used for API call. args (dict[str, str]): The arguments required for the command. Returns: CommandResults: Standard CommandResults object. """ job_id = args.get("id", "") validate_quarantine_job_id(id=job_id) response = client.get_quarantine_job(job_id=job_id) hr_output = prepare_hr_for_quarantine_job_get(response) return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, ) def cofense_quarantine_jobs_list_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Filter and return a paginated list of matching quarantine jobs. Args: client: VisionClient to be used. args: Arguments provided by user. Returns: CommandResults: Standard Command Result. """ exclude_quarantine_emails = argToBoolean(args.get("exclude_quarantine_emails", False)) page = arg_to_number(args.get("page", 0)) if int(page) < 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_PAGE_VALUE"]) size = arg_to_number(args.get("size", 50)) validate_page_size(size) sort = prepare_sort_query(arg_to_list(args.get("sort", DEFAULT_SORT_VALUE)), "quarantine_jobs_list") body = prepare_body_for_qurantine_jobs_list_command(args) response = client.quarantine_jobs_list( page=page, size=size, sort=sort, exclude_quarantine_emails=exclude_quarantine_emails, body=body ) hr_output = prepare_hr_for_quarantine_jobs_list(response) return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response.get("quarantineJobs")), readable_output=hr_output, raw_response=response, ) def cofense_quarantine_job_create_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Create a new quarantine job using internet message id and recipient's address. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard command result. """ quarantine_emails: List = arg_to_list_with_filter_null_values(args.get("quarantine_emails")) validate_required_parameters(quarantine_emails=quarantine_emails) requests_body = prepare_requests_body_for_quarantine_job_create(quarantine_emails) response = client.create_quarantine_job(requests_body) hr_output = prepare_hr_for_quarantine_job_create(remove_empty_elements(response)) return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, ) def cofense_message_search_results_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Retrieve list of paginated search results. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard CommandResults object. """ search_id = args.get("id", "") validate_search_id(search_id) page = arg_to_number(args.get("page", 0), arg_name="page") size = arg_to_number(args.get("size", 50), arg_name="size") if int(page) < 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_PAGE_VALUE"]) validate_page_size(size) sort = prepare_sort_query(arg_to_list(args.get("sort", DEFAULT_SORT_VALUE)), "message_search_result_get") response = client.get_search_results(search_id=search_id, page=page, size=size, sort=sort) context_data = prepare_context_for_message_search_results_get_command(response) hr_output = prepare_hr_for_message_search_results_get_command(remove_empty_elements(response)) return CommandResults( outputs_prefix=SEARCH_OUTPUT_PREFIX, outputs_key_field="id", outputs=context_data, readable_output=hr_output, raw_response=response, ) def cofense_message_searches_list_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Retrieve list of paginated search results. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard CommandResults object. """ page = arg_to_number(args.get("page", 0), arg_name="page") size = arg_to_number(args.get("size", 50), arg_name="size") if int(page) < 0: # type: ignore raise ValueError(ERROR_MESSAGE["INVALID_PAGE_VALUE"]) validate_page_size(size) sort = prepare_sort_query(arg_to_list(args.get("sort", DEFAULT_SORT_VALUE)), "message_searches_list") response = client.list_searches(page=page, size=size, sort=sort) hr_output = prepare_hr_for_message_searches_list(remove_empty_elements(response)) return CommandResults( outputs_prefix=SEARCH_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response.get("searches")), readable_output=hr_output, raw_response=response, ) def cofense_quarantine_job_restore_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Restore emails quarantined by the job identified by its ID. Args: client (VisionClient): VisionClient to be used. args (Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard command result object. """ job_id = args.get("id", "") validate_quarantine_job_id(id=job_id) client.restore_quarantine_job(id=job_id) context_data = {"id": job_id, "isRestored": True} hr_output = f"## Emails quarantined by the quarantine job ID {job_id} have been successfully restored." return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs=remove_empty_elements(context_data), outputs_key_field="id", readable_output=hr_output, ) def cofense_message_search_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Retrieve the search identified by id. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard CommandResults object. """ search_id = args.get("id", "") validate_search_id(search_id) response = client.get_search(search_id) hr_output = prepare_hr_for_message_search_get(remove_empty_elements(response)) return CommandResults( outputs_prefix=SEARCH_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, ) def cofense_quarantine_job_approve_command(client: VisionClient, args: dict[str, str]) -> CommandResults: """Approve the quarantine job identified by its unique ID. Args: client (VisionClient): Client object to be used. args (dict[str, str]): Arguments provided by the user. Returns: CommandResults: Standard command results object """ job_id = args.get("id", "") message_count = arg_to_number(args.get("message_count", ""), arg_name="message_count") # Validate arguments (id and message_count) validate_quarantine_job_id(id=job_id) if message_count is not None and message_count <= 0: raise ValueError(ERROR_MESSAGE["INVALID_QUARANTINE_JOB_PARAM"].format("message_count")) client.approve_quarantine_job(id=job_id, message_count=message_count) context_data = {"id": job_id, "isApproved": True} hr_output = f"## Quarantine Job with ID {job_id} has been approved successfully." return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(context_data), readable_output=hr_output, ) def cofense_quarantine_job_delete_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Delete the quarantine job identified by its unique ID. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard Command Result. """ job_id = args.get("id", "") validate_quarantine_job_id(id=job_id) client.delete_quarantine_job(job_id) response = {"id": job_id, "isDeleted": True} hr_output = prepare_hr_for_quarantine_job_delete(job_id) return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=response, readable_output=hr_output, raw_response="", ) def cofense_ioc_delete_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Delete a single active or expired IOC from the local IOC Repository. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard command result. """ source = args.get("source") ioc_id = args.get("id") validate_required_parameters(source=source, id=ioc_id) response = client.delete_ioc(source, ioc_id) if response: response = {"deleted": True, **response.get("data", {})} hr_output = prepare_hr_for_ioc_delete(response) return CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, outputs_key_field="id", indicator=get_standard_context(client, response), ) def cofense_quarantine_job_stop_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Stop a quarantine job identified by its unique ID. Args: client (VisionClient): client object to be used. args (dict[str, Any]): arguments provided by the user. Returns: Standard command results. """ job_id = args.get("id", "") validate_quarantine_job_id(id=job_id) response = client.stop_quarantine_job(id=job_id) hr_output = prepare_hr_for_quarantine_job_stop(response=response) return CommandResults( outputs_prefix=QUARANTINE_JOB_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), raw_response=response, readable_output=hr_output, ) def cofense_message_search_create_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Create a search based on user specified arguments. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard command result. """ subjects: List = arg_to_list_with_filter_null_values(args.get("subjects")) senders: List = arg_to_list_with_filter_null_values(args.get("senders")) attachment_names: List = arg_to_list_with_filter_null_values(args.get("attachment_names")) attachment_hash_criteria: str = args.get("attachment_hash_match_criteria", "ANY") attachment_hashes: List = arg_to_list_with_filter_null_values(args.get("attachment_hashes")) attachment_mime_types: List = arg_to_list_with_filter_null_values(args.get("attachment_mime_types")) attachment_exclude_mime_types: List = arg_to_list_with_filter_null_values(args.get("attachment_exclude_mime_types")) domain_match_criteria: str = args.get("domain_match_criteria", "ANY") domains: List = arg_to_list_with_filter_null_values(args.get("domains")) whitelist_urls: List = arg_to_list_with_filter_null_values(args.get("whitelist_urls")) headers: List = arg_to_list_with_filter_null_values(args.get("headers")) internet_message_id = args.get("internet_message_id") partial_ingest: bool = argToBoolean(args.get("partial_ingest", False)) received_after_date = args.get("received_after_date") received_before_date = args.get("received_before_date") recipient = args.get("recipient") url = args.get("url") if received_after_date: received_after_date = arg_to_datetime(received_after_date, arg_name="received_after_date") received_after_date = received_after_date.strftime(DATE_FORMAT) # type: ignore if received_before_date: received_before_date = arg_to_datetime(received_before_date, arg_name="received_before_date") received_before_date = received_before_date.strftime(DATE_FORMAT) # type: ignore validate_arguments_for_message_search_create( subjects=subjects, senders=senders, attachment_names=attachment_names, attachment_hashes=attachment_hashes, attachment_hash_criteria=attachment_hash_criteria, domain_match_criteria=domain_match_criteria, attachment_mime_types=attachment_mime_types, attachment_exclude_mime_types=attachment_exclude_mime_types, domains=domains, whitelist_urls=whitelist_urls, headers=headers, ) body = prepare_requests_body_for_message_search_create( subjects=subjects, senders=senders, attachment_names=attachment_names, attachment_hash_match_criteria=attachment_hash_criteria, attachment_hashes=attachment_hashes, attachment_mime_types=attachment_mime_types, attachment_exclude_mime_types=attachment_exclude_mime_types, domain_match_criteria=domain_match_criteria, domains=domains, whitelist_urls=whitelist_urls, headers=headers, internet_message_id=internet_message_id, partial_ingest=partial_ingest, received_after_date=received_after_date, received_before_date=received_before_date, recipient=recipient, url=url, ) response = client.create_search(body) hr_output = prepare_hr_for_message_search_create_command(remove_empty_elements(response)) return CommandResults( outputs_prefix=SEARCH_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, ) def cofense_last_ioc_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Synchronize the ioc source and returns last updated IOCs. Args: client(VisionClient): VisionClient to be used. args(Dict[str, Any]): Arguments provided by user. Returns: CommandResults: Standard command result. """ ioc_source = args.get("source", "") validate_required_parameters(source=ioc_source) response = client.get_last_ioc(ioc_source) hr_output = prepare_hr_for_last_ioc_get_command(remove_empty_elements(response)) return CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response.get("data")), readable_output=hr_output, raw_response=response, indicator=get_standard_context(client, response.get("data", {})), ) def cofense_iocs_update_command(client: VisionClient, args: dict[str, Any]) -> List[CommandResults]: """Update the IOCs stored in the local IOC repository. Args: client (VisionClient): Client object to be used. args (dict[str, str]): Arguments provided by the user. Returns: List[CommandResults]: Standard command results object """ source = args.get("source") iocs_json = args.get("iocs_json") if not iocs_json: iocs_json = json.dumps( [ { "threat_type": args.get("threat_type"), "threat_value": args.get("threat_value"), "threat_level": args.get("threat_level"), "source_id": args.get("source_id"), "created_at": args.get("created_at"), "updated_at": args.get("updated_at"), "requested_expiration": args.get("requested_expiration"), } ] ) validate_required_parameters(iocs_json=iocs_json, source=source) try: iocs_json = json.loads(iocs_json) # type: ignore if isinstance(iocs_json, dict): iocs_json = [iocs_json] except json.JSONDecodeError: raise ValueError(f"{iocs_json} is an invalid JSON format") body = prepare_and_validate_body_for_iocs_update(iocs_json) response = client.update_iocs(source, body) command_results = [] for ioc in response.get("data", []): command_results.append( CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(ioc), readable_output=prepare_hr_for_update_iocs(ioc), raw_response=ioc, indicator=get_standard_context(client, ioc), ) ) return ( command_results if command_results else CommandResults( # type: ignore readable_output=tableToMarkdown("IOC:", []) ) ) def cofense_ioc_update_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Update a single IOC stored in the local IOC repository. Args: client (VisionClient): Client object to be used. args (dict[str, str]): Arguments provided by the user. Returns: CommandResults: Standard command results object """ md5_id = args.get("id") expires_at = args.get("expires_at") if expires_at: expires_at = arg_to_datetime(expires_at, arg_name="expires_at").strftime(DATE_FORMAT) # type: ignore validate_required_parameters(id=md5_id, expires_at=expires_at) body = prepare_body_for_ioc_update(expires_at) # type: ignore response = client.update_ioc(md5_id, body) response = response.get("data", {}) hr_output = prepare_hr_for_update_ioc(response) # type: ignore return CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, indicator=get_standard_context(client, response), ) def cofense_iocs_list_command(client: VisionClient, args: dict[str, Any]) -> List[CommandResults]: """List the IOCs. Args: client (VisionClient): client object to be used. args (dict[str, Any]): arguments provided by the user. Returns: List[CommandResults]: Standard command results. """ source = args.get("source", "") page = arg_to_number(args.get("page", 0), arg_name="page") size = arg_to_number(args.get("size", 50), arg_name="size") validate_arguments_for_iocs_list(source=source, page=page, size=size) include_expired = argToBoolean(args.get("include_expired", False)) since = args.get("since") sort = prepare_sort_query(arg_to_list(args.get("sort", "")), command="iocs_list") if since: since = arg_to_datetime(since, arg_name="since") since = since.strftime(DATE_FORMAT) # type: ignore response = client.list_iocs( source=source, page=page, # type: ignore size=size, # type: ignore since=since, # type: ignore include_expired=include_expired, sort_string=sort, ) command_results = [] for ioc in response.get("data", []): command_results.append( CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(ioc), readable_output=prepare_hr_for_iocs_list(ioc), raw_response=ioc, indicator=get_standard_context(client, ioc), ) ) return ( command_results if command_results else CommandResults( # type: ignore readable_output=tableToMarkdown("IOC:", []) ) ) def cofense_ioc_get_command(client: VisionClient, args: dict[str, Any]) -> CommandResults: """Get a single IOC stored in the local IOC repository. Args: client (VisionClient): Client object to be used. args (dict[str, str]): Arguments provided by the user. Returns: CommandResults: Standard command results object """ md5_id = args.get("id") source = args.get("source") validate_required_parameters(id=md5_id) response = client.get_ioc(source, md5_id) response = response.get("data", {}) hr_output = prepare_hr_for_get_ioc(response) # type: ignore return CommandResults( outputs_prefix=IOC_OUTPUT_PREFIX, outputs_key_field="id", outputs=remove_empty_elements(response), readable_output=hr_output, raw_response=response, indicator=get_standard_context(client, response), ) def cofense_searchable_headers_list_command(client: VisionClient): """Retrieve list of configured header keys which are available to create a search. Args: client(VisionClient): VisionClient to be used. Returns: CommandResults: Standard Command Result. """ response = client.list_searchable_headers() hr_output = tableToMarkdown( "Available headers to create a search:", {"Headers": response.get("headers")}, ["Headers"], removeNull=True ) context_data = {"name": "searchableHeaders", "value": response.get("headers", [])} return CommandResults( outputs_prefix="Cofense.Config", outputs_key_field="name", outputs=context_data, readable_output=hr_output, raw_response=response, ) def main(): """Parse params and runs command functions.""" params = demisto.params() base_url = params.get("url") client_id = params.get("credentials", {}).get("identifier").strip() client_secret = params.get("credentials", {}).get("password") verify_certificate = not argToBoolean(params.get("insecure", False)) proxy = argToBoolean(params.get("proxy", False)) threat_levels_good = argToList(params.get("threat_levels_good", [])) threat_levels_suspicious = argToList(params.get("threat_levels_suspicious", [])) threat_levels_bad = argToList(params.get("threat_levels_bad", [])) COFENSE_COMMANDS: dict[str, Callable] = { "cofense-message-metadata-get": cofense_message_metadata_get_command, "cofense-message-get": cofense_message_get_command, "cofense-message-attachment-get": cofense_message_attachment_get_command, "cofense-message-token-get": cofense_message_token_get_command, "cofense-quarantine-jobs-list": cofense_quarantine_jobs_list_command, "cofense-quarantine-job-create": cofense_quarantine_job_create_command, "cofense-quarantine-job-restore": cofense_quarantine_job_restore_command, "cofense-message-searches-list": cofense_message_searches_list_command, "cofense-message-search-get": cofense_message_search_get_command, "cofense-quarantine-job-get": cofense_quarantine_job_get_command, "cofense-quarantine-job-approve": cofense_quarantine_job_approve_command, "cofense-quarantine-job-delete": cofense_quarantine_job_delete_command, "cofense-message-search-results-get": cofense_message_search_results_get_command, "cofense-ioc-delete": cofense_ioc_delete_command, "cofense-quarantine-job-stop": cofense_quarantine_job_stop_command, "cofense-message-search-create": cofense_message_search_create_command, "cofense-last-ioc-get": cofense_last_ioc_get_command, "cofense-iocs-update": cofense_iocs_update_command, "cofense-ioc-update": cofense_ioc_update_command, "cofense-iocs-list": cofense_iocs_list_command, "cofense-ioc-get": cofense_ioc_get_command, } command = demisto.command() demisto.debug(f"Command being called is {command}") try: client = VisionClient( base_url=base_url, client_id=client_id, client_secret=client_secret, verify=verify_certificate, proxy=proxy, threat_levels_good=threat_levels_good, threat_levels_suspicious=threat_levels_suspicious, threat_levels_bad=threat_levels_bad, ) if command == "test-module": return_results(test_module(client)) elif COFENSE_COMMANDS.get(command): args = demisto.args() remove_nulls_from_dictionary(trim_spaces_from_args(args)) return_results(COFENSE_COMMANDS[command](client, args)) elif command == "cofense-searchable-headers-list": return_results(cofense_searchable_headers_list_command(client)) else: raise NotImplementedError(f"Command {command} is not implemented") # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {command} command.\nError:\n{e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): # pragma: no cover main()