From 3abec136b052284b7e3c0b22e341e37f302fd153 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-bot <73200433+splunk-soar-connectors-bot@users.noreply.github.com> Date: Mon, 18 Mar 2024 03:21:51 -0700 Subject: [PATCH] Merging next to main for release 2.5.1 (#18) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove semgrep workflow file * 'convert readme.html to manual_readme_content.md' * fix for message attachment type * release notes * licensing fix * Update README.md * removed error print duplicated * Bumped up the version of googleworkspaceforgmail from 2.5.0 to 2.5.1 * Release notes for version 2.5.1 * Release notes for version 2.5.1 --------- Co-authored-by: splunk-soar-connectors-admin Co-authored-by: Michał Posłuszny Co-authored-by: mposluszny-splunk <150343546+mposluszny-splunk@users.noreply.github.com> Co-authored-by: root --- LICENSE | 2 +- README.md | 4 +-- __init__.py | 2 +- gsgmail.json | 10 +++--- gsgmail_connector.py | 18 ++++++---- gsgmail_consts.py | 2 +- gsgmail_get_email.html | 2 +- gsgmail_list_users.html | 2 +- gsgmail_process_email.py | 2 +- gsgmail_view.py | 2 +- manual_readme_content.md | 73 ++++++++++++++++++++++++++++++++++++++++ readme.html | 38 --------------------- release_notes/2.5.1.md | 1 + 13 files changed, 99 insertions(+), 59 deletions(-) create mode 100644 manual_readme_content.md delete mode 100644 readme.html create mode 100644 release_notes/2.5.1.md diff --git a/LICENSE b/LICENSE index fe5e893..d0f6848 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2017-2023 Splunk Inc. + Copyright (c) 2017-2024 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 508d091..5b9d8bc 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ # G Suite for GMail Publisher: Splunk -Connector Version: 2.5.0 +Connector Version: 2.5.1 Product Vendor: Google Product Name: GMail Product Version Supported (regex): ".\*" -Minimum Product Version: 6.0.0 +Minimum Product Version: 6.1.1 Integrates with G Suite for various investigative and containment actions diff --git a/__init__.py b/__init__.py index ed269c4..04fd24e 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,6 @@ # File: __init__.py # -# Copyright (c) 2017-2023 Splunk Inc. +# Copyright (c) 2017-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/gsgmail.json b/gsgmail.json index 3116a6b..0350d8e 100644 --- a/gsgmail.json +++ b/gsgmail.json @@ -10,16 +10,16 @@ "package_name": "phantom_gsgmail", "product_vendor": "Google", "product_name": "GMail", - "min_phantom_version": "6.0.0", + "min_phantom_version": "6.1.1", "fips_compliant": true, "python_version": "3", "latest_tested_versions": [ "Cloud, May 26, 2023" ], - "app_version": "2.5.0", + "app_version": "2.5.1", "product_version_regex": ".*", - "license": "Copyright (c) 2017-2023 Splunk Inc.", - "utctime_updated": "2022-01-25T00:07:36.000000Z", + "license": "Copyright (c) 2017-2024 Splunk Inc.", + "utctime_updated": "2024-03-18T08:57:36.000000Z", "pip_dependencies": { "wheel": [ { @@ -1369,4 +1369,4 @@ } ] } -} +} \ No newline at end of file diff --git a/gsgmail_connector.py b/gsgmail_connector.py index c00749c..f3de87a 100644 --- a/gsgmail_connector.py +++ b/gsgmail_connector.py @@ -1,6 +1,6 @@ # File: gsgmail_connector.py # -# Copyright (c) 2017-2023 Splunk Inc. +# Copyright (c) 2017-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -259,7 +259,7 @@ def _parse_multipart_msg(self, action_result, msg, email_details, extract_attach email_details['email_headers'] = [] for part in msg.walk(): - type = part.get_content_type() + part_type = part.get_content_type() headers = self._get_email_headers_from_part(part) # split out important headers (for output table rendering) if headers.get('to'): @@ -274,13 +274,13 @@ def _parse_multipart_msg(self, action_result, msg, email_details, extract_attach disp = str(part.get('Content-Disposition')) file_name = part.get_filename() # look for plain text parts, but skip attachments - if type == 'text/plain' and 'attachment' not in disp: + if part_type == 'text/plain' and 'attachment' not in disp: charset = part.get_content_charset() or 'utf8' # decode the base64 unicode bytestring into plain text plain_body = part.get_payload(decode=True).decode(encoding=charset, errors="ignore") # Add to list of plan text bodies plain_bodies.append(plain_body) - if type == 'text/html' and 'attachment' not in disp: + if part_type == 'text/html' and 'attachment' not in disp: charset = part.get_content_charset() or 'utf8' # decode the base64 unicode bytestring into plain text html_body = part.get_payload(decode=True).decode(encoding=charset, errors="ignore") @@ -289,11 +289,15 @@ def _parse_multipart_msg(self, action_result, msg, email_details, extract_attach elif file_name and extract_attachments: attach_resp = None try: + if part_type.startswith("message/"): + content = part.get_payload(0).as_string() + else: + content = part.get_payload(decode=True) # Create vault item with attachment payload - attach_resp = Vault.create_attachment(part.get_payload(decode=True), container_id=container_id, file_name=file_name) + attach_resp = Vault.create_attachment(content, container_id=container_id, file_name=file_name) except Exception as e: message = self._get_error_message_from_exception(e) - self.error_print('Unable to add attachment: {} Error: {}').format(str(file_name), message) + return action_result.set_status(phantom.APP_ERROR, f"Unable to add attachment: {file_name} Error: {message}") if attach_resp.get('succeeded'): # Create vault artifact artifact = { @@ -460,7 +464,7 @@ def _handle_get_email(self, param): email_details_resp['parsed_plain_body'] = msg.get_payload(decode=True).decode(encoding=charset, errors="ignore") except Exception as e: message = self._get_error_message_from_exception(e) - self.error_print("Unable to add email body: {}").format(message) + self.error_print(f"Unable to add email body: {message}") action_result.add_data(email_details_resp) diff --git a/gsgmail_consts.py b/gsgmail_consts.py index c2d9364..6b316db 100644 --- a/gsgmail_consts.py +++ b/gsgmail_consts.py @@ -1,6 +1,6 @@ # File: gsgmail_consts.py # -# Copyright (c) 2017-2023 Splunk Inc. +# Copyright (c) 2017-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/gsgmail_get_email.html b/gsgmail_get_email.html index 4822039..23a5c1f 100644 --- a/gsgmail_get_email.html +++ b/gsgmail_get_email.html @@ -10,7 +10,7 @@ {% block widget_content %} + +- label - To fetch the emails from the given folder name (default - all folders). + **Note:-** Reply email in the email thread would not be ingested if you provide a specific label + in the configuration (eg. Inbox). It will ingest the reply email only if you leave the label + configuration parameter empty. +- ingest_manner - To select the oldest first or newest first preference for ingestion (default - + oldest first). +- first_run_max_emails - Maximum containers to poll for the first scheduled polling (default - + 1000). +- max_containers - Maximum containers to poll after the first scheduled poll completes (default - + 100). +- extract_attachments - Extract all the attachments included in emails. +- download_eml_attachments - Downloads the EML file attached with the mail. +- extract_urls - Extracts the URLs present in the emails. +- extract_ips - Extracts the IP addresses present in the emails. +- extract_domains - Extract the domain names present in the emails. +- extract_hashes - Extract the hashes present in the emails (MD5). diff --git a/readme.html b/readme.html deleted file mode 100644 index ef0907c..0000000 --- a/readme.html +++ /dev/null @@ -1,38 +0,0 @@ - - - -

Service Account

- This app requires a pre-configured service account to operate. Please follow the procedure outlined at this link to create a service account.
The following APIs will need to be enabled:
  • AdminSDK
  • GMail API
At the end of the creation process, the admin console should ask you to save the config as a JSON file. Copy the contents of the JSON file in the clipboard and paste it as the value of the key_json asset configuration parameter. -

Scopes

- Once the service account has been created and APIs enabled, the next step is to configure scopes on these APIs to allow the App to access them. Every action requires different scopes to operate, these are listed in the action documentation.
To enable scopes please complete the following steps: -
    -
  • Go to your G Suite domain's Admin console.
  • -
  • Select Security from the list of controls. If you don't see Security listed, select Show More, then select Security from the list of controls. If you can't see the controls, make sure you're signed in as an administrator for the domain.
  • -
  • Select API controls in the Access and data control section.
  • -
  • Select MANAGE DOMAIN WIDE DELEGATIONS in the Domain wide delegation section.
  • -
  • Select Add new in the API clients section
  • -
  • In the Client ID field enter the service account's Client ID. You can find your service account's client ID in the Service accounts credentials page or the service account JSON file (key named client_id).
  • -
  • In the One or More API Scopes field enter the list of scopes that you wish to grant access to the App. For example, to enable all the scopes required by this app enter: https://mail.google.com/, https://www.googleapis.com/auth/admin.directory.user.readonly, https://www.googleapis.com/auth/gmail.readonly
  • -
  • Click Authorize.
  • -
-

On-Poll

-
  • API provides created time of the email and gmail searches based on the received time of the email.
  • Use the large container numbers in asset to avoid any kind of data loss for emails which received at the same time.

  • -
    Configuration:
    -
      -
    • label - To fetch the emails from the given folder name (default - all folders).
      Note:- Reply email in the email thread would not be ingested if you provide a specific label in the configuration (eg. Inbox). It will ingest the reply email only if you leave the label configuration parameter empty.
    • -
    • ingest_manner - To select the oldest first or newest first preference for ingestion (default - oldest first).
    • -
    • first_run_max_emails - Maximum containers to poll for the first scheduled polling (default - 1000).
    • -
    • max_containers - Maximum containers to poll after the first scheduled poll completes (default - 100).
    • -
    • extract_attachments - Extract all the attachments included in emails.
    • -
    • download_eml_attachments - Downloads the EML file attached with the mail.
    • -
    • extract_urls - Extracts the URLs present in the emails.
    • -
    • extract_ips - Extracts the IP addresses present in the emails.
    • -
    • extract_domains - Extract the domain names present in the emails.
    • -
    • extract_hashes - Extract the hashes present in the emails (MD5).
    • -
    - - diff --git a/release_notes/2.5.1.md b/release_notes/2.5.1.md new file mode 100644 index 0000000..9641332 --- /dev/null +++ b/release_notes/2.5.1.md @@ -0,0 +1 @@ +* Fixed downloading `message/` attachment types [PAPP-33372] \ No newline at end of file