From 9a23640d7e8d42fcc8bcfb1bcb908ebf0c9cffcb Mon Sep 17 00:00:00 2001 From: content-bot <55035720+content-bot@users.noreply.github.com> Date: Tue, 19 Dec 2023 20:11:49 +0200 Subject: [PATCH] Added support for report attachment download (#31478) --- Packs/CofenseTriage/.pack-ignore | 51 +++- .../CofenseTriagev3/CofenseTriagev3.py | 119 ++++++++- .../CofenseTriagev3/CofenseTriagev3.yml | 183 +++++++++++--- .../CofenseTriagev3/CofenseTriagev3_test.py | 106 +++++++- .../Integrations/CofenseTriagev3/README.md | 226 ++++++++++++++++++ .../report_attachment_download_response.xml | 6 + .../report_attachment_list.md | 5 + .../report_attachment_list_context.json | 90 +++++++ .../report_attachment_list_response.json | 102 ++++++++ Packs/CofenseTriage/ReleaseNotes/2_1_20.md | 8 + Packs/CofenseTriage/pack_metadata.json | 2 +- 11 files changed, 861 insertions(+), 37 deletions(-) create mode 100644 Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_download_response.xml create mode 100644 Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list.md create mode 100644 Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_context.json create mode 100644 Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_response.json create mode 100644 Packs/CofenseTriage/ReleaseNotes/2_1_20.md diff --git a/Packs/CofenseTriage/.pack-ignore b/Packs/CofenseTriage/.pack-ignore index 9ba23337edf3..0a75216b525f 100644 --- a/Packs/CofenseTriage/.pack-ignore +++ b/Packs/CofenseTriage/.pack-ignore @@ -12,4 +12,53 @@ ignore=IM111 [known_words] cofense - +cofens +lt +lteq +gt +gteq +d +updation +s +md +assignee +x +ss +vp +ztrv +fc +v +vq +m +nt +vdv +sm +yx +jv +tp +h +qfz +crlf +xlsm +br +xl +categorizations +n +mw +dg +dc +j +tc +r +vlet +kn +nstrings +ctt +b +submi +srctag +phenotypes +commentable +jpg +png +rgba \ No newline at end of file diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.py b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.py index 6e381ff50fb9..47a3767f7ac3 100644 --- a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.py +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.py @@ -35,7 +35,9 @@ "COMMENTS": "api/public/v2/comments/", "REPORT_ID": "api/public/v2/reports/{}", "CLUSTER": "api/public/v2/clusters", - "REPORT_ATTACHMENT_PAYLOAD": "/api/public/v2/reports/{}/attachment_payloads" + "REPORT_ATTACHMENT_PAYLOAD": "/api/public/v2/reports/{}/attachment_payloads", + "REPORT_ATTACHMENT": "/api/public/v2/reports/{}/attachments", + "REPORT_ATTACHMENT_DOWNLOAD": "api/public/v2/attachments/{}/download", } OUTPUT_PREFIX = { @@ -46,6 +48,7 @@ "RULE": "Cofense.Rule", "REPORTER": "Cofense.Reporter", "ATTACHMENT_PAYLOAD": "Cofense.AttachmentPayload", + "ATTACHMENT": "Cofense.Attachment", "INTEGRATION_SUBMISSION": "Cofense.IntegrationSubmission", "COMMENT": "Cofense.Comment", "CLUSTER": "Cofense.Cluster" @@ -985,6 +988,35 @@ def prepare_hr_for_attachment_payloads(results: List[Dict[str, Any]]) -> str: UPDATED_AT], removeNull=True) +def prepare_hr_for_report_attachments(results: List[Dict[str, Any]]) -> str: + """ + Parse and convert the report attachment in the response into human-readable markdown string. + + :type results: ``List[Dict[str, Any]]`` + :param results: Details of urls. + + :return: Human Readable string containing information of report attachment. + :rtype: ``str`` + """ + attachments_hr = [] + for res in results: + attributes = res.get("attributes") + hr = {"Attachment ID": res.get("id", "")} + + if attributes: + hr["File Name"] = attributes.get("filename", "") + hr["File Size in Bytes"] = attributes.get("size", "") + hr["Is Child"] = attributes.get("is_child", "") + hr[CREATED_AT] = attributes.get("created_at", "") + hr[UPDATED_AT] = attributes.get("updated_at", "") + attachments_hr.append(hr) + + return tableToMarkdown("Attachment(s)", attachments_hr, + headers=["Attachment ID", "File Name", + "File Size in Bytes", "Is Child", CREATED_AT, UPDATED_AT], + removeNull=True) + + def validate_comment_list_args(args: Dict[str, str]) -> Dict[str, Any]: """ Validate arguments for cofense-comment-list command, raise ValueError on invalid arguments. @@ -1399,6 +1431,87 @@ def cofense_report_attachment_payload_list_command(client: Client, args: Dict[st ) +def cofense_report_attachment_list_command(client: Client, args: Dict[str, str]) -> CommandResults: + """ + Retrieves report attachment list based on the filter values provided in the command arguments. + For reported emails that contain attachments, Cofense Triage captures the attachment's filename and size. + + :type client: ``Client`` + :param client: Client object to be used. + + :type args: ``Dict[str, str]`` + :param args: The command arguments provided by the user. + + :return: Standard command result. + :rtype: ``CommandResults`` + """ + params, _ = validate_list_command_args(args, "attachments") + report_id = args.get("id") + # Validation for empty report_id + if not report_id: + raise ValueError(MESSAGES["REQUIRED_ARGUMENT"].format("id")) + # Appending the report id to the url_suffix + url_suffix = URL_SUFFIX["REPORT_ATTACHMENT"].format(report_id) + + # Sending http request + response = client.http_request(url_suffix, params=params) + + result = response.get("data") + + # Returning if data is empty or not present + if not result: + return CommandResults(readable_output=MESSAGES["NO_RECORDS_FOUND"].format("attachments")) + + if isinstance(result, dict): + result = [result] + + # Creating the Human Readable + hr_response = prepare_hr_for_report_attachments(result) + + # Creating the Context data + context_data = remove_empty_elements(result) + + return CommandResults(outputs_prefix=OUTPUT_PREFIX["ATTACHMENT"], + outputs_key_field="id", + outputs=context_data, + readable_output=hr_response, + raw_response=response + ) + + +def cofense_report_attachment_download_command(client: Client, args: Dict[str, str]) -> dict: + """ + Downloads the attachment for a the specified attachment ID. + + :type client: ``Client`` + :param client: Client object to be used. + + :type args: ``Dict[str, str]`` + :param args: The command arguments provided by the user. + + :return: File Result. + :rtype: ``dict`` + """ + attachment_id = args.get("id") + if not attachment_id: + raise ValueError(MESSAGES["REQUIRED_ARGUMENT"].format("id")) + # Appending the id to the url_suffix + url_suffix = URL_SUFFIX["REPORT_ATTACHMENT_DOWNLOAD"].format(attachment_id) + headers = { + 'Accept': "*/*" + } + # Sending http request + response = client.http_request(url_suffix, resp_type="response", headers=headers) + content_disposition = response.headers.get('Content-Disposition') or '' + content_disposition_split = content_disposition.split(';') + if len(content_disposition_split) > 1: + file_name = content_disposition_split[1].replace('filename=', '').replace('"', '') + file_name = urllib.parse.unquote(file_name).strip() + else: + file_name = f"Attachment ID - {attachment_id}" + return fileResult(file_name, data=response.content) + + def fetch_incidents(client: Client, last_run: dict, params: Dict) -> Tuple[dict, list]: """Fetches incidents from Cofense API. @@ -2033,7 +2146,9 @@ def main() -> None: 'cofense-cluster-list': cofense_cluster_list_command, 'cofense-threat-indicator-update': cofense_threat_indicator_update_command, 'cofense-report-image-download': cofense_report_image_download_command, - 'cofense-report-attachment-payload-list': cofense_report_attachment_payload_list_command + 'cofense-report-attachment-payload-list': cofense_report_attachment_payload_list_command, + 'cofense-report-attachment-list': cofense_report_attachment_list_command, + 'cofense-report-attachment-download': cofense_report_attachment_download_command, } command = demisto.command() demisto.debug(f'[CofenseTriagev3] Command being called is {command}') diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.yml b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.yml index 22b2f5626a4d..417260d2b5d3 100644 --- a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.yml +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3.yml @@ -118,15 +118,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the threat indicators. name: page_number - - description: 'Specify the attributes to sort the threat indicators. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: threat_level, -created_at' + - description: 'Specify the attributes to sort the threat indicators. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: threat_level, -created_at.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of threat indicators by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"threat_level_eq\":\"Malicious,Benign\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"} + For example: {\"threat_level_eq\":\"Malicious,Benign\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: threat_level, threat_type, threat_value' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: threat_level, threat_type, threat_value.' isArray: true name: fields_to_retrieve - description: 'Specify the level of the threat to retrieve the threat indicators. Some possible values are: Malicious, Suspicious, Benign.' @@ -208,15 +208,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the reports. name: page_number - - description: 'Specify the attributes to sort the reports. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -received_at, match_priority' + - description: 'Specify the attributes to sort the reports. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -received_at, match_priority.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of reports by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"updated_at_gt\":\"2020-10-26T10:48:16.834Z\",\"categorization_tags_any\":\"test, snow\"} + For example: {\"updated_at_gt\":\"2020-10-26T10:48:16.834Z\",\"categorization_tags_any\":\"test, snow\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: location, from_address' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: location, from_address.' name: fields_to_retrieve - description: 'Specify the priority to retrieve the reports based on the priority of the rules that match the reports. Possible values are: 0, 1, 2, 3, 4, 5.' isArray: true @@ -486,15 +486,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the categories. name: page_number - - description: 'Specify the attributes to sort the categories. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: score, -name' + - description: 'Specify the attributes to sort the categories. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: score, -name.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of categories by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"score_gteq\":\"2,10\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"} + For example: {\"score_gteq\":\"2,10\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: name, score' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: name, score.' isArray: true name: fields_to_retrieve - description: Specify the name of the category to retrieve the category accordingly. @@ -571,15 +571,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the rules. name: page_number - - description: 'Specify the attributes to sort the rules. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -name, priority' + - description: 'Specify the attributes to sort the rules. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -name, priority.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of rules by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"priority_eq\":\"2,3\", \"name_cont\":\"Test\"} + For example: {\"priority_eq\":\"2,3\", \"name_cont\":\"Test\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: name, description' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: name, description.' isArray: true name: fields_to_retrieve - description: Specify the name of the rule to retrieve the rule. @@ -728,15 +728,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the URLs. name: page_number - - description: 'Specify the attributes to sort the URLs. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -created_at, -updated_at' + - description: 'Specify the attributes to sort the URLs. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -created_at, -updated_at.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of urls by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"risk_score_eq\":\"1,2\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"} + For example: {\"risk_score_eq\":\"1,2\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: url, risk_score' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: url, risk_score.' name: fields_to_retrieve - description: Specify the risk scores to retrieve the urls. isArray: true @@ -900,15 +900,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the reporters. name: page_number - - description: 'Specify the attributes to sort the reporters. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: reports_count, -email' + - description: 'Specify the attributes to sort the reporters. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: reports_count, -email.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of reporters by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"reputation_score_eq\":\"1,2\", \"reports_count_gt\":\"3\"} + For example: {\"reputation_score_eq\":\"1,2\", \"reports_count_gt\":\"3\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: email, reports_count' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: email, reports_count.' isArray: true name: fields_to_retrieve - description: Specify reputation score to retrieve the reporters. @@ -990,15 +990,15 @@ script: name: page_size - description: Specify a page number to retrieve the integration submissions. name: page_number - - description: 'Specify the attributes to sort the integration submissions. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: status, -id' + - description: 'Specify the attributes to sort the integration submissions. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: status, -id.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of integration submissions by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"status_eq\":\"complete\", \"risk_score_eq\":\"0,1\"} + For example: {\"status_eq\":\"complete\", \"risk_score_eq\":\"0,1\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: status, kind' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: status, kind.' isArray: true name: fields_to_retrieve - description: 'Specify the status to retrieve the integration submission. Some possible values are: ending, complete, target_not_found, error, running, or hash_not_found.' @@ -1083,15 +1083,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the attachment payloads. name: page_number - - description: 'Specify the attributes to sort the attachment payloads. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: risk_score, -id' + - description: 'Specify the attributes to sort the attachment payloads. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: risk_score, -id.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of attachment payloads by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"risk_score\":\"0,1\", \"created_at_gteq\":\"2020-04-13T10:48:16.834Z\"} + For example: {\"risk_score\":\"0,1\", \"created_at_gteq\":\"2020-04-13T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: md5, risk_score' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: md5, risk_score.' isArray: true name: fields_to_retrieve - description: Specify the risk scores to retrieve the attachment payloads. @@ -1166,14 +1166,14 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the comments. name: page_number - - description: 'Specify the attributes to sort the comments. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -created_at, body' + - description: 'Specify the attributes to sort the comments. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: -created_at, body.' name: sort_by - description: |- Specify the filters to filter the list of comments by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"body_format_eq\":\"json\", \"created_at_gteq\":\"2021-04-13T10:48:16.834Z\"} + For example: {\"body_format_eq\":\"json\", \"created_at_gteq\":\"2021-04-13T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: body, body_format' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: body, body_format.' isArray: true name: fields_to_retrieve - auto: PREDEFINED @@ -1386,15 +1386,15 @@ script: - defaultValue: '1' description: Specify a page number to retrieve the clusters. name: page_number - - description: 'Specify the attributes to sort the clusters. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: created_at, -updated_at' + - description: 'Specify the attributes to sort the clusters. Note: The default sort order for an attribute is ascending. Prefix the attributes with a hyphen to sort in descending order. For example: created_at, -updated_at.' isArray: true name: sort_by - description: |- Specify the filters to filter the list of clusters by attribute values. Note: Enter values in key-value JSON format. To separate multiple values of a single attribute, use commas. Add backslash(\) before quotes. Format accepted: {\"attribute1_operator \": \"value1, value2\", \"attribute2_operator\" : \"value3, value4\"} - For example: {\"risk_score_eq\":\"1,2\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"} + For example: {\"risk_score_eq\":\"1,2\", \"updated_at_gt\":\"2020-10-26T10:48:16.834Z\"}. name: filter_by - - description: 'Specify the fields to retrieve the mentioned attributes only. For example: unprocessed_reports_count, processed_reports_count' + - description: 'Specify the fields to retrieve the mentioned attributes only. For example: unprocessed_reports_count, processed_reports_count.' isArray: true name: fields_to_retrieve - description: Specify the tags to retrieve the cluster. @@ -1704,7 +1704,128 @@ script: - contextPath: Cofense.AttachmentPayload.relationships.reports.links.related description: Link to retrieve the detailed information of the report with attachments containing the payload. type: String - dockerimage: demisto/python3:3.10.13.72123 + - arguments: + - description: 'Specify ID of the report to retrieve the attachments.' + name: id + required: true + - defaultValue: '20' + description: 'Specify the number of attachments to retrieve per page. Note: Possible values are between 1 and 200.' + name: page_size + - defaultValue: '1' + description: 'Specify a page number to retrieve the attachments.' + name: page_number + - description: 'Specify the date and time of creation, from when to retrieve the attachments. Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc.' + name: created_at + - description: 'Specify the date and time of updation, from when to retrieve the attachments. Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc.' + name: updated_at + description: |- + Retrieves attachments based on provided report id in the command arguments. + For reported emails that contain attachments, Cofense Triage captures the attachment's filename and size. + name: cofense-report-attachment-list + outputs: + - contextPath: Cofense.Attachment.id + description: Unique identifier of the attachment. + type: String + - contextPath: Cofense.Attachment.type + description: Type of the resource of Cofense Triage. + type: String + - contextPath: Cofense.Attachment.links.self + description: Link of the resource. + type: String + - contextPath: Cofense.Attachment.attributes.filename + description: Name of the attachment file. + type: String + - contextPath: Cofense.Attachment.attributes.size + description: Attachment size in bytes. + type: Number + - contextPath: Cofense.Attachment.attributes.is_child + description: Boolean value indicating that attachment is child or not. + type: Boolean + - contextPath: Cofense.Attachment.attributes.created_at + description: Date and time, in ISO 8601 format, when the resource was created. + type: Date + - contextPath: Cofense.Attachment.attributes.updated_at + description: Date and time, in ISO 8601 format, when the resource was last updated. + type: Date + - contextPath: Cofense.Attachment.relationships.attachment_payload.links.self + description: Link to retrieve the attachment payload associated with the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.attachment_payload.links.related + description: Link to retrieve the detailed information of the attachment payload associated with the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.attachment_payload.data.type + description: Type indicating attachment payload. + type: String + - contextPath: Cofense.Attachment.relationships.attachment_payload.data.id + description: Unique identifier of the attachment payload associated with the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.parent.links.self + description: Link to retrieve the parent of the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.parent.links.related + description: Link to retrieve the detailed information of the parent of the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.parent.data.type + description: Type indicating the parent of the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.parent.data.id + description: Unique identifier of the parent of the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.reports.links.self + description: Link to retrieve the report associated with the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.reports.links.related + description: Link to retrieve the detailed information of the report associated with the attachment. + type: String + - contextPath: Cofense.Attachment.relationships.reports.data.type + description: Type indicating report. + type: String + - contextPath: Cofense.Attachment.relationships.reports.data.id + description: Unique identifier of the report associated with the attachment. + type: String + - arguments: + - description: |- + Specify the ID of the attachment to download the attachment file. + Note: To retrieve id, execute cofense-report-attachment-list command. + name: id + required: true + description: Downloads the attachment for the specified attachment ID. + name: cofense-report-attachment-download + outputs: + - contextPath: File.Size + description: File size in bytes. + type: String + - contextPath: File.SHA1 + description: SHA1 hash of file. + type: String + - contextPath: File.SHA256 + description: SHA256 hash of file. + type: String + - contextPath: File.SHA512 + description: SHA512 hash of file. + type: String + - contextPath: File.Name + description: File name. + type: String + - contextPath: File.SSDeep + description: SSDeep hash of the file. + type: String + - contextPath: File.EntryID + description: The entry ID of the file. + type: Unknown + - contextPath: File.Info + description: File information. + type: String + - contextPath: File.Type + description: The file type. + type: String + - contextPath: File.MD5 + description: MD5 hash of the file. + type: String + - contextPath: File.Extension + description: The file extension. + type: String + dockerimage: demisto/python3:3.10.13.83255 isfetch: true isremotesyncin: true runonce: false diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3_test.py b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3_test.py index 521682dc096f..b85e87745490 100644 --- a/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3_test.py +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/CofenseTriagev3_test.py @@ -1,5 +1,4 @@ import json -import io import time import os import pytest @@ -28,7 +27,7 @@ def util_load_json(path: str) -> dict: """Load a json to python dict.""" - with io.open(path, mode='r', encoding='utf-8') as f: + with open(path, mode='r', encoding='utf-8') as f: return json.loads(f.read()) @@ -1103,3 +1102,106 @@ def test_validate_report_attachment_payload_list_args_when_invalid_args_are_prov with pytest.raises(ValueError) as err: cofense_report_attachment_payload_list_command(mocked_client, args) assert str(err.value) == MESSAGES['REQUIRED_ARGUMENT'].format('id') + + +def test_cofense_report_attachment_list_command_when_invalid_args_are_provided(mocked_client): + """Test case scenario when the arguments provided are not valid.""" + + from CofenseTriagev3 import MESSAGES, cofense_report_attachment_list_command + + args = { + "id": None, + } + + with pytest.raises(ValueError) as err: + cofense_report_attachment_list_command(mocked_client, args) + assert str(err.value) == MESSAGES['REQUIRED_ARGUMENT'].format('id') + + +def test_cofense_report_attachment_list_command_when_empty_response_is_returned(mocked_client): + """Test case scenario for successful execution of cofense-report-attachment-list command with an empty + response. """ + + from CofenseTriagev3 import cofense_report_attachment_list_command + mocked_client.http_request.return_value = {"data": {}} + readable_output = "No attachments were found for the given argument(s)." + + # Execute + command_response = cofense_report_attachment_list_command(mocked_client, {'id': 'test'}) + # Assert + assert command_response.readable_output == readable_output + + +def test_cofense_report_attachment_list_command_when_valid_response_is_returned(mocked_client): + """Test case scenario for successful execution of cofense-report-attachment-list command.""" + + from CofenseTriagev3 import cofense_report_attachment_list_command + + response = util_load_json( + os.path.join("test_data", os.path.join("report_attachment", "report_attachment_list_response.json"))) + + mocked_client.http_request.return_value = response + + context_output = util_load_json( + os.path.join("test_data", os.path.join("report_attachment", "report_attachment_list_context.json"))) + + with open(os.path.join("test_data", os.path.join("report_attachment", "report_attachment_list.md")), 'r') as f: + readable_output = f.read() + + # Execute + args = {"id": "30339", "updated_at": "2020-10-21T20:30:24.185Z"} + + command_response = cofense_report_attachment_list_command(mocked_client, args) + # Assert + assert command_response.outputs_prefix == 'Cofense.Attachment' + assert command_response.outputs_key_field == "id" + assert command_response.outputs == context_output + assert command_response.readable_output == readable_output + assert command_response.raw_response == response + + +def test_cofense_report_attachment_download_command_when_invalid_args_are_provided(mocked_client): + """Test case scenario when the arguments provided are not valid.""" + + from CofenseTriagev3 import MESSAGES, cofense_report_attachment_download_command + + args = { + "id": None, + } + + with pytest.raises(ValueError) as err: + cofense_report_attachment_download_command(mocked_client, args) + assert str(err.value) == MESSAGES['REQUIRED_ARGUMENT'].format('id') + + +def test_cofense_report_attachment_download_command_when_valid_args_are_provided(mocked_client): + """Test case scenario when the arguments provided are valid.""" + + from CofenseTriagev3 import cofense_report_attachment_download_command + + with open(os.path.join("test_data", os.path.join("report_attachment", "report_attachment_download_response.xml")), 'r') as f: + response = f.read() + + # Mock response with the valid headers. + class MockResponse: + content = response + headers = {"Content-Disposition": """attachment; filename="xl%2FordStrings.xml"; filename*=UTF-8''xl%2FordStrings.xml"""} + + mocked_client.http_request.return_value = MockResponse + + args = {"id": "30339"} + command_response = cofense_report_attachment_download_command(mocked_client, args) + + # Assert for file name based on the header. + assert command_response["File"] == 'xl/ordStrings.xml' + + # Mock response with empty headers + MockResponse.headers = {} + + mocked_client.http_request.return_value = MockResponse + + args = {"id": "30339"} + command_response = cofense_report_attachment_download_command(mocked_client, args) + + # Assert for file name based on the attachment ID. + assert command_response["File"] == 'Attachment ID - 30339' diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/README.md b/Packs/CofenseTriage/Integrations/CofenseTriagev3/README.md index ba62796491e7..7a06eadfb6ac 100644 --- a/Packs/CofenseTriage/Integrations/CofenseTriagev3/README.md +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/README.md @@ -862,6 +862,230 @@ Attachment payloads identify the MIME type and MD5 and SHA256 hash signatures of >| 78 | image/png; charset=binary | 61da9c47fff9b04e59b951aa700c7980 | 7757f5392a8971b280464ae0d760b04980b82a9a2a3105c2bd6c9293ff7f9b9a | | 2020-10-21T20:57:56.940Z | 2020-10-21T20:57:56.940Z | +### cofense-report-attachment-list + +*** +Retrieves attachments based on provided report id in the command arguments. +For reported emails that contain attachments, Cofense Triage captures the attachment's filename and size. + +#### Base Command + +`cofense-report-attachment-list` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | Specify ID of the report to retrieve the attachments. | Required | +| page_size | Specify the number of attachments to retrieve per page. Note: Possible values are between 1 and 200. Default is 20. | Optional | +| page_number | Specify a page number to retrieve the attachments. Default is 1. | Optional | +| created_at | Specify the date and time of creation, from when to retrieve the attachments. Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc. | Optional | +| updated_at | Specify the date and time of updation, from when to retrieve the attachments. Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Cofense.Attachment.id | String | Unique identifier of the attachment. | +| Cofense.Attachment.type | String | Type of the resource of Cofense Triage. | +| Cofense.Attachment.links.self | String | Link of the resource. | +| Cofense.Attachment.attributes.filename | String | Name of the attachment file. | +| Cofense.Attachment.attributes.size | Number | Attachment size in bytes. | +| Cofense.Attachment.attributes.is_child | Boolean | Boolean value indicating that attachment is child or not. | +| Cofense.Attachment.attributes.created_at | Date | Date and time, in ISO 8601 format, when the resource was created. | +| Cofense.Attachment.attributes.updated_at | Date | Date and time, in ISO 8601 format, when the resource was last updated. | +| Cofense.Attachment.relationships.attachment_payload.links.self | String | Link to retrieve the attachment payload associated with the attachment. | +| Cofense.Attachment.relationships.attachment_payload.links.related | String | Link to retrieve the detailed information of the attachment payload associated with the attachment. | +| Cofense.Attachment.relationships.attachment_payload.data.type | String | Type indicating attachment payload. | +| Cofense.Attachment.relationships.attachment_payload.data.id | String | Unique identifier of the attachment payload associated with the attachment. | +| Cofense.Attachment.relationships.parent.links.self | String | Link to retrieve the parent of the attachment. | +| Cofense.Attachment.relationships.parent.links.related | String | Link to retrieve the detailed information of the parent of the attachment. | +| Cofense.Attachment.relationships.parent.data.type | String | Type indicating the parent of the attachment. | +| Cofense.Attachment.relationships.parent.data.id | String | Unique identifier of the parent of the attachment. | +| Cofense.Attachment.relationships.reports.links.self | String | Link to retrieve the report associated with the attachment. | +| Cofense.Attachment.relationships.reports.links.related | String | Link to retrieve the detailed information of the report associated with the attachment. | +| Cofense.Attachment.relationships.reports.data.type | String | Type indicating report. | +| Cofense.Attachment.relationships.reports.data.id | String | Unique identifier of the report associated with the attachment. | + + +#### Command Example +```!cofense-report-attachment-list id=30339 page_size=2``` + +#### Context Example +```json +{ + "Cofense": { + "Attachment": [ + { + "id": "30339", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339" + }, + "attributes": { + "filename": "Invoice.xlsm", + "size": 100000, + "is_child": false, + "created_at": "2023-04-09T13:25:28.540Z", + "updated_at": "2023-04-09T13:25:28.540Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30339/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "1452" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30339/parent" + } + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30339/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + }, + { + "id": "30340", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340" + }, + "attributes": { + "filename": "docProps/app.xml", + "size": 700, + "is_child": true, + "created_at": "2023-04-09T13:25:29.249Z", + "updated_at": "2023-04-09T13:25:29.249Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30340/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "74" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30340/parent" + }, + "data": { + "type": "attachments", + "id": "30339" + } + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30340/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + } + ] + } +} +``` + +#### Human Readable Output + +>### Attachment(s) +>|Attachment ID|File Name|File Size in Bytes|Is Child|Created At|Updated At| +>|---|---|---|---|---|---| +>| 30339 | Invoice.xlsm | 100000 | false | 2023-04-09T13:25:28.540Z | 2023-04-09T13:25:28.540Z | +>| 30340 | docProps/app.xml | 700 | true | 2023-04-09T13:25:29.249Z | 2023-04-09T13:25:29.249Z | + + +### cofense-report-attachment-download + +*** +Downloads the attachment for the specified attachment ID. + +#### Base Command + +`cofense-report-attachment-download` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | Specify the ID of the attachment to download the attachment file.
Note: To retrieve id, execute cofense-report-attachment-list command. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| File.Size | String | File size in bytes. | +| File.SHA1 | String | SHA1 hash of file. | +| File.SHA256 | String | SHA256 hash of file. | +| File.SHA512 | String | SHA512 hash of file. | +| File.Name | String | File name. | +| File.SSDeep | String | SSDeep hash of the file. | +| File.EntryID | Unknown | The entry ID of the file. | +| File.Info | String | File information. | +| File.Type | String | The file type. | +| File.MD5 | String | MD5 hash of the file. | +| File.Extension | String | The file extension. | + +#### Command example +```!cofense-report-attachment-download id=30``` +#### Context Example +```json +{ + "File": { + "EntryID": "3000@80068006-8006-8006-8006-800680068006", + "Extension": "xml", + "Type": "text/xml; charset=utf-8", + "MD5": "11111111111111111111111111111111", + "Name": "xl/sharedStrings.xml", + "SHA1": "1111111111111111111111111111111111111111", + "SHA256": "1111111111111111111111111111111111111111111111111111111111111111", + "SHA512": "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "SSDeep": "3:111111111111111111111111111111111111111111111111111111111111:111111111111111111111111", + "Size": 206, + "Info": "XML 1.0 document, ASCII text, with CRLF line terminators" + } +} +``` + +#### Human Readable Output + +>Uploaded file: xl/sharedStrings.xml Download + +>|Property|Value| +>|---|---| +>| Type | text/xml; charset=utf-8 | +>| Size | 206 bytes | +>| Info | XML 1.0 document, ASCII text, with CRLF line terminators | +>| MD5 | 11111111111111111111111111111111 | +>| SHA1 | 1111111111111111111111111111111111111111 | +>| SHA256 | 1111111111111111111111111111111111111111111111111111111111111111 | +>| SHA512 | 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 | +>| SSDeep | 3:111111111111111111111111111111111111111111111111111111111111:111111111111111111111111 | + + ### cofense-category-list *** Retrieves categories based on the provided parameters. @@ -2559,3 +2783,5 @@ The ability to mirror incident data has been added. * *cofense-threat-indicator-update* * *cofense-url-list* * *cofense-report-attachment-payload-list* +* *cofense-report-attachment-list* +* *cofense-report-attachment-download* diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_download_response.xml b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_download_response.xml new file mode 100644 index 000000000000..67a0a989fcc5 --- /dev/null +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_download_response.xml @@ -0,0 +1,6 @@ + + + + Click here to view the invoice + + \ No newline at end of file diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list.md b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list.md new file mode 100644 index 000000000000..345934445a3d --- /dev/null +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list.md @@ -0,0 +1,5 @@ +### Attachment(s) +|Attachment ID|File Name|File Size in Bytes|Is Child|Created At|Updated At| +|---|---|---|---|---|---| +| 30339 | Invoice.xlsm | 100000 | false | 2023-04-09T13:25:28.540Z | 2023-04-09T13:25:28.540Z | +| 30340 | docProps/app.xml | 700 | true | 2023-04-09T13:25:29.249Z | 2023-04-09T13:25:29.249Z | diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_context.json b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_context.json new file mode 100644 index 000000000000..d2bee9b80ba3 --- /dev/null +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_context.json @@ -0,0 +1,90 @@ +[ + { + "id": "30339", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339" + }, + "attributes": { + "filename": "Invoice.xlsm", + "size": 100000, + "is_child": false, + "created_at": "2023-04-09T13:25:28.540Z", + "updated_at": "2023-04-09T13:25:28.540Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30339/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "1452" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30339/parent" + } + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30339/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + }, + { + "id": "30340", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340" + }, + "attributes": { + "filename": "docProps/app.xml", + "size": 700, + "is_child": true, + "created_at": "2023-04-09T13:25:29.249Z", + "updated_at": "2023-04-09T13:25:29.249Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30340/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "74" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30340/parent" + }, + "data": { + "type": "attachments", + "id": "30339" + } + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30340/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + } +] \ No newline at end of file diff --git a/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_response.json b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_response.json new file mode 100644 index 000000000000..4f90fa32ceb4 --- /dev/null +++ b/Packs/CofenseTriage/Integrations/CofenseTriagev3/test_data/report_attachment/report_attachment_list_response.json @@ -0,0 +1,102 @@ +{ + "data": [ + { + "id": "30339", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339" + }, + "attributes": { + "filename": "Invoice.xlsm", + "size": 100000, + "is_child": false, + "created_at": "2023-04-09T13:25:28.540Z", + "updated_at": "2023-04-09T13:25:28.540Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30339/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "1452" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30339/parent" + }, + "data": null + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30339/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30339/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + }, + { + "id": "30340", + "type": "attachments", + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340" + }, + "attributes": { + "filename": "docProps/app.xml", + "size": 700, + "is_child": true, + "created_at": "2023-04-09T13:25:29.249Z", + "updated_at": "2023-04-09T13:25:29.249Z" + }, + "relationships": { + "attachment_payload": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/attachment_payload", + "related": "https://triage.example.com/api/public/v2/attachments/30340/attachment_payload" + }, + "data": { + "type": "attachment_payloads", + "id": "74" + } + }, + "parent": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/parent", + "related": "https://triage.example.com/api/public/v2/attachments/30340/parent" + }, + "data": { + "type": "attachments", + "id": "30339" + } + }, + "report": { + "links": { + "self": "https://triage.example.com/api/public/v2/attachments/30340/relationships/report", + "related": "https://triage.example.com/api/public/v2/attachments/30340/report" + }, + "data": { + "type": "reports", + "id": "47024" + } + } + } + } + ], + "meta": { + "record_count": 16, + "page_count": 8 + }, + "links": { + "first": "https://triage.example.com/api/public/v2/reports/47024/attachments?page%5Bnumber%5D=1&page%5Bsize%5D=2", + "next": "https://triage.example.com/api/public/v2/reports/47024/attachments?page%5Bnumber%5D=2&page%5Bsize%5D=2", + "last": "https://triage.example.com/api/public/v2/reports/47024/attachments?page%5Bnumber%5D=8&page%5Bsize%5D=2" + } +} \ No newline at end of file diff --git a/Packs/CofenseTriage/ReleaseNotes/2_1_20.md b/Packs/CofenseTriage/ReleaseNotes/2_1_20.md new file mode 100644 index 000000000000..93daecbc3bb6 --- /dev/null +++ b/Packs/CofenseTriage/ReleaseNotes/2_1_20.md @@ -0,0 +1,8 @@ + +#### Integrations + +##### Cofense Triage v3 + +- Added the new `cofense-report-attachment-list` command. +- Added the new `cofense-report-attachment-download` command. +- Updated the Docker image to: *demisto/python3:3.10.13.83255*. diff --git a/Packs/CofenseTriage/pack_metadata.json b/Packs/CofenseTriage/pack_metadata.json index 570283070abf..3bd23e89fed0 100644 --- a/Packs/CofenseTriage/pack_metadata.json +++ b/Packs/CofenseTriage/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Cofense Triage", "description": "Cofense Triage allows users to fetch reports by using the fetch incidents capability. It also provides commands to get entities like reporters, rules, categories, and more.", "support": "partner", - "currentVersion": "2.1.19", + "currentVersion": "2.1.20", "author": "Cofense", "url": "https://cofense.com/contact-support/", "email": "support@cofense.com",