ExtraHop for IBM SOAR

Table of Contents


Release Notes

Version

Date

Notes

1.2.0

11/2024

Search Packet: function and playbook bug fix and enhancements

1.1.0

04/2023

Use mod_time instead of update_time in poller. Convert rules/workflows to playbooks

1.0.0

06/2022

Initial Release

1.2.0 Changes

In v1.2.0 the following updates are implemented in the Search Packets function and playbook:

  • Handle non 200 status code correctly

  • Add 2 new ExtraHop parameters: decrypt_files and include_secrets

  • Write a note to the case when the search results attachment is greater than the maximum allowed by SOAR

  • Search Packets example playbook Active From input parameter is now mandatory

  • When the limit_search_duration is not specified in the search packets function, the function timeout value is set to the maximum search duration allowed by ExtraHop: 5 minutes.

1.1 Changes

In v1.1, the existing rules and workflows have been replaced with playbooks. This change is made to support the ongoing, newer capabilities of playbooks. Each playbook has the same functionality as the previous, corresponding rule/workflow.

If upgrading from a previous release, notice that the previous release’s rules/workflows remain in place. Both sets of rules and playbooks are active. For manual actions, playbooks will have the same name as it’s corresponding rule, but with “(PB)” added at the end.

You can continue to use the rules/workflows. But migrating to playbooks will provide greater functionality along with future app enhancements and bug fixes.

NOTE Starting with version 1.1.0 of the ExtraHop app for SOAR:

  • The poller uses ExtraHop detection mod_time field to determine which detections to pull in to SOAR.

  • The poller includes an optional polling_lookback parameter in the app.config that can be used to look back the specified number of minutes when the poller starts or restarts to pull in “older” detections. If not specified in the app.config, the poller uses a look back of zero minutes.

  • The function ExtraHop Reveal(x) search detections takes an optional mod_time parameter used for searching detections in ExtraHop.


Overview

IBM Security SOAR app for ExtraHop

screenshot: main

ExtraHop is a cybersecurity cloud-native solution that provides AI-based network intelligence to help enterprises detect and respond to advanced threats.

The ExtraHop App for IBM SOAR escalates ExtraHop detections into IBM Security SOAR as an incident/case and facilitates manual enrichment and remediation actions against an ExtraHop RevealX 360 environment in the IBM SOAR Platform.

Key Features

The ExtraHop App provides the following functionality:

  • A poller which gathers current detections from ExtraHop and escalates to the SOAR platform as cases/incidents.

  • Functions to get, search and update detections.

  • Functions to get and add detection notes.

  • Functions to get and search devices.

  • Functions to get, create and assign tags.

  • Functions get and set the watchlist.

  • A function to get activitymaps.


Requirements

This app supports the IBM Security QRadar SOAR Platform and the IBM Security QRadar SOAR for IBM Cloud Pak for Security.

SOAR platform

The SOAR platform supports two app deployment mechanisms, Edge Gateway (also known as App Host) and integration server.

If deploying to a SOAR platform with an App Host, the requirements are:

  • SOAR platform >= 51.0.0.0.

  • The app is in a container-based format (available from the AppExchange as a zip file).

If deploying to a SOAR platform with an integration server, the requirements are:

  • SOAR platform >= 51.0.0.0.

  • The app is in the older integration format (available from the AppExchange as a zip file which contains a tar.gz file).

  • Integration server is running resilient-circuits>=51.0.2.2.0.

  • If using an API key account, make sure the account provides the following minimum permissions:

    Name

    Permissions

    Org Data

    Read

    Function

    Read

    incident

    Create

    all_incidents

    Read

    all_incidents_fields

    Edit

    layouts

    Read, Edit

The following SOAR platform guides provide additional information:

  • Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.

  • Integration Server Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.

  • System Administrator Guide: provides the procedure to install, configure and deploy apps.

The above guides are available on the IBM Documentation website at ibm.biz/soar-docs. On this web page, select your SOAR platform version. On the follow-on page, you can find the Edge Gateway Deployment Guide, App Host Deployment Guide, or Integration Server Guide by expanding Apps in the Table of Contents pane. The System Administrator Guide is available by expanding System Administrator.

Cloud Pak for Security

If you are deploying to IBM Cloud Pak for Security, the requirements are:

  • IBM Cloud Pak for Security >= 1.10.

  • Cloud Pak is configured with an Edge Gateway.

  • The app is in a container-based format (available from the AppExchange as a zip file).

The following Cloud Pak guides provide additional information:

  • Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings. From the Table of Contents, select Case Management and Orchestration & Automation > Orchestration and Automation Apps.

  • System Administrator Guide: provides information to install, configure, and deploy apps. From the IBM Cloud Pak for Security IBM Documentation table of contents, select Case Management and Orchestration & Automation > System administrator.

These guides are available on the IBM Documentation website at ibm.biz/cp4s-docs. From this web page, select your IBM Cloud Pak for Security version. From the version-specific IBM Documentation page, select Case Management and Orchestration & Automation.

Proxy Server

The app does support a proxy server.

Python Environment

Python 3.9, 3.11, and 3.12 are officially supported. When deployed as an app, the app runs on Python 3.11. Additional package dependencies may exist for each of these packages:

  • resilient-circuits>=51.0.2.2.0

  • retry2 ~= 0.9

ExtraHop Development Version

This app has been implemented using:

Product Name

Product Version

API URL

API Version

ExtraHop RevealX 360

9.8.11834

https://<extrahop_cloud_api_url> or https://<sensor_hostname_or_ip>

v1

Configuration

ExtraHop standalone sensor
  • The ExtraHop system must be configured to allow API key generation for the user.

  • A valid API key must be generated for the ExtraHop app user.

ExtraHop Cloud Services
  • REST API access must be enabled for the user.

  • Create REST API credentials (key ID and key secret token) for the ExtraHop app user.

See: Cloud Service api setup

Permission

  • REST API access must be enabled for the account that IBM SOAR is communicating with as specified in the App configuration file.


Installation

Install

  • To install or uninstall an App or Integration on the SOAR platform, see the documentation at ibm.biz/soar-docs.

  • To install or uninstall an App on IBM Cloud Pak for Security, see the documentation at ibm.biz/cp4s-docs and follow the instructions above to navigate to Orchestration and Automation.

App Configuration

The following table provides the settings you need to configure the app. These settings are made in the app.config file. See the documentation discussed in the Requirements section for the procedure.

Config

Required

Example

Description

extrahop_rx_host_url

Yes

https://<extrahop-hostname-or-IP-api-address>

Cloud api service url or sensor url.

extrahop_rx_api_version

Yes

v1

Version of (API) access to ExtraHop.

extrahop_rx_cloud_console_url

*Yes

https://<extrahop-hostname-or-IP-console-address>

Cloud service console url for cloud-based ExtraHop instance.

extrahop_rx_key_id

*Yes

1ab2ef34gh56ijklm012n3abc4

Key ID setting if ExtraHop cloud instance used by the integration.

extrahop_rx_key_secret

*Yes

ab2ef34gh56ijklm012n3abc41ab2ef34gh56ijklm012n3abc4

Key secret setting if ExtraHop cloud instance used by the integration.

extrahop_rx_api_key

*Yes

ab2ef34GH56ijkLM012n3abc41ab2ef34GH56ijklm4

API key setting if standalone sensor used by the integration.

polling_interval

Yes

60

Interval to wait between polls of ExtraHop for detections.

polling_lookback

No

120

Number of minutes to look back for new ExtraHop detections the first time the app starts or restarts.

polling_filters

No

polling_filters="risk_score_min": 80, "category": ["sec.exploit"], "types": ["interactive_traffic_ssh", "interactive_traffic_shell"],  "status": [".none", "new", "in_progress", "acknowledged"], "resolution": [".none" ]

Filter detection results returned to SOAR using key/value pairs.

extrahop_cafile

No

<path to cert file> or false

TLS certificate setting. Can be a path to a CA bundle or ‘false’

https_proxy

No

https://proxy:443 or proxy:443

Optional setting for an https proxy if required.

NOTE: The integration can use either the ExtraHop Cloud Service or an ExtraHop standalone sensor.

NOTE: If connecting to an ExtraHop cloud instance, the setting extrahop_rx_api_key should be set to a blank value or alteratively commented out.

NOTE: If connecting to a standalone sensor, the settings extrahop_rx_key_id and extrahop_rx_key_secret should be set to a blank value or alternatively commented out.

Custom Layout

When the poller starts running, a new incident tab is created as shown below. If the poller is not configured to run, the custom layout can be configured manually.

  • Import the Data Tables and Custom Fields like the screenshot below:

  • Create a new ExtraHop incident tab in Layouts as follows:

  1. Navigate to the ‘Customization Settings’ and select the Layouts tab.

  2. Click on ‘Incident Tabs’.

  3. Add a new incident tab named ‘ExtraHop’.

  4. Drag and Drop the ‘ExtraHop Update Notification’ custom property onto the ExtraHop tab.

  5. Create new heading ‘ExtraHop Properties’ in the ExtraHop tab.

  6. Drag and Drop the ExtraHop the remaining custom properties under the new heading as shown below.

  7. Create new heading ‘ExtraHop Details’ in the ExtraHop tab.

  8. Drag and drop the ExtraHop data tables under the new heading as shown below.

  9. Click Save.

The following screenshot shows the ExtraHop properties and data tables added to the ExtraHop tab:

screenshot: custom_layouts


Poller - ExtraHop Escalate Detections

The ExtraHop integration poller starts querying ExtraHop for detections as soon as the app begins running.

The poller provides the following functionality.

  • For any new detections discovered, creates a matching incident in the SOAR platform.

  • The ExtraHop detections Ticket ID is assigned the SOAR case value.

  • The playbook Extrahop Reveal(x): Update Case (PB) is triggered automatically to update an incident/case.

  • The automatic playbook enhances the case/incident by adding artifacts and data tables with detection and device information from the matching ExtraHop detection.

  • Can be configured to filter the detections which are escalated to the SOAR cases.

  • Closes SOAR case if the corresponding ExtraHop detections are closed.

  • Closes ExtraHop detections if the corresponding SOAR cases are closed.

  • Updates a notification property in the ExtraHop custom tab if information for a SOAR case if the corresponding ExtraHop detection is updated.

  • Adds a note to an ExtraHop detection when a matching SOAR case is created.

NOTE Starting with version 1.1.0 of the ExtraHop app for SOAR:

  • The poller uses ExtraHop detection mod_time field to determine which detections to pull in to SOAR.

  • The poller includes an optional polling_lookback parameter in the app.config that can be used to look back the specified number of minutes when the poller starts or restarts to pull in “older” detections. If not specified in the app.config, the poller uses a look back of zero minutes.

The following screenshot shows examples of SOAR incidents created by the poller from ExtraHop detections:

screenshot: fn-extrahop-revealx-incidents

The following screenshot shows an example of a SOAR incident Details tab created by the poller:

screenshot: fn-extrahop-revealx-incident-details

The following screenshot shows an example of custom properties in the ExtraHop tab of a SOAR incident created by the poller:

screenshot: fn-extrahop-revealx-incident-properties

The following screenshot shows an example of an ExtraHop detection update notification in the ExtraHop tab of a SOAR incident created by the poller:

screenshot: fn-extrahop-revealx-incident-notification

The following screenshot shows examples of artifacts added to a SOAR incident created by the poller:

screenshot: fn-extrahop-revealx-incident-artifacts

NOTE: See the data tables section for examples of data tables updated by the poller.


Function - Extrahop Reveal(x) add detection note

Add a note to an ExtraHop detection. Parameters detection_id, note. (Optional) update_time.

screenshot: fn-extrahop-revealx-add-detection-note

The function provides the following functionality.

  • Adds a note to a detection in the ExtraHop environment. The original note is overwritten.

NOTE: The original note is overwritten.

NOTE: Add detection note will fail if Detection Tracking is enabled on ExtraHop.

An example playbook that uses this SOAR function is Extrahop Reveal(x) Update Detection (PB).

  • A note is added to the ExtraHop detection when a matching SOAR case is closed.

The automatic data table playbook Extrahop Reveal(x): Update Detection (PB) is triggered when a SOAR case is closed.

The following screenshot shows an example of a note added to an ExtraHop detection:

screenshot: fn-extrahop-revealx-add-detection-note-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_detection_id

number

No

-

Extrahop detection ID

extrahop_note

text

No

-

ExtraHop note object

extrahop_update_time

number

No

-

(Optional) Return detections that were updated on or after the specified date, expressed in milliseconds since the epoch.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": "success"
  },
  "inputs": {
    "extrahop_detection_id": 4294967305,
    "extrahop_note": "\nIBM SOAR 10/04/2023 15:36:28\n[SOAR Case - 3080](https://host0.ibm.com:443/#incidents/3080)\nIBM SOAR 10/04/2023 14:00:50\n[SOAR Case - 3390](https://host1.ibm.com:443/#incidents/3390)\nIBM SOAR 2023-04-10 14:18:35\n[SOAR case - \u00273390\u0027](Closed with resolution summary: \u0027Not an issue\u0027)",
    "extrahop_update_time": 0
  },
  "metrics": {
    "execution_time_ms": 4470,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:18:48",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

##  ExtraHop - pb_extrahop_rx_update_detection pre processing script ##
import re
inputs.extrahop_detection_id = incident.properties.extrahop_detection_id

UPD_DET_DATETIME = playbook.functions.results.get_detection_note_result.metrics.get("timestamp", None)
SUMMARY = re.sub('<[^<]+?>', '', incident.resolution_summary.content)


def get_current_note():
    # Get old note
    note = ''
    get_detection_note_content = playbook.functions.results.get_detection_note_result.content
    note_obj = get_detection_note_content.get("result", {})
    if not note_obj:
        raise ValueError("Existing ExtraHop detection note not found.")
    note = note_obj.get("note", None)
    return note


def make_summary_note():
    # Make a  note.
    summary_note = "IBM SOAR {}\n".format(UPD_DET_DATETIME)
    summary_note += "[SOAR case - '{}'](Closed with resolution summary: '{}')" \
    .format(incident.id, SUMMARY)
    return summary_note

# Processing
def main():
    detection_note = get_current_note()
    inputs.extrahop_note = '\n'.join([detection_note if detection_note else "", make_summary_note()])
    inputs.extrahop_update_time = 0
main()

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_update_detection post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_add_detection_note"
PB_NAME = "Extrahop Reveal(x): Update Detection"
results = playbook.functions.results.add_detection_note_result
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    detection_id = INPUTS.get("extrahop_detection_id", None)
    if CONTENT:
        result = CONTENT.get("result", None)
        if result == "success":
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Successfully added closure resolution note to " \
                        "ExtraHop detection <b>{1}</b> for SOAR function <b>{2}</b> with parameters <b>{3}</b>."\
                .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        elif result.get("error"):
            note_text += "ExtraHop Integration: Playbook <b>{0}</b>: Failed to add closure resolution note to ExtraHop " \
                         "detection <b>{1}</b> for SOAR function <b>{2}</b> with parameters <b>{3}</b>."\
                .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
            note_text += "<br>Error code: <b>{0}</b>, Error <b>{1}<b>.".format(result.get("error"), result.get("text"))
        elif result == "failed":
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Failed to add closure resolution note to ExtraHop " \
                        "detection <b>{1}</b> for SOAR function <b>{2}</b> with parameters <b>{3}</b>."\
                .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        else:
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Failed to add closure resolution note to ExtraHop " \
                        "detection <b>{1}</b> with unexpected response for SOAR function <b>{2}</b> with parameters <b>{3}</b>."\
                .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    else:
        note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to add closure resolution note to ExtraHop detection <b>{1}</b> for SOAR function <b>{2}</b> with parameters" \
                     " <b>{3}</b> ."\
            .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) assign tag

Assign a tag to a list of devices ids forExtrahop Reveal(x). Parameters tag_id. devices_ids.

screenshot: fn-extrahop-revealx-assign-tag

The function provides the following functionality.

  • Assigns a tag to a list of device ids discovered in the ExtraHop environment.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Assign Tag (PB).

  • A note is added to the SOAR incident with the status of the action.

The playbook is initiated by the manual data table menu item Extrahop Reveal(x): Assign Tag (PB) for data table ExtraGop Devices.

screenshot: fn-extrahop-revealx-assign-tag-action

screenshot: fn-extrahop-revealx-assign-tag-action_2

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-assign-tag-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_device_ids

text

No

-

Comma or newline seperated list of device ids.

extrahop_tag_id

number

No

-

The unique identifier for the tag.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": "success"
  },
  "inputs": {
    "extrahop_device_ids": "4294967313",
    "extrahop_tag_id": 21
  },
  "metrics": {
    "execution_time_ms": 4046,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:21:27",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

tag_name = playbook.inputs.extrahop_tag_name
get_tags_content = playbook.functions.results.get_tags_results.get("content", {})
inputs.extrahop_device_ids = str(row.devs_id)
if tag_name is None:
    raise ValueError("The tag name is not set")
inputs.extrahop_tag_id = None
for tag in get_tags_content.get("result", []):
    if tag_name == tag.get("name", None):
        inputs.extrahop_tag_id = tag.get("id", None)
        break
if not inputs.extrahop_tag_id:
    raise ValueError("Tag {} not found.".format(tag_name))

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_assign_tag post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_assign_tag"
PB_NAME = "Extrahop Reveal(x): Assign Tag"
results = playbook.functions.results.assign_tag_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = u''
    tag_name = playbook.inputs.extrahop_tag_name
    tag = INPUTS.get("extrahop_tag_name")
    if CONTENT:
        result = CONTENT.get("result", None)
        if result == "success":
            device_id = INPUTS.get("extrahop_device_ids")
            tag_id = INPUTS.get("extrahop_tag_id")
            note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Successfully assigned tag <b>'{1}'</b> with id <b>{2}</b> to device id <b>{3}</b> for SOAR " \
                        "function <b>{4}</b> with parameters:<br><b>{5}</b>.".format(PB_NAME, tag_name, tag_id, device_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

        elif result == "failed":
            note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Failed to assign tag <b>{1}</b> with id <b>{2}</b> to device id <b>{3}</b> for " \
                        "SOAR function <b>{4}</b> with parameters:<br><b>{5}</b>.".format(PB_NAME, tag_name, tag_id, device_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        else:
            note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Assign tag <b>{1}</b> with id <b>{2}</b> to device id <b>{3}</b> failed with unexpected " \
                        "response for SOAR function <b>{4}</b> with parameters:<br><b>{5}</b>.".format(PB_NAME, tag_name, tag_id, device_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    else:
        note_text += "ExtraHop Reveal(x): Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to assign tag <b>{1}</b> with id  <b>{2}</b> to device id <b>{3}</b> for SOAR function <b>{4}</b> with parameters:<br><b>{5}</b>."\
            .format(PB_NAME, tag_name, tag_id, device_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) create tag

Create a new tag for Extrahop Reveal(x). Parameter tag_name.

screenshot: fn-extrahop-revealx-create-tag

The function provides the following functionality.

  • Creates a new tag in the ExtraHop environment.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Create Tag (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table Extrahop Tags is updated.

The playbook is initiated by the menu item Extrahop Reveal(x): Create Tag (PB).

screenshot: fn-extrahop-revealx-create-tag-action

screenshot: fn-extrahop-revealx-create-tag-action_2

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-create-tag-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_tag_name

text

No

-

The string value for an ExtraHop tag name.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": "success"
  },
  "inputs": {
    "extrahop_tag_name": "SOAR-Testing-tag"
  },
  "metrics": {
    "execution_time_ms": 7343,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 13:43:35",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

inputs.extrahop_tag_name = playbook.inputs.extrahop_tag_name
if inputs.extrahop_tag_name is None:
    raise ValueError("The tag name is not set")

Example Function Post Process Script:

##  ExtraHop - wf_extrahop_rx_create_tag post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_create_tag"
PB_NAME = "Extrahop Reveal(x): Create Tag"
results = playbook.functions.results.create_tag_result
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]

# Processing

note_text = u''
tag = INPUTS.get("extrahop_tag_name")
if CONTENT:
    result = CONTENT.get("result", None)
    if result == "success":
        playbook.addProperty("tag_created", {})
        tag = INPUTS.get("extrahop_tag_name")
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Successfully created tag <b>'{1}'</b> for SOAR " \
                    "function <b>{2}</b> with parameters:<br><b>{3}</b>.".format(PB_NAME, tag, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    elif result == "failed":
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Failed to create tag <b>'{1}'</b> for " \
                    "SOAR function <b>{2}</b> with parameters:<br><b>{3}</b>.".format(PB_NAME, tag, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    elif result == "exists":
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: A 422 (tag name exists) error was thrown while to create tag <b>'{1}'</b> for " \
                    "SOAR function <b>{2}</b> with parameters:<br><b>{3}</b>.".format(PB_NAME, tag, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    else:
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: Create tag <b>'{1}'</b> failed with unexpected " \
                    "response for SOAR function <b>{2}</b> with parameters:<br><b>{3}</b>.".format(PB_NAME, tag, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
else:
    note_text += "ExtraHop Reveal(x): Playbook<b>{0}</b>: There was <b>no</b> result returned while attempting " \
                 "to create a tag <b>'{1}'</b>for SOAR function <b>{2}</b> with parameters:<br><b>{3}</b> ."\
            .format(PB_NAME, tag, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

incident.addNote(helper.createRichText(note_text))



Function - Extrahop Reveal(x) get activitymaps

Get activitymap information from Extrahop Reveal(x). Optional parameter activitymap_id.

screenshot: fn-extrahop-revealx-get-activitymaps

The function provides the following functionality.

  • Retrieves information on activitymaps in the ExtraHop environment.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Get Activitymaps (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table ExtraHop Activitymaps is updated.

The playbook is initiated by the incident menu item Extrahop Reveal(x): Get Activitymaps (PB).

screenshot: fn-extrahop-revealx-get-activitymaps-action

The following screenshot shows an example of the data table updated by the function.

screenshot: fn-extrahop-revealx-get-activitymaps-datatable

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-get-activitymaps-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_activitymap_id

number

No

-

The unique identifier for the activity map.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "description": "testing SOAR app",
        "id": 1,
        "mod_time": 1680790675151,
        "mode": "2dforce",
        "name": "My-activity-map",
        "owner": "owner@example.com",
        "rights": [
          "view"
        ],
        "short_code": "6Tk88",
        "show_alert_status": false,
        "walks": [
          {
            "origins": [
              {
                "object_id": 4294967298,
                "object_type": "device"
              }
            ],
            "steps": [
              {
                "relationships": [
                  {
                    "protocol": "any",
                    "role": "any"
                  }
                ]
              },
              {
                "relationships": [
                  {
                    "protocol": "aaa",
                    "role": "server"
                  }
                ]
              }
            ]
          }
        ],
        "weighting": "bytes"
      },
      {
        "description": "Testing SOAR app",
        "id": 2,
        "mod_time": 1680790704719,
        "mode": "2dforce",
        "name": "My-activity-map-2",
        "owner": "owner@example.com",
        "rights": [
          "view"
        ],
        "short_code": "mnKTM",
        "show_alert_status": false,
        "walks": [
          {
            "origins": [
              {
                "object_id": 100,
                "object_type": "device_group"
              }
            ],
            "steps": [
              {
                "relationships": [
                  {
                    "protocol": "any",
                    "role": "any"
                  }
                ]
              }
            ]
          }
        ],
        "weighting": "bytes"
      }
    ]
  },
  "inputs": {},
  "metrics": {
    "execution_time_ms": 2996,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 13:42:33",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

None

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_get_activitymaps post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_get_activitymaps"
PB_NAME = "Extrahop Reveal(x): Get Activity Maps"
results = playbook.functions.results.get_activitymap_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
DATA_TABLE = "extrahop_activitymaps"
DATA_TBL_FIELDS = ["ams_description", "ams_id", "mode", "ams_name", "owner", "rights", "short_code",
                   "show_alert_status", "walks", "weighting"]
# Processing
def main():
    note_text = ''
    if CONTENT:
        ams = CONTENT.get("result")
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: There were <b>{1}</b> Activity Maps returned for SOAR " \
                    "function <b>{2}</b> with parameters <b>{3}</b>.".format(PB_NAME, len(ams), FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        if ams:
            for am in ams:
                newrow = incident.addRow(DATA_TABLE)
                newrow.query_execution_date = QUERY_EXECUTION_DATE
                newrow.mod_time = am.get("mod_time", None)
                for f1 in DATA_TBL_FIELDS:
                    f2 = f1
                    if f1.startswith("ams_"):
                        f2 = f1.split('_', 1)[1]
                    if am[f2] is None:
                        newrow[f1] = am[f2]
                    if isinstance(am[f2], list):
                        if f1 in ["walks"]:
                            obj_cnt = 0
                            tbl = u''
                            for w in am[f2]:
                                for kw, vw in w.items():
                                    if kw == "origins":
                                        tbl += "<div><b>origins:</b></div>"
                                        for o in vw:
                                            for k, v in o.items():
                                                tbl += u"<div><b>&emsp;{0}:</b>{1}</div>".format(k, v)
                                        tbl += "<br>"
                                    elif kw == "steps":
                                        tbl += "<div><b>steps:</b></div>"
                                        for s in vw:
                                            relationships = s.get("relationships")
                                            if relationships:
                                                tbl += "<div><b>&emsp;relationships:</b></div>"
                                                for r in relationships:
                                                    for k, v in r.items():
                                                        tbl += "<div><b>&emsp;&emsp;{0}:</b>{1}</div>".format(k, v)
                                                tbl += "<br>"
                                        tbl += "<br>"
                                    else:
                                        tbl += "<div><b>{}:</b></div>".format(kw)
                                        tbl += "<div><b>&emsp{}</b></div>".format(vw)
                            tbl += "<br>"
                            obj_cnt += 1
                            newrow[f1] = tbl
                        else:
                            newrow[f1] = "{}".format(", ".join(am[f2]))
                    elif isinstance(am[f2], (bool, dict)):
                        newrow[f1] = str(am[f2])
                    else:
                        newrow[f1] = "{}".format(am[f2])
            note_text += "<br>The data table <b>{0}</b> has been updated".format("Extrahop Activitymaps")
    else:
        note_text += "ExtraHop Reveal(x): Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to get activitymaps for SOAR function <b>{1}</b> with parameters <b>{2}</b>." \
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) get detection note

Get a note from an ExtraHop detection. Parameter detection_id.

screenshot: fn-extrahop-revealx-get-detection-note

The function provides the following functionality.

  • Gets the current note from a detection in the ExtraHop environment.

NOTE: Get detection note will fail if Detection Tracking is enabled on ExtraHop.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Update Detection (PB).

  • The current note is retrieved from the ExtraHop detection when a matching SOAR incident is closed.

The automatic data table playbook Extrahop Reveal(x): Update Detection (PB) is initiated when a SOAR case/incident is closed.

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_detection_id

number

No

-

Extrahop detection ID

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": {
      "author": "rest_api_id_33ovi...",
      "note": "\nIBM SOAR 10/04/2023 15:36:28\n[SOAR Case - 3080](https://host0.ibm.com:443/#incidents/3080)\nIBM SOAR 10/04/2023 14:00:50\n[SOAR Case - 3390](https://host1.ibm.com:443/#incidents/3390)",
      "update_time": 1681150711820
    }
  },
  "inputs": {
    "extrahop_detection_id": 4294967305
  },
  "metrics": {
    "execution_time_ms": 447,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:18:35",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

inputs.extrahop_detection_id = incident.properties.extrahop_detection_id

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_update_detection post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_get_detection_note"
PB_NAME = "Extrahop Reveal(x): Update Detection"
results = playbook.functions.results.get_detection_note_result
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    if CONTENT:
        result = CONTENT.get("result", None)
        if result:
            note = result.get("note", None)
            if note:
                playbook.addProperty("get_note_ok", {})
            else:
                note_text += "ExtraHop Integration: Playbook <b>{0}</b>: Get detection note failed for " \
                             "SOAR function <b>{1}</b> with parameters <b>{2}</b>."\
                    .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        elif CONTENT.get("error", None):
            note_text += u"ExtraHop Integration: Playbook <b>{0}</b>: Get detection note failed for " \
                        "SOAR function <b>{1}</b> with parameters <b>{2}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
            note_text += "<br>Error code: <b>{0}</b>, Error <b>{1}<b>.".format(CONTENT.get("error"), CONTENT.get("text"))
    else:
        note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to get a detection note for SOAR function <b>{1}</b> with parameters <b>{2}</b>."\
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    if note_text:
        incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) get detections

Get detections information from Extrahop Reveal(x). Optional parameter extrahop_detection_id.

screenshot: fn-extrahop-revealx-get-detections

The function provides the following functionality.

  • Retrieves information on detections in the ExtraHop environment.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Update Case (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table ExtraHop Detections is updated.

The playbook is initiated by the automatic Extrahop Reveal(x): Update Case (PB). The following screenshots show an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-get-detections-datatable screenshot: fn-extrahop-revealx-get-detections-datatable_2 screenshot: fn-extrahop-revealx-get-detections-datatable_3

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-get-detections-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_detection_id

number

No

-

Extrahop detection ID

extrahop_limit

number

No

-

(Optional) Limit the number of devices returned to the specified maximum number.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": {
      "appliance_id": 1,
      "assignee": "admin@example.com",
      "categories": [
        "sec",
        "sec.caution"
      ],
      "description": "[pc3](#/metrics/devices/44522fe6bb834d83a3b0a142b7da750a.0e3da802a0b30000/overview?from=1681140240\u0026interval_type=DT\u0026until=1681140270) sent an HTTP request that included a suspicious host in the request header. This host is considered suspicious based on threat intelligence found in your ExtraHop system. Confirm whether [pc3](#/metrics/devices/44522fe6bb834d83a3b0a142b7da750a.0e3da802a0b30000/overview?from=1681140240\u0026interval_type=DT\u0026until=1681140270) is the victim of a malware or phishing attack.\n\nSuspicious hostname linked to this detection:\n* zupertech.com",
      "end_time": 1681140270000,
      "id": 4294967305,
      "is_user_created": false,
      "mitre_tactics": [
        {
          "id": "TA0001",
          "name": "Initial Access",
          "url": "https://attack.mitre.org/tactics/TA0001"
        },
        {
          "id": "TA0010",
          "name": "Exfiltration",
          "url": "https://attack.mitre.org/tactics/TA0010"
        },
        {
          "id": "TA0011",
          "name": "Command and Control",
          "url": "https://attack.mitre.org/tactics/TA0011"
        }
      ],
      "mitre_techniques": [
        {
          "id": "T1041",
          "legacy_ids": [
            "T1041"
          ],
          "name": "Exfiltration Over C2 Channel",
          "url": "https://attack.mitre.org/techniques/T1041"
        },
        {
          "id": "T1189",
          "legacy_ids": [
            "T1189"
          ],
          "name": "Drive-by Compromise",
          "url": "https://attack.mitre.org/techniques/T1189"
        },
        {
          "id": "T1566",
          "legacy_ids": [
            "T1192"
          ],
          "name": "Phishing",
          "url": "https://attack.mitre.org/techniques/T1566"
        },
        {
          "id": "T1573",
          "legacy_ids": [
            "T1024",
            "T1032",
            "T1079"
          ],
          "name": "Encrypted Channel",
          "url": "https://attack.mitre.org/techniques/T1573"
        }
      ],
      "mod_time": 1681144146129,
      "participants": [
        {
          "external": false,
          "id": 1285,
          "object_id": 4294967310,
          "object_type": "device",
          "role": "offender"
        }
      ],
      "properties": {
        "host": "zupertech.com"
      },
      "resolution": "action_taken",
      "risk_score": 60,
      "start_time": 1681140240000,
      "status": "closed",
      "ticket_id": "3390",
      "title": "HTTP Request to a Suspicious Host",
      "type": "ti_http_host",
      "update_time": 1681140270000
    }
  },
  "inputs": {
    "extrahop_detection_id": 4294967305
  },
  "metrics": {
    "execution_time_ms": 459,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:18:51",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

inputs.extrahop_detection_id = incident.properties.extrahop_detection_id

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_search_detections post processing script ##
# funct_extrahop_rx_get_detections
#  Globals
FN_NAME = "funct_extrahop_rx_get_detections"
PB_NAME = "Extrahop Reveal(x): Refresh Case"
results = playbook.functions.results.get_detections_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
DATA_TABLE = "extrahop_detections"

# Read CATEGORY_MAP and TYPE_MAP from playbook property.
CATEGORY_MAP = playbook.properties.category_map
TYPE_MAP = playbook.properties.type_map
LINKBACK_URL = "/extrahop/#/detections/detail/{}"

# Processing
def process_dets(det):
    detection_url = make_linkback_url(det.get("id", None))
    detection_url_html = u'<div><b><a target="blank" href="{0}">{1}</a></b></div>' \
        .format(detection_url, det.get("id", None))
    newrow = incident.addRow(DATA_TABLE)
    newrow.query_execution_date = QUERY_EXECUTION_DATE
    newrow.detection_url = detection_url_html
    newrow.appliance_id = det.get("appliance_id", None)
    newrow.assignee = det.get("assignee", None)
    newrow.categories = "{}".format(", ".join(CATEGORY_MAP[c] if CATEGORY_MAP.get(c) else c for c in det.get("categories", [])))
    newrow.det_description = det.get("description", None)
    newrow.det_id = det.get("id", None)
    newrow.is_user_created = str(det.get("is_user_created", None))
    newrow.end_time = det.get("end_time", None)
    newrow.mod_time = det.get("mod_time", None)
    newrow.update_time = det.get("update_time", None)
    newrow.start_time = det.get("start_time", None)
    newrow.status = det.get("status", None)
    newrow.title = det.get("title", None)
    detection_type = det.get("type", None)
    newrow.type = TYPE_MAP.get(detection_type) if detection_type and TYPE_MAP.get(detection_type) else detection_type
    newrow.risk_score = det.get("risk_score", None)
    newrow.resolution = det.get("resolution", None)
    #newrow.ticket_url =  '<div><b><a target="blank" href="{0}">{1}</a></div>'.format(det.get(f2, None), det.get(f2, None).split('/')[-1])
    newrow.ticket_id = det.get("ticket_id", None)
    newrow.properties = make_json_string(det.get("properties", {}))
    newrow.participants = make_list_string(det.get("participants", []))
    newrow.mitre_techniques = make_list_string(det.get("mitre_techniques", []))
    newrow.mitre_tactics = make_list_string(det.get("mitre_tactics", []))
 
    # Update the "UPDATEABLE_FIELDS" custom fields also
    incident.properties.extrahop_assignee = det.get("assignee", None)
    incident.properties.extrahop_risk_score = det.get("risk_score", None)
    incident.properties.extrahop_mod_time = det.get("mod_time", None)
    incident.properties.extrahop_end_time = det.get("end_time", None)  
    incident.properties.extrahop_status = det.get("status", None)
    
    # Add participant artifacts
    add_properties_artifacts(det.get("properties", {}))

    # Add participant artifacts
    add_participants_artifacts(det.get("det_id", None), det.get("participants", []))

def make_json_string(detection_json):
    """_summary_

    Args:
        det (json object): ExtraHop detection object 

    Returns:
        str : properties json object converted to a formatted string
    """
    tbl = ''
    for i, j in detection_json.items():
        if i == "suspicious_ipaddr":
            det_type = "Suspicious IP Addresses"
            value = j["value"]
            tbl = '{0}<div><b>{1}:'.format(tbl, det_type)
            tbl = '{0}:<div><b>{1}'.format(tbl, ", ".join("{}".format(i) for i in value))
        else:
            tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, i, j)
        
    return tbl

def make_list_string(detection_list):
    """_summary_

    Args:
        det (json object): ExtraHop detection object 

    Returns:
        str : properties json object converted to a formatted string

"""

    tbl = u''
    for i in detection_list:
        for k, v in i.items():
            if k == "legacy_ids":
                tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, k, ','.join(v))
            elif k == "url":
                tbl = '{0}<div><b>{1}:<a target="blank" href="{2}">{3}</a></div>' \
                                .format(tbl, k, v, i["id"])
            else:
                tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, k, v)
        tbl += u"<br>"

    return tbl

def make_linkback_url(det_id):
    """Create a url to link back to the detection.

    Args:
        det_id (str/int): id representing the detection.

    Returns:
        str: completed url for linkback
    """
    return incident.properties.extrahop_console_url + LINKBACK_URL.format(det_id)

def addArtifact(artifact_type, artifact_value, description):
    """Add new artifacts to the incident.

    :param artifact_type: The type of the artifact.
    :param artifact_value: - The value of the artifact.
    :param description: - the description of the artifact.
    """
    incident.addArtifact(artifact_type, artifact_value, description)

def add_properties_artifacts(properties):
    """Add IP Address artifacts of the detections properties.

    Args:
        properties (_type_): properties of the detections (json object)
    """
    for i, j in properties.items():
        if i == "suspicious_ipaddr":
            artifact_type = "IP Address"
            artifact_type = "Suspicious IP Addresses"
            value = j["value"]
            for ip in value:
                addArtifact(artifact_type, ip, "Suspicious IP address found by ExtraHop.")

def add_participants_artifacts(det_id, participants):
    """ Add artifacts of the participants 

    Args:
        participants (_type_): List of json objects 
    """
    for p in participants:
        if p.get("object_type") == "ipaddr":
            artifact_type = "IP Address"
            addArtifact(artifact_type, p.get("object_value"),
                        "Participant IP address in ExtraHop detection '{0}', role: '{1}'."
                         .format(det_id, p.get("role")))
        if p.get("hostname"):
            artifact_type = "DNS Name"
            addArtifact(artifact_type, p["hostname"],
                        "Participant DNS name in ExtraHop detection '{0}', role: '{1}'."
                        .format(det_id, p.get("role")))

# Processing
def main():
    detection_id = INPUTS.get("extrahop_detection_id")
    note_text = u''
    if CONTENT:
        det = CONTENT.get("result", {})
        note_text = u"ExtraHop Reveal(x): Playbook <b>{0}</b>: A Detection was successfully returned for " \
                    u"detection ID <b>{1}</b> for SOAR function <b>{2}</b> with parameters <b>{3}</b>." \
                    .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        if det:
            process_dets(det)
            note_text += u"<br>The data table <b>{0}</b> has been updated".format("Extrahop Detections")
    else:
        note_text += u"ExtraHop Reveal(x): Playbook<b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     u"to get detections for detection ID <b>{1}</b> for SOAR function <b>{2}</b> ." \
                     u" with parameters <b>{3}</b>." \
            .format(PB_NAME, detection_id, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))
main()


Function - Extrahop Reveal(x) get devices

Get devices information from Extrahop Reveal(x). Optional parameters device_id, active_from, active_util, limit and offset.

screenshot: fn-extrahop-revealx-get-devices

The function provides the following functionality.

  • Retrieves information for devices in the ExtraHop environment.

An example playbook that uses this SOAR function is Extrahop Reveal(x): Search Devices (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table ExtraHop Devices is updated.

The playbook is initiated by the manual incident menu item ExtraHop Reveal(x): Search Devices (PB).

screenshot: fn-extrahop-revealx-get-devices-action

screenshot: fn-extrahop-revealx-search-devices-action_2

The following screenshots show an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-get-devices-datatable

screenshot: fn-extrahop-revealx-get-devices-datatable_2

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-get-devices-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_active_from

number

No

-

(Optional) The beginning timestamp for the request. Return only devices active after this time. Time is expressed in milliseconds since the epoch. 0 indicates the time of the request.

extrahop_active_until

number

No

-

(Optional) The ending timestamp for the request. Return only devices active before this time.

extrahop_device_id

number

No

-

Extrahop device ID

extrahop_limit

number

No

-

(Optional) Limit the number of devices returned to the specified maximum number.

extrahop_offset

number

No

-

(Optional) Skip the specified number of devices. This parameter is often combined with the limit parameter to paginate result sets.

extrahop_search_type

text

No

-

Indicates the field to search.

extrahop_value

text

No

-

Indicates the vakue to search for.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e2c7dd42fa50000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139880000,
        "discovery_id": "0e2c7dd42fa50000",
        "display_name": "oasis.i.rx.tours",
        "dns_name": "oasis.i.rx.tours",
        "extrahop_id": "0e2c7dd42fa50000",
        "id": 4294967315,
        "ipaddr4": "10.1.88.218",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:2C:7D:D4:2F:A5",
        "mod_time": 1681149516194,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "db_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e627f3316130000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139700000,
        "discovery_id": "0e627f3316130000",
        "display_name": "db1.i.rx.tours",
        "dns_name": "db1.i.rx.tours",
        "extrahop_id": "0e627f3316130000",
        "id": 4294967316,
        "ipaddr4": "10.1.1.7",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:62:7F:33:16:13",
        "mod_time": 1681149635562,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "db_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "custom",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": "aws.ec2.imds",
        "custom_type": "",
        "default_name": "Custom ~aws.ec2.imds---",
        "description": null,
        "device_class": "custom",
        "dhcp_name": "",
        "discover_time": 1681139670000,
        "discovery_id": "~aws.ec2.imds---",
        "display_name": "aws.ec2.imds",
        "dns_name": "",
        "extrahop_id": "~aws.ec2.imds---",
        "id": 4294967308,
        "ipaddr4": null,
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": null,
        "mod_time": 1681139913474,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "custom",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "custom",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": "aws.vpc.dns",
        "custom_type": "",
        "default_name": "Custom ~aws.vpc.dns----",
        "description": null,
        "device_class": "custom",
        "dhcp_name": "",
        "discover_time": 1681139670000,
        "discovery_id": "~aws.vpc.dns----",
        "display_name": "aws.vpc.dns",
        "dns_name": "",
        "extrahop_id": "~aws.vpc.dns----",
        "id": 4294967298,
        "ipaddr4": null,
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": null,
        "mod_time": 1681139763633,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "custom",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "custom",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": "aws.vpc.ntp",
        "custom_type": "",
        "default_name": "Custom ~aws.vpc.ntp----",
        "description": null,
        "device_class": "custom",
        "dhcp_name": "",
        "discover_time": 1681139640000,
        "discovery_id": "~aws.vpc.ntp----",
        "display_name": "aws.vpc.ntp",
        "dns_name": "",
        "extrahop_id": "~aws.vpc.ntp----",
        "id": 4294967312,
        "ipaddr4": null,
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": null,
        "mod_time": 1681139913487,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "custom",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "gateway",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0eb9806c43070000",
        "description": null,
        "device_class": "gateway",
        "dhcp_name": "",
        "discover_time": 1681139640000,
        "discovery_id": "0eb9806c43070000",
        "display_name": "Device 0eb9806c43070000",
        "dns_name": "",
        "extrahop_id": "0eb9806c43070000",
        "id": 4294967297,
        "ipaddr4": null,
        "ipaddr6": "fe80::cb9:80ff:fe6c:4307",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:B9:80:6C:43:07",
        "mod_time": 1681149396781,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "gateway",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "gateway",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e915f41761b0000",
        "description": null,
        "device_class": "gateway",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e915f41761b0000",
        "display_name": "Device 0e915f41761b0000",
        "dns_name": "",
        "extrahop_id": "0e915f41761b0000",
        "id": 4294967314,
        "ipaddr4": "10.1.0.1",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:91:5F:41:76:1B",
        "mod_time": 1681148735347,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "gateway",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "domain_controller",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e9ded7f42090000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e9ded7f42090000",
        "display_name": "dc1.i.rx.tours",
        "dns_name": "dc1.i.rx.tours",
        "extrahop_id": "0e9ded7f42090000",
        "id": 4294967313,
        "ipaddr4": null,
        "ipaddr6": "2600:1f10:44c7:3300:383d:6cd4:d4d5:3019",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:9D:ED:7F:42:09",
        "mod_time": 1681149485578,
        "model": null,
        "model_override": null,
        "netbios_name": "DC1",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "domain_controller",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "http_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0eda16c895d50000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0eda16c895d50000",
        "display_name": "web1.i.rx.tours",
        "dns_name": "web1.i.rx.tours",
        "extrahop_id": "0eda16c895d50000",
        "id": 4294967311,
        "ipaddr4": "10.1.1.64",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:DA:16:C8:95:D5",
        "mod_time": 1681149485572,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "http_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "pc",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e3da802a0b30000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "pc3",
        "discover_time": 1681139610000,
        "discovery_id": "0e3da802a0b30000",
        "display_name": "pc3",
        "dns_name": "pc3.i.rx.tours",
        "extrahop_id": "0e3da802a0b30000",
        "id": 4294967310,
        "ipaddr4": "10.1.0.161",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:3D:A8:02:A0:B3",
        "mod_time": 1681149427474,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "pc",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "pc",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e6f5c9ccbcb0000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "pc2",
        "discover_time": 1681139610000,
        "discovery_id": "0e6f5c9ccbcb0000",
        "display_name": "pc2",
        "dns_name": "pc2.i.rx.tours",
        "extrahop_id": "0e6f5c9ccbcb0000",
        "id": 4294967309,
        "ipaddr4": "10.1.0.189",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:6F:5C:9C:CB:CB",
        "mod_time": 1681149427468,
        "model": null,
        "model_override": null,
        "netbios_name": "PC2",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "pc",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e9d01dde7450000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e9d01dde7450000",
        "display_name": "ssh1.i.rx.tours",
        "dns_name": "ssh1.i.rx.tours",
        "extrahop_id": "0e9d01dde7450000",
        "id": 4294967307,
        "ipaddr4": "10.1.100.187",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:9D:01:DD:E7:45",
        "mod_time": 1681149396796,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e299a804a4d0000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e299a804a4d0000",
        "display_name": "ftp1.i.rx.tours",
        "dns_name": "ftp1.i.rx.tours",
        "extrahop_id": "0e299a804a4d0000",
        "id": 4294967306,
        "ipaddr4": "10.1.100.57",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:29:9A:80:4A:4D",
        "mod_time": 1681149396791,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0ecacf92cfcf0000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "ip-10-1-100-212",
        "discover_time": 1681139610000,
        "discovery_id": "0ecacf92cfcf0000",
        "display_name": "ip-10-1-100-212",
        "dns_name": "vpn.i.rx.tours",
        "extrahop_id": "0ecacf92cfcf0000",
        "id": 4294967305,
        "ipaddr4": "10.1.100.212",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:CA:CF:92:CF:CF",
        "mod_time": 1681149366180,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "gateway",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0ea63eed67fd0000",
        "description": null,
        "device_class": "gateway",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0ea63eed67fd0000",
        "display_name": "Device 0ea63eed67fd0000",
        "dns_name": "",
        "extrahop_id": "0ea63eed67fd0000",
        "id": 4294967304,
        "ipaddr4": "10.1.100.1",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:A6:3E:ED:67:FD",
        "mod_time": 1681149366175,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "gateway",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "http_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e8d65dcbfe70000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "ip-10-1-100-35",
        "discover_time": 1681139610000,
        "discovery_id": "0e8d65dcbfe70000",
        "display_name": "ip-10-1-100-35",
        "dns_name": "echo1.i.rx.tours",
        "extrahop_id": "0e8d65dcbfe70000",
        "id": 4294967303,
        "ipaddr4": "10.1.100.35",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:8D:65:DC:BF:E7",
        "mod_time": 1681149335495,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "http_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "gateway",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0ec8fcdae52b0000",
        "description": null,
        "device_class": "gateway",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0ec8fcdae52b0000",
        "display_name": "Device 0ec8fcdae52b0000",
        "dns_name": "",
        "extrahop_id": "0ec8fcdae52b0000",
        "id": 4294967302,
        "ipaddr4": null,
        "ipaddr6": "fe80::cc8:fcff:feda:e52b",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:C8:FC:DA:E5:2B",
        "mod_time": 1681139793788,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "gateway",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "http_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e2d40a873950000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e2d40a873950000",
        "display_name": "web3.i.rx.tours",
        "dns_name": "web3.i.rx.tours",
        "extrahop_id": "0e2d40a873950000",
        "id": 4294967301,
        "ipaddr4": null,
        "ipaddr6": "2600:1f10:44c7:3300:f8b2:7031:96bb:ee9f",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:2D:40:A8:73:95",
        "mod_time": 1681149635567,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "http_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "pc",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e5c9467324b0000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "pc1",
        "discover_time": 1681139610000,
        "discovery_id": "0e5c9467324b0000",
        "display_name": "pc1",
        "dns_name": "pc1.i.rx.tours",
        "extrahop_id": "0e5c9467324b0000",
        "id": 4294967300,
        "ipaddr4": "10.1.0.6",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:5C:94:67:32:4B",
        "mod_time": 1681149635572,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "pc",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "http_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e7ff45eb0ed0000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e7ff45eb0ed0000",
        "display_name": "web2.i.rx.tours",
        "dns_name": "web2.i.rx.tours",
        "extrahop_id": "0e7ff45eb0ed0000",
        "id": 4294967299,
        "ipaddr4": "10.1.1.94",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:7F:F4:5E:B0:ED",
        "mod_time": 1681149635557,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "http_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e3332e223c10000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681139610000,
        "discovery_id": "0e3332e223c10000",
        "display_name": "jump.i.rx.tours",
        "dns_name": "jump.i.rx.tours",
        "extrahop_id": "0e3332e223c10000",
        "id": 4294967296,
        "ipaddr4": null,
        "ipaddr6": "2600:1f10:44c7:3304:2e55:c0b1:7f5f:4a5",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:33:32:E2:23:C1",
        "mod_time": 1681149577486,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      }
    ]
  },
  "inputs": {},
  "metrics": {
    "execution_time_ms": 555,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:00:55",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

search_filters =  [ 
    "extrahop_device_field",
    "extrahop_device_operand",
    "extrahop_device_operator"
]
for p in search_filters:
    if hasattr(playbook.inputs, p) and playbook.inputs.get(p):
        raise ValueError("A search filter and Device ID are not allowed at the same time.")
        
if playbook.inputs.extrahop_device_id:
    inputs.extrahop_device_id = playbook.inputs.extrahop_device_id
    
if playbook.inputs.extrahop_active_from:
    inputs.extrahop_active_from = playbook.inputs.extrahop_active_from
if playbook.inputs.extrahop_active_until:
    inputs.extrahop_active_until = playbook.inputs.extrahop_active_until
if playbook.inputs.extrahop_limit:
    inputs.extrahop_limit = playbook.inputs.extrahop_limit
if playbook.inputs.extrahop_offset:
    inputs.extrahop_offset = playbook.inputs.extrahop_offset

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_get_devices post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_get_devices"
PB_NAME = "Extrahop Reveal(x): Refresh Case"
results = playbook.functions.results.get_devices_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
# Display subset of fields
DATA_TABLE = "extrahop_devices"
DATA_TBL_FIELDS = ["display_name", "devs_description", "default_name", "dns_name", "ipaddr4", "ipaddr6", "macaddr",
                   "role", "vendor", "devs_id", "extrahop_id", "activity", "mod_time", "user_mod_time", "discover_time", 
                   "last_seen_time"]
LINKBACK_URL = "/extrahop/#/metrics/devices/{}.{}"


def make_linkback_url(dev_id):
    """Create a url to link back to the endpoint alert, case, etc.

    Args:
        dev_id (str/int): id representing the device etc.

    Returns:
        str: completed url for linkback
    """
    return incident.properties.extrahop_console_url + LINKBACK_URL.format(incident.properties.extrahop_site_uuid, dev_id)

def process_devs(dev):
    # Process a device result.
    newrow = incident.addRow(DATA_TABLE)
    newrow.query_execution_date = QUERY_EXECUTION_DATE
    newrow.display_name = dev.get("display_name", None)
    newrow.devs_description = dev.get("description", None)
    newrow.default_name = dev.get("default_name", None)
    newrow.dns_name = dev.get("dns_name", None)
    newrow.ipaddr4 = dev.get("ipaddr4", None)
    newrow.ipaddr6 = dev.get("ipaddr6", None)
    newrow.macaddr  = dev.get("macaddr", None)
    newrow.role = dev.get("role", None)
    newrow.vendor = dev.get("vendor", None)
    newrow.devs_id = dev.get("id", None)
    newrow.extrahop_id = dev.get("extrahop_id", None)
    newrow.activity = dev.get("activity", None)
    newrow.on_watchlist = str(dev.get("on_watchlist", None))
    newrow.mod_time = dev.get("mod_time", None)
    newrow.user_mod_time = dev.get("user_mod_time", None)              
    newrow.discover_time = dev.get("discover_time", None)
    newrow.last_seen_time = dev.get("last_seen_time", None)
    device_url = make_linkback_url(dev["extrahop_id"])
    device_url_html = u'<div><b><a target="blank" href="{1}">{2}</a></b></div>' \
        .format("url", device_url, dev["extrahop_id"])
    newrow.device_url = device_url_html

def get_dev_ids():
    # Get participant dev ids    
    dev_ids = []
    get_devices_content = playbook.functions.results.get_detections_results.content
    devs = get_devices_content.get("result", {})
    participants = devs.get("participants", {})
    for p in participants:
        if p.get("object_type", None) == "device":
            dev_ids.append(p.get("object_id", None))
    return dev_ids


# Processing
participant_dev_ids = get_dev_ids()
note_text = ''
if CONTENT:
    devs = [d for d in CONTENT.get("result") if d.get("id", None) in participant_dev_ids]
    note_text = "ExtraHop Integration: Playbook <b>{0}</b>: There were <b>{1}</b> Devices returned for SOAR " \
                    "function <b>{2}</b> with parameters <b>{3}</b>.".format(PB_NAME, len(devs), FN_NAME, ", ".join(
            "{}:{}".format(k, v) for k, v in INPUTS.items()))
    if devs:
        if isinstance(devs, list):
            for dev in devs:
                process_devs(dev)
        else:
            process_devs(devs)
        note_text += "<br>The data table <b>{0}</b> has been updated".format(DATA_TABLE)

else:
    note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to get devices for SOAR function <b>{1}</b> with parameters <b>{2}</b>." \
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

incident.addNote(helper.createRichText(note_text))

#Unset the Detection update notification. 
incident.properties.extrahop_update_notification = None


Function - Extrahop Reveal(x) get tags

Get tags information from Extrahop Reveal(x). Optional parameter tag_id.

screenshot: fn-extrahop-revealx-get-tags

The function provides the following functionality.

  • Retrieves a list of tags discovered in the ExtraHop environment.

An example playbook that uses this SOAR function is ExtraHop Reveal(x): Get Tags (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table Extrahop Tags is updated.

The playbook is initiated by the manual incident menu item ExtraHop Reveal(x): Get Tags (PB).

screenshot: fn-extrahop-revealx-get-tags-action

The following screenshot shows an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-get-tags-datatable

The following screenshot shows an example of a note added to a SOAR case:

screenshot: fn-extrahop-revealx-get-tags-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_tag_id

number

No

-

The unique identifier for the tag.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "id": 21,
        "mod_time": 1681148615537,
        "name": "SOAR-Testing-tag"
      }
    ]
  },
  "inputs": {},
  "metrics": {
    "execution_time_ms": 628,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:21:21",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

if playbook.inputs.extrahop_tag_name is None:
    raise ValueError("The tag name is not set")

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_get_tags post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_get_tags"
PB_NAME = "Extrahop Reveal(x): Assign Tag"
results = playbook.functions.results.get_tags_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    tag_name = playbook.inputs.extrahop_tag_name
    tag_id = None
    
    if CONTENT:
        tags = CONTENT.get("result", {})
        for tag in tags:
            if tag_name == tag["name"]:
                tag_id = tag["id"]
                playbook.addProperty("tag_exists", {})
                break
        if not tag_id:
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Tag <b>'{1}'</b> not returned for SOAR function <b>{2}</b> "\
                        "with parameters:<br><b>{3}</b>."\
                    .format(PB_NAME, tag_name, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    else:
        note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to get tags for SOAR function <b>{1}</b> with parameters:<br><b>{2}</b>."\
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    if note_text:
        incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) get watchlist

Retrieve all devices that are in the watchlist from Extrahop Reveal(x).

screenshot: fn-extrahop-revealx-get-watchlist

The function provides the following functionality.

  • Retrieves a list of devices on the watchlist in the ExtraHop environment.

An example playbook that uses this SOAR function is ExtraHop Reveal(x): Get Watchlist (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table Extrahop Watchlist is updated.

The playbook is initiated by the manual incident menu item ExtraHop Reveal(x): Get Watchlist (PB).

screenshot: fn-extrahop-revealx-get-watchlist-action

The following screenshot shows an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-get-watchlist-datatable

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-get-watchlist-note

Inputs:

Name

Type

Required

Example

Tooltip

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "custom",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": "aws.vpc.ntp",
        "custom_type": "",
        "default_name": "Custom ~aws.vpc.ntp----",
        "description": null,
        "device_class": "custom",
        "dhcp_name": "",
        "discover_time": 1681158480000,
        "discovery_id": "~aws.vpc.ntp----",
        "display_name": "aws.vpc.ntp",
        "dns_name": "",
        "extrahop_id": "~aws.vpc.ntp----",
        "id": 4294967313,
        "ipaddr4": null,
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": null,
        "mod_time": 1681647107939,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "custom",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "db_server",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e627f3316130000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681158510000,
        "discovery_id": "0e627f3316130000",
        "display_name": "db1.i.rx.tours",
        "dns_name": "db1.i.rx.tours",
        "extrahop_id": "0e627f3316130000",
        "id": 4294967298,
        "ipaddr4": "10.1.1.7",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:62:7F:33:16:13",
        "mod_time": 1681752256777,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "db_server",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "pc",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e3da802a0b30000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "pc3",
        "discover_time": 1681158480000,
        "discovery_id": "0e3da802a0b30000",
        "display_name": "pc3",
        "dns_name": "pc3.i.rx.tours",
        "extrahop_id": "0e3da802a0b30000",
        "id": 4294967311,
        "ipaddr4": "10.1.0.161",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:3D:A8:02:A0:B3",
        "mod_time": 1681752406778,
        "model": null,
        "model_override": null,
        "netbios_name": "PC3",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "pc",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e2c7dd42fa50000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681158720000,
        "discovery_id": "0e2c7dd42fa50000",
        "display_name": "oasis.i.rx.tours",
        "dns_name": "oasis.i.rx.tours",
        "extrahop_id": "0e2c7dd42fa50000",
        "id": 4294967316,
        "ipaddr4": null,
        "ipaddr6": "2600:1f10:44c7:3304:1bb4:204b:45f3:30a0",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:2C:7D:D4:2F:A5",
        "mod_time": 1681752437427,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "other",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e3332e223c10000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "",
        "discover_time": 1681158450000,
        "discovery_id": "0e3332e223c10000",
        "display_name": "jump.i.rx.tours",
        "dns_name": "jump.i.rx.tours",
        "extrahop_id": "0e3332e223c10000",
        "id": 4294967296,
        "ipaddr4": null,
        "ipaddr6": "fe80::c33:32ff:fee2:23c1",
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:33:32:E2:23:C1",
        "mod_time": 1681752198592,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "other",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      },
      {
        "analysis": "advanced",
        "analysis_level": 2,
        "auto_role": "gateway",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e915f41761b0000",
        "description": null,
        "device_class": "gateway",
        "dhcp_name": "",
        "discover_time": 1681158480000,
        "discovery_id": "0e915f41761b0000",
        "display_name": "Device 0e915f41761b0000",
        "dns_name": "",
        "extrahop_id": "0e915f41761b0000",
        "id": 4294967315,
        "ipaddr4": "10.1.0.1",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:91:5F:41:76:1B",
        "mod_time": 1681716728051,
        "model": null,
        "model_override": null,
        "netbios_name": "",
        "node_id": 1,
        "on_watchlist": true,
        "parent_id": null,
        "role": "gateway",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      }
    ]
  },
  "inputs": {},
  "metrics": {
    "execution_time_ms": 688,
    "host": "laptop.local",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-17 13:27:24",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

None

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_get_watchlist post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_get_watchlist"
PB_NAME = "Extrahop Reveal(x): Get Watchlist"
results = playbook.functions.results.get_watchlist_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
# Display subset of fields
DATA_TABLE = "extrahop_watchlist"
DATA_TBL_FIELDS = ["display_name", "ipaddr4", "ipaddr6", "macaddr", "extrahop_id"]

# Processing
def main():
    note_text = ''
    if CONTENT:
        devs = CONTENT.get("result", [])
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: There were <b>{1}</b> devices returned in the Watchlist" \
                    " for SOAR function <b>{2}</b> with parameters <b>{3}</b>.".format(PB_NAME, len(devs), FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        if devs:
            for dev in devs:
                newrow = incident.addRow("extrahop_watchlist")
                newrow.query_execution_date = QUERY_EXECUTION_DATE
                for f1 in DATA_TBL_FIELDS:
                  f2 = f1
                  if dev[f1] is None:
                      newrow[f1] = dev[f2]
                  if isinstance(dev[f1], list):
                      newrow[f1] = "{}".format(", ".join(dev[f2]))
                  elif isinstance(dev[f1], bool):
                      newrow[f1] = str(dev[f2])
                  else:
                      newrow[f1] = "{}".format(dev[f2])
            note_text += "<br>The data table <b>{0}</b> has been updated".format("Extrahop Detections")

    else:
        note_text += "ExtraHop Reveal(x): Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to get the watchlist for SOAR function <b>{1}</b> with parameters <b>{2}</b>." \
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) search detections

Search for detections information from Extrahop Reveal(x). Optional parameters search_filter, active_from, active_util, limit, offset, update_time and sort.

screenshot: fn-extrahop-revealx-search-detections

The function provides the following functionality.

  • Retrieves a list of detections in the ExtraHop environment based on the provided parameters.

  • A filter in JSON is used to target the information retrieved.

An example playbook that uses this SOAR function is ExtraHop Reveal(x): Search Detections (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table Extrahop Detections is updated.

The playbook is initiated by the manual incident menu item ExtraHop Reveal(x): Search Detections (PB).

The following screenshot shows an example of the action inputs for the playbook:

screenshot: fn-extrahop-revealx-search-detections-action

screenshot: fn-extrahop-revealx-search-detections-action_2

The following screenshot shows an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-search-detections-datatable screenshot: fn-extrahop-revealx-search-detections-datatable_2 screenshot: fn-extrahop-revealx-search-detections-datatable_3

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-search-detections-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_active_from

number

No

-

(Optional) The beginning timestamp for the request. Return only devices active after this time. Time is expressed in milliseconds since the epoch. 0 indicates the time of the request.

extrahop_active_until

number

No

-

(Optional) The ending timestamp for the request. Return only devices active before this time.

extrahop_limit

number

No

-

(Optional) Limit the number of devices returned to the specified maximum number.

extrahop_mod_time

number

No

-

(Optional) Return detections that were updated on or after the specified date, expressed in milliseconds since the epoch.

extrahop_offset

number

No

-

(Optional) Skip the specified number of devices. This parameter is often combined with the limit parameter to paginate result sets.

extrahop_search_filter

text

No

-

The filter criteria for Extrahop search results.

extrahop_sort

text

No

-

Sorts returned detections by the specified fields. By default, detections are sorted by most recent update time and then ID in ascending order.

extrahop_update_time

number

No

-

(Optional) Return detections that were updated on or after the specified date, expressed in milliseconds since the epoch.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "appliance_id": 1,
        "assignee": null,
        "categories": [
          "sec",
          "sec.hardening"
        ],
        "description": "[pc2](#/metrics/devices/44522fe6bb834d83a3b0a142b7da750a.0e6f5c9ccbcb0000/overview?from=1681160178\u0026interval_type=DT\u0026until=1681749330) established a Server Message Block (SMB) connection with the SMBv1 dialect. This deprecated dialect of the SMB/CIFS protocol is known to be vulnerable to attacks.",
        "id": 4294967308,
        "is_user_created": false,
        "mitre_tactics": [],
        "mitre_techniques": [],
        "mod_time": 1681749167977,
        "participants": [
          {
            "external": false,
            "hostname": "pc2.i.rx.tours",
            "id": 1336,
            "object_id": 4294967310,
            "object_type": "device",
            "object_value": "10.1.0.189",
            "role": "offender"
          }
        ],
        "properties": {},
        "resolution": null,
        "risk_score": 30,
        "start_time": 1681160178555,
        "status": "in_progress",
        "ticket_id": "2118",
        "title": "SMBv1 Connection",
        "type": "smbv1_connection_individual",
        "update_time": 1681749150000
      }
    ]
  },
  "inputs": {
    "extrahop_search_filter": "{\"filter\": {\"status\": [\"in_progress\"]}}"
  },
  "metrics": {
    "execution_time_ms": 907,
    "host": "laptop.local",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-17 12:37:03",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

##  ExtraHop - wf_extrahop_rx_search_detections pre processing script ##
# Read CATEGORY_MAP and TYPE_MAP from workflow propertyself. 
# Reverse the dict keys and values
CATEGORY_MAP = {v: k for k, v in playbook.properties.category_map.items()}
TYPE_MAP = {v: k for k, v in playbook.properties.type_map.items()}
DOT_PARAMS = [
    "me",
    "none"
]


def get_prop(prop, type=None):
    if prop:
        if isinstance(prop, int):
            return prop
        elif isinstance(prop, list):
            return ['{}'.format('.' + i if i in DOT_PARAMS else i) for i in prop]
        else:
            result = '{}'.format('.' + prop if prop in DOT_PARAMS else prop)
        if type == "list":
            return [result]

        return result

    else:
        return None


filter = {}
search_filter = {}
category = None
detection_types = None
if playbook.inputs.extrahop_detection_category:
    category = CATEGORY_MAP[playbook.inputs.extrahop_detection_category]
if hasattr(playbook.inputs, "extrahop_detection_types"):
    detection_types = [TYPE_MAP[d] for d in playbook.inputs.extrahop_detection_types]

filter_props = {
    "risk_score_min": get_prop(playbook.inputs.extrahop_detection_risk_score_min),
    "types": get_prop(detection_types),
    "category": get_prop(category),
    "assignee": get_prop(playbook.inputs.extrahop_detection_assignee, "list"),
    "ticket_id": get_prop(playbook.inputs.extrahop_detection_ticket_id, "list"),
    "status": get_prop(playbook.inputs.get("extrahop_detection_status") if hasattr(playbook.inputs, "extrahop_detection_status") else None),
    "resolution": get_prop(playbook.inputs.get("extrahop_detection_resolution") if hasattr(playbook.inputs, "extrahop_detection_resolution") else None)
}

filter = {k: v for k, v in filter_props.items() if v}

if filter:
    if playbook.properties.extrahop_detection_id:
        raise ValueError("The search filter and Detection ID are not allowed at the same time.")

    search_filter = {
        "filter": filter
    }
    inputs.extrahop_search_filter = str(search_filter).replace("'", '"')

if playbook.inputs.extrahop_active_from:
    inputs.extrahop_active_from = playbook.inputs.extrahop_active_from
if playbook.inputs.extrahop_active_until:
    inputs.extrahop_active_until = playbook.inputs.extrahop_active_until
if playbook.inputs.extrahop_limit:
    inputs.extrahop_limit = playbook.inputs.extrahop_limit
if playbook.inputs.extrahop_offset:
    inputs.extrahop_offset = playbook.inputs.extrahop_offset
if playbook.inputs.extrahop_update_time:
    inputs.extrahop_update_time = playbook.inputs.extrahop_update_time
if playbook.inputs.extrahop_mod_time:
    inputs.extrahop_mod_time = playbook.inputs.extrahop_mod_time

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_search_detections post processing script ##
import datetime
#  Globals
FN_NAME = "funct_extrahop_rx_search_detections"
PB_NAME = "Extrahop Revealx search detections"
results = playbook.functions.results.search_detections_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
DATA_TABLE = "extrahop_detections"

# Read CATEGORY_MAP and TYPE_MAP from workflow property.
CATEGORY_MAP = playbook.properties.category_map
TYPE_MAP = playbook.properties.type_map

LINKBACK_URL = "/extrahop/#/detections/detail/{}"

# Processing
def process_dets(det):
    detection_url = make_linkback_url(det["id"])
    detection_url_html = u'<div><b><a target="blank" href="{0}">{1}</a></b></div>' \
        .format(detection_url, det.get("id", None))
    newrow = incident.addRow(DATA_TABLE)
    newrow.query_execution_date = QUERY_EXECUTION_DATE
    newrow.detection_url = detection_url_html
    newrow.appliance_id = det.get("appliance_id", None)
    newrow.assignee = det.get("assignee", None)
    newrow.categories = "{}".format(", ".join(CATEGORY_MAP[c] if CATEGORY_MAP.get(c) else c for c in det.get("categories", [])))
    newrow.det_description = det.get("description", None)
    newrow.det_id = det.get("id", None)
    newrow.is_user_created = str(det.get("is_user_created", None))
    newrow.end_time = det.get("end_time", None)
    newrow.mod_time = det.get("mod_time", None)
    newrow.update_time = det.get("update_time", None)
    newrow.start_time = det.get("start_time", None)
    newrow.status = det.get("status", None)
    newrow.title = det.get("title", None)
    detection_type = det.get("type", None)
    newrow.type = TYPE_MAP.get(detection_type) if detection_type and TYPE_MAP.get(detection_type) else detection_type
    newrow.risk_score = det.get("risk_score", None)
    newrow.resolution = det.get("resolution", None)
    #newrow.ticket_url =  '<div><b><a target="blank" href="{0}">{1}</a></div>'.format(det.get(f2, None), det.get(f2, None).split('/')[-1])
    newrow.ticket_id = det.get("ticket_id", None)
    newrow.properties = make_properties_string(det)
    newrow.participants = make_list_string(det.get("participants", []))
    newrow.mitre_tactics = make_list_string(det.get("mitre_tactics", []))
    newrow.mitre_techniques = make_list_string(det.get("mitre_techniques", []))

def make_properties_string(det):
    """_summary_

    Args:
        det (json object): ExtraHop detection object 

    Returns:
        str : properties json object converted to a formatted string
    """
    tbl = ''
    properties = det.get("properties", {})
    for i, j in properties.items():
        if i == "suspicious_ipaddr":
            det_type = "Suspicious IP Addresses"
            value = j["value"]
            tbl = '{0}<div><b>{1}:'.format(tbl, det_type)
            tbl = '{0}:<div><b>{1}'.format(tbl, ", ".join("{}".format(i) for i in value))
        else:
            tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, i, j)
        
    return tbl

def make_list_string(detection_list):
    """_summary_

    Args:
        det (json object): ExtraHop detection object 

    Returns:
        str : properties json object converted to a formatted string

"""

    tbl = u''
    for i in detection_list:
        for k, v in i.items():
            if k == "legacy_ids":
                tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, k, ','.join(v))
            elif k == "url":
                tbl = '{0}<div><b>{1}:<a target="blank" href="{2}">{3}</a></div>' \
                                .format(tbl, k, v, i["id"])
            else:
                tbl = '{0}<div><b>{1}:</b>{2}</div>'.format(tbl, k, v)
        tbl += u"<br>"

    return tbl

# Processing
def make_linkback_url(det_id):
    """Create a url to link back to the detection.

    Args:
        det_id (str/int): id representing the detection.

    Returns:
        str: completed url for linkback
    """
    return incident.properties.extrahop_console_url + LINKBACK_URL.format(det_id)

def format_input_params(input_params):
    input_params_formatted =''
    for k, v in input_params.items():
        if k == "extrahop_active_until" or k == "extrahop_active_from":
            v = datetime.datetime.fromtimestamp(v/1000).strftime('%Y-%m-%d %H:%M:%S')
        input_params_formatted += "{}: {}<br>".format(k, v)
    return input_params_formatted
    
# Processing
def main():
    note_text = ''
    input_params_formatted = format_input_params(INPUTS)
    if CONTENT:
        dets = CONTENT.get("result", {})
        note_text = "ExtraHop Reveal(x): Playbook <b>{0}</b>: There were <b>{1}</b> Detections returned for SOAR " \
                    "function <b>{2}</b> with parameters:<br><b>{3}</b>".format(PB_NAME, len(dets), FN_NAME, input_params_formatted)
        if dets:
            for det in dets:
                process_dets(det)
            note_text += "<br>The data table <b>{0}</b> has been updated".format("Extrahop Detections")

    else:
        note_text += "ExtraHop Reveal(x): Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to search detections for SOAR function <b>{1}</b> with parameters:<br><b>{2}</b>" \
                    .format(PB_NAME, FN_NAME, input_params_formatted)

    incident.addNote(helper.createRichText(note_text))
    
# Start execution
main()


Function - Extrahop Reveal(x) search devices

Search for devices information from Extrahop Reveal(x). Optional parameters search_filter, active_from, active_util, limit and offset.

screenshot: fn-extrahop-revealx-search-devices

The function provides the following functionality.

  • Retrieves a list of devices on the in the ExtraHop environment based on the parameters provided.

  • A filter in JSON is used to target the information retrieved.

An example playbook that uses this SOAR function is ExtraHop Reveal(x): Search Devices (PB).

  • A note is added to the SOAR incident with the status of the action.

  • The data table Extrahop Devices is updated.

The playbook is initiated by the manual incident menu item ExtraHop Reveal(x): Search Devices (PB).

The following screenshot shows an example of the action inputs for the playbook:

screenshot: fn-extrahop-revealx-search-devices-action

screenshot: fn-extrahop-revealx-search-devices-action_2

The following screenshot shows an example of the data table updated by the function:

screenshot: fn-extrahop-revealx-search-devices-datatable

screenshot: fn-extrahop-revealx-search-devices-datatable_2

The following screenshot shows an example of a note added to a SOAR incident:

screenshot: fn-extrahop-revealx-search-devices-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_active_from

number

No

-

(Optional) The beginning timestamp for the request. Return only devices active after this time. Time is expressed in milliseconds since the epoch. 0 indicates the time of the request.

extrahop_active_until

number

No

-

(Optional) The ending timestamp for the request. Return only devices active before this time.

extrahop_limit

number

No

-

(Optional) Limit the number of devices returned to the specified maximum number.

extrahop_offset

number

No

-

(Optional) Skip the specified number of devices. This parameter is often combined with the limit parameter to paginate result sets.

extrahop_search_filter

text

No

-

The filter criteria for Extrahop search results.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": [
      {
        "analysis": "advanced",
        "analysis_level": 1,
        "auto_role": "pc",
        "cdp_name": "",
        "cloud_account": null,
        "cloud_instance_description": null,
        "cloud_instance_id": null,
        "cloud_instance_name": null,
        "cloud_instance_type": null,
        "critical": false,
        "custom_criticality": null,
        "custom_make": null,
        "custom_model": null,
        "custom_name": null,
        "custom_type": "",
        "default_name": "Device 0e3da802a0b30000",
        "description": null,
        "device_class": "node",
        "dhcp_name": "pc3",
        "discover_time": 1681158480000,
        "discovery_id": "0e3da802a0b30000",
        "display_name": "pc3",
        "dns_name": "pc3.i.rx.tours",
        "extrahop_id": "0e3da802a0b30000",
        "id": 4294967311,
        "ipaddr4": "10.1.0.161",
        "ipaddr6": null,
        "is_l3": false,
        "last_seen_time": null,
        "macaddr": "0E:3D:A8:02:A0:B3",
        "mod_time": 1681751806994,
        "model": null,
        "model_override": null,
        "netbios_name": "PC3",
        "node_id": 1,
        "on_watchlist": false,
        "parent_id": null,
        "role": "pc",
        "subnet_id": null,
        "user_mod_time": 0,
        "vendor": null,
        "vlanid": 0,
        "vpc_id": null
      }
    ]
  },
  "inputs": {
    "extrahop_search_filter": "{\"filter\": {\"field\": \"ipaddr\", \"operand\": \"10.1.0.161\", \"operator\": \"=\"}}"
  },
  "metrics": {
    "execution_time_ms": 812,
    "host": "laptop.local",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-17 13:17:05",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

##  ExtraHop - pb_extrahop_rx_search_devices pre processing script ##

def get_prop(prop, type=None):
    if prop:
        return '{}'.format(prop)
    else:
        return None


def main():
    filter = {}

    search_filter = {}
    filter_props = {
        "field": get_prop(playbook.inputs.extrahop_device_field),
        "operand": get_prop(playbook.inputs.extrahop_device_operand),
        "operator": get_prop(playbook.inputs.extrahop_device_operator)
    }
    filter = {k: v for k, v in filter_props.items() if v}

    if filter and playbook.inputs.extrahop_device_id:
        raise ValueError("The device ID and search filter shouldn't be set at the same time.")

    if filter:
        missing_props = []
        for f in ["field", "operand", "operator"]:
            if not filter.get(f, None):
                missing_props.append(f)
        if missing_props:
            raise ValueError("The filter is missing properties: '{}'.".format(", ".join(missing_props)))

        search_filter = {
            "filter": filter
        }

    if playbook.inputs.extrahop_device_id:
        search_filter = {
            "filter": {
                "field": "discovery_id",
                "operator": "=",
                "operand": str(playbook.inputs.extrahop_device_id)
            }
        }
    if search_filter:
        inputs.extrahop_search_filter = str(search_filter).replace("'", '"')
    if playbook.inputs.extrahop_active_from:
        inputs.extrahop_active_from = playbook.inputs.extrahop_active_from
    if playbook.inputs.extrahop_active_until:
        inputs.extrahop_active_until = playbook.inputs.extrahop_active_until
    if playbook.inputs.extrahop_limit:
        inputs.extrahop_limit = playbook.inputs.extrahop_limit
    if playbook.inputs.extrahop_offset:
        inputs.extrahop_offset = playbook.inputs.extrahop_offset

    if inputs == {}:
      raise ValueError("At least one search criteria is required to search devices. inputs = {0}".format(inputs))

main()

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_search_devices post processing script ##
import datetime
#  Globals
FN_NAME = "funct_extrahop_rx_search_devices"
PB_NAME = "Extrahop Reveal(x): Search Devices"
results = playbook.functions.results.device_search_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})
QUERY_EXECUTION_DATE = results["metrics"]["timestamp"]
# Display subset of fields
DATA_TABLE = "extrahop_devices"
LINKBACK_URL = "/extrahop/#/metrics/devices/{}.{}"


# Processing
def make_linkback_url(dev_id):
    """Create a url to link back to the endpoint alert, case, etc.

    Args:
        dev_id (str/int): id representing the device etc.

    Returns:
        str: completed url for linkback
    """
    return incident.properties.extrahop_console_url + LINKBACK_URL.format(incident.properties.extrahop_site_uuid, dev_id)


def process_devs(dev):
    # Process a device result.
    newrow = incident.addRow(DATA_TABLE)
    newrow.query_execution_date = QUERY_EXECUTION_DATE
    newrow.display_name = dev.get("display_name", None)
    newrow.devs_description = dev.get("description", None)
    newrow.default_name = dev.get("default_name", None)
    newrow.dns_name = dev.get("dns_name", None)
    newrow.ipaddr4 = dev.get("ipaddr4", None)
    newrow.ipaddr6 = dev.get("ipaddr6", None)
    newrow.macaddr  = dev.get("macaddr", None)
    newrow.role = dev.get("role", None)
    newrow.vendor = dev.get("vendor", None)
    newrow.devs_id = dev.get("id", None)
    newrow.extrahop_id = dev.get("extrahop_id", None)
    newrow.activity = dev.get("activity", None)
    newrow.on_watchlist = str(dev.get("on_watchlist", None))
    newrow.mod_time = dev.get("mod_time", None)
    newrow.user_mod_time = dev.get("user_mod_time", None)              
    newrow.discover_time = dev.get("discover_time", None)
    newrow.last_seen_time = dev.get("last_seen_time", None)
    device_url = make_linkback_url(dev["extrahop_id"])
    device_url_html = u'<div><b><a target="blank" href="{1}">{2}</a></b></div>' \
        .format("url", device_url, dev["extrahop_id"])
    newrow.device_url = device_url_html

def format_input_params(input_params):
    input_params_formatted =''
    for k, v in input_params.items():
        if k == "extrahop_active_until" or k == "extrahop_active_from":
            v = datetime.datetime.fromtimestamp(v/1000).strftime('%Y-%m-%d %H:%M:%S')
        input_params_formatted += "{}: {}\n".format(k, v)
    return input_params_formatted
    
def main():
    note_text = ''
    input_params_formatted = format_input_params(INPUTS)
    if CONTENT:
        if CONTENT.get("error", None):
            note_text = "ExtraHop: Playbook <b>{0}</b>: Search devices failed with error <b>'{1}'</b> for " \
                        "SOAR function <b>{2}</b> with parameters:<br><b>{3}</b>".format(PB_NAME, CONTENT["error"], FN_NAME, input_params_formatted)
        else:
            devs = CONTENT.get("result", None)
            note_text = "ExtraHop: Playbook <b>{0}</b>: There were <b>{1}</b> Devices returned for SOAR " \
                        "function <b>{2}</b> with parameters:<br><b>{3}</b>".format(PB_NAME, len(devs), FN_NAME, input_params_formatted)
            if devs:
                for dev in devs:
                    process_devs(dev)
                note_text += "<br>The data table <b>{0}</b> has been updated".format(DATA_TABLE)
            else:
                note_text += "<br>The data table <b>{0}</b> has NOT been updated".format(DATA_TABLE)

    else:
        note_text += "ExtraHop: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to search devices for SOAR function <b>{1}</b> with parameters:<br><b>{2}</b>" \
            .format(PB_NAME, FN_NAME, input_params_formatted)

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) search packets

Search for and download packets stored on the ExtraHop Reveal(x) system. Supported output formats: pcap, keylog_txt, pcapng, zip, extract.

screenshot: fn-extrahop-revealx-search-packets

The function provides the following functionality.

  • Does a packet search and download from an ExtraHop environment. The packet data can be downloaded in pcap, zip and keylog_txt output format.

NOTE: Extra configuration is required to use the keylog_txt output. Session key download

An example playbook that uses this SOAR function is ExtraHop Reveal(x): Search Packets (PB).

  • A note is added to the SOAR incident with the status of the action.

  • An attachment in the select output format is added to the SOAR incident.

The playbook is initiated by the manual incident artifact menu item ExtraHop Reveal(x): Search Packets.

The following screenshot shows an example of the action inputs for the playbook:

screenshot: fn-extrahop-revealx-search-packets-action

screenshot: fn-extrahop-revealx-search-packets-action_2

The following screenshot shows an example of the attachments added by the function:

screenshot: fn-extrahop-revealx-search-packets-attachment

The following screenshot shows an example of notes added to a SOAR incident:

screenshot: fn-extrahop-revealx-search-packets-note

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_active_from

number

Yes

-

(Always) The beginning timestamp for the request. Return only devices active after this time. Time is expressed in milliseconds since the epoch. 0 indicates the time of the request.

extrahop_active_until

number

No

-

(Optional) The ending timestamp for the request. Return only devices active before this time.

extrahop_always_return_body

boolean

No

-

If True return an empty packet capture file and an HTTP status of 200.

extrahop_bpf

text

No

host 192.168.1.2  dst host 192.168.1.3

Filter packets with Berkeley Packet Filter syntax.

extrahop_ip1

text

No

-

Return packets sent to or received by the specified IP address.

extrahop_ip2

text

No

-

Return packets sent to or received by the specified IP address.

extrahop_limit_bytes

text

No

-

The maximum number of bytes to return.

extrahop_limit_search_duration

text

No

-

The maximum amount of time to run the packet search.

extrahop_output

text

No

-

The output format. Valid values pcap , keylog_txt and zip

extrahop_port1

text

No

-

Return packets sent from or received on the specified port.

extrahop_port2

text

No

-

Return packets sent from or received on the specified port.

extrahop_decrypt_files

boolean

No

-

Specifies whether to decrypt extracted files with stored secrets. This option is valid only if the output parameter is extract.

extrahop_include_secrets

boolean

No

-

Whether or not to include TLS secrets together with packet data in .pcapng files. Only valid if “output” is “pcapng”.

incident_id

number

Yes

-

-

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": {
      "attachment": "\u003cb\u003eextrahop 2023-03-31 21.00.00 to 2023-04-08 21.00.00 PDT_20230410140142.pcap\u003c/b\u003e"
    }
  },
  "inputs": {
    "extrahop_active_from": 1680321600000,
    "extrahop_active_until": 1681012800000,
    "extrahop_bpf": "host dc1.attack.local",
    "extrahop_decrypt_files": null,
    "extrahop_include_secrets": null,
    "extrahop_ip1": null,
    "extrahop_ip2": null,
    "extrahop_limit_bytes": null,
    "extrahop_limit_search_duration": null,
    "extrahop_output": "pcap",
    "extrahop_port1": null,
    "extrahop_port2": null,
    "incident_id": 3389
  },
  "metrics": {
    "execution_time_ms": 28890,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:01:44",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

inputs.incident_id = incident.id
if artifact.type == "IP Address":
    inputs.extrahop_bpf = "host {}".format(artifact.value)
elif artifact.type == "MAC Address":
    inputs.extrahop_bpf = "ether host {}".format(artifact.value)
inputs.extrahop_active_from = playbook.inputs.extrahop_active_from
inputs.extrahop_active_until = playbook.inputs.extrahop_active_until
inputs.extrahop_output = playbook.inputs.extrahop_output
inputs.extrahop_limit_search_duration = playbook.inputs.extrahop_limit_search_duration
inputs.extrahop_limit_bytes = playbook.inputs.extrahop_limit_bytes
inputs.extrahop_ip1 = playbook.inputs.extrahop_ip1
inputs.extrahop_port1 = playbook.inputs.extrahop_port1
inputs.extrahop_ip2 = playbook.inputs.extrahop_ip2
inputs.extrahop_port2 = playbook.inputs.extrahop_port2
if inputs.extrahop_output == "extract":
    inputs.extrahop_decrypt_files = playbook.inputs.extrahop_decrypt_files
if inputs.extrahop_output == "pcapng":
    inputs.extrahop_include_secrets = playbook.inputs.extrahop_include_secrets

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_search_packets post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_search_packets"
PB_NAME = "Extrahop Reveal(x): Search Packets"
results = playbook.functions.results.search_packets_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    if CONTENT:
        result = CONTENT.get("result")
        if result.get("attachment"):
            note_text += "ExtraHop Integration: Playbook <b>{0}</b>: Successfully searched for packets for SOAR " \
                         "function <b>{1}</b> with parameters <b>{2}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
            note_text += "<br>Attachment <b>{}<b> added.".format(result.get("attachment"))
        elif result.get("status"):
            note_text += u"ExtraHop Integration: Playbook <b>{0}</b>: Search for packets returned no results for SOAR " \
                        u"SOAR function <b>{1}</b> with parameters <b>{2}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
            note_text += u"<br>Status <b>{}<b>.".format(result.get("status"))
        elif result.get("error"):
            note_text += u"ExtraHop Integration: Playbook <b>{0}</b>: Search for packets failed for " \
                        u"SOAR function <b>{1}</b> with parameters <b>{2}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
            note_text += u"<br>Error <b>{}<b>.".format(result.get("error"))
    else:
        note_text += u"ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     u"to search packets for SOAR function <b>{1}</b> with parameters <b>{2}</b>." \
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) update detection

Update a detection in Extrahop Reveal(x). Required parameter incident_id, detection_id, owner_id, plan_status, resolution. Optional parameters participants.

screenshot: fn-extrahop-revealx-update-detection

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_detection_id

number

No

-

Extrahop detection ID

extrahop_participants

text

No

{ "id": 0, "usernames": [], "origins": [] }

A list of devices and applications associated with a detection.

incident_id

number

Yes

-

-

soar_inc_owner_id

text

No

-

-

soar_inc_plan_status

text

No

-

SOAR incident status

soar_inc_resolution_id

text

No

-

SOAR incident resolution

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": "success"
  },
  "inputs": {
    "extrahop_detection_id": 4294967305,
    "incident_id": 3390,
    "soar_inc_owner_id": "admin@example.com",
    "soar_inc_plan_status": "C",
    "soar_inc_resolution_id": "Resolved"
  },
  "metrics": {
    "execution_time_ms": 635,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 14:18:31",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

inputs.extrahop_detection_id = incident.properties.extrahop_detection_id
inputs.incident_id = incident.id
inputs.soar_inc_owner_id = incident.owner_id
inputs.soar_inc_plan_status = incident.plan_status
inputs.soar_inc_resolution_id = incident.resolution_id

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_update_detection post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_update_detection"
PB_NAME = "Extrahop Reveal(x): Update Detection"
results = playbook.functions.results.update_detection_result
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    if CONTENT:
        result = CONTENT.get("result", None)
        if result == "success":
            playbook.addProperty("update_detection_ok", {})
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Successfully updated the detection status for SOAR " \
                        "function <b>{1}</b> with parameters <b>{2}</b>.".format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        elif result == "failed":
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Failed to update the detection status for " \
                        "SOAR function <b>{1}</b> with parameters <b>{2}</b>.".format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        else:
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Update detection status failed with unexpected " \
                        "response for SOAR function <b>{1}</b> with parameters <b>{2}</b>.".format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
    else:
        note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to update the detection status <b>{1}</b> for SOAR function <b>{2}</b> with parameters <b>{3}</b>."\
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))

    incident.addNote(helper.createRichText(note_text))

main()


Function - Extrahop Reveal(x) update watchlist

Add or remove devices from the watchlist on Extrahop Reveal(x). Required parameter assign or unassign comma-seperated list of devices.

screenshot: fn-extrahop-revealx-update-watchlist

Inputs:

Name

Type

Required

Example

Tooltip

extrahop_assign

text

No

-

Comma or newline seperated list of device ids to assign to a watchlist.

extrahop_unassign

text

No

-

Comma or newline seperated list of device ids to unassign from a watchlist.

Outputs:

NOTE: This example might be in JSON format, but results is a Python Dictionary on the SOAR platform.

results = {
  "content": {
    "result": "success"
  },
  "inputs": {
    "extrahop_assign": "4294967313"
  },
  "metrics": {
    "execution_time_ms": 974,
    "host": "MBP",
    "package": "fn-extrahop",
    "package_version": "1.0.0",
    "timestamp": "2023-04-10 13:52:55",
    "version": "1.0"
  },
  "raw": null,
  "reason": null,
  "success": true,
  "version": 2.0
}

Example Function Input Script:

dev_id = row.devs_id
action = playbook.inputs.extrahop_watchlist_action
if action == "add":
    inputs.extrahop_assign = str(dev_id)
elif action == "remove":
    inputs.extrahop_unassign = str(dev_id)

Example Function Post Process Script:

##  ExtraHop - pb_extrahop_rx_update_watchlist post processing script ##
#  Globals
FN_NAME = "funct_extrahop_rx_update_watchlist"
PB_NAME = "Extrahop Reveal(x): Update Watchlist"
results = playbook.functions.results.update_watchlist_results
CONTENT = results.get("content", {})
INPUTS = results.get("inputs", {})

# Processing
def main():
    note_text = ''
    if CONTENT:
        result = CONTENT["result"]
        if result == "success":
            workflow.addProperty("watchlist_updated", {})
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Successfully updated the watchlist for SOAR " \
                        "function <b>{1}</b> with parameters <b>{2}</b> for device <b>{3}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()), row.devs_id)
        elif result == "failed":
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Failed to update the watchlist for " \
                        "SOAR function <b>{1}</b> with parameters <b>{2}</b> for device <b>{3}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()))
        elif result == "conflict":
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: A 409 (conflict) error was thrown while attempting  " \
                        "to update the watchlist for SOAR function <b>{1}</b> with parameters <b>{2}</b> for device <b>{3}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()), row.devs_id)
            note_text += u"<br>Check if the sensor is being managed from the cloud-based service."
        else:
            note_text = "ExtraHop Integration: Playbook <b>{0}</b>: Update watchlist failed with unexpected " \
                        "response for SOAR function <b>{1}</b> with parameters <b>{2}</b> for device <b>{3}</b>."\
                .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()), row.devs_id)
    else:
        note_text += "ExtraHop Integration: Playbook <b>{0}</b>: There was <b>no</b> result returned while attempting " \
                     "to update the watchlist <b>{1}</b> with parameters <b>{2}</b> for device <b>{3}</b>."\
            .format(PB_NAME, FN_NAME, ", ".join("{}:{}".format(k, v) for k, v in INPUTS.items()), row.devs_id)

    incident.addNote(helper.createRichText(note_text))

main()


Script - ExtraHop script: add artifact from device

Add Devices data table field as a SOAR artifact.

Object: incident

Script Text:

# Create a SOAR artifact based on a dropdown which selects the corresponding data-table field.
ARTIFACT_TYPE = playbook.inputs.extrahop_artifact_type.replace(" (v4)" ,"").replace(" (v6)" ,"")

PARAMS = {
    "IP Address": row.ipaddr4,
    "DNS Name": row.dns_name,
    "MAC Address": row.macaddr
}
# Both IP address V4 or V6 will be added as type "IP Address".
if "v6" in rule.properties.extrahop_artifact_type:
    PARAMS.update({"IP Address": row.ipaddr6})

def addArtifact(artifact_type, artifact_value, description):
    """This method adds new artifacts to the incident derived from matches of the the regular expression

    :param artifact_type: The type of the artifact.
    :param artifact_value: - The value of the artifact.
    :param description: - the description of the artifact.
    """
    incident.addArtifact(artifact_type, artifact_value, description)

def validate_fields(fields, params):
    """
    Ensure required fields are present. Throw ValueError if not
    :param fields: Required fields.
    :param params: Data-table fields as parameters.
    :return: no return
    """
    for f in fields:
        if f not in params or not params.get(f) or params.get(f) == '':
            raise ValueError(str('Required data-table field is missing or empty for artifact type: ' + f))


# Processing starts here
desc = ''
validate_fields([ARTIFACT_TYPE], PARAMS)
desc = "Artifact from Device detected in the ExtraHop environment. Device name '{}', Device ID '{}'.".format(row.default_name, row.devs_id)
addArtifact(ARTIFACT_TYPE, PARAMS[ARTIFACT_TYPE], desc)


Script - ExtraHop script: detection property helper

Set ExtraHop detection properties as workflow property dicts.

Object: incident

Script Text:

##  ExtraHop - scr_extrahop_detection_property_helper script ##
# Used to share data with several workflows.

# Map of detection category  display name to name.
CATEGORY_MAP = {
    "sec.action": "Actions on Objective",
    "sec.botnet": "Botnet",
    "sec.caution": "Caution",
    "sec.command": "Command & Control",
    "sec.cryptomining": "Cryptocurrency Mining",
    "sec.dos": "Denial of Service",
    "sec.exfil": "Exfiltration",
    "sec.exploit": "Exploitation",
    "sec.hardening": "Hardening",
    "sec.lateral": "Lateral Movement",
    "sec.ransomware": "Ransomware",
    "sec.recon": "Reconnaissance",
    "sec": "Security"
}
# Map of detection type name to  display name.
TYPE_MAP = {
    "aaa_auth_errors": "AAA Auth Errors",
    "aaa_brute_force": "Spike in AAA Failed Login Attempts",
    "abnormally_large_database_response": "Database Data Staging",
    "abnormal_s3_upload": "Data Exfiltration to S3 Bucket",
    "abnormal_user_creation": "Unusual User Creation",
    "add_printer_driver": "New Printer Driver Installation Request",
    "anonymous_ftp": "Anonymous FTP Auth Enabled",
    "apache_http_server_path_traversal": "Apache HTTP Server Path Traversal Exploit",
    "apache_struts2_exploit_attempt": "Apache Struts 2 Exploit Attempt",
    "attempted_connections_dropped": "Attempted Connections Dropped",
    "aws_imds_proxying": "AWS Instance Metadata Service (IMDS) Proxy",
    "aws_services_enumeration": "AWS Cloud Service Enumeration",
    "bittorrent_activity": "BitTorrent Activity",
    "blacklisted_cert": "Suspicious SSL/TLS Certificates",
    "bloodhound_enumeration_activity": "BloodHound Enumeration Activity",
    "c2_web_beaconing": "Command-and-Control Beaconing",
    "call_does_not_exist_error": "Call Does Not Exist Error",
    "cifs_round_trip_time": "SMB/CIFS Transaction Delays",
    "cisco_cdp_vulnerabilities": "Cisco CDP Exploit Attempt",
    "citrix_issues": "Citrix Issues",
    "cobalt_strike_c2_dns": "Cobalt Strike DNS Beaconing",
    "cobalt_strike_c2_http": "Cobalt Strike C&C HTTP Connection",
    "cobalt_strike_c2_tls": "Cobalt Strike C&C SSL/TLS Connection",
    "crit_server_suspicious_download": "Suspicious File Download on Critical Server",
    "cryptocurrency_mining": "Cryptocurrency Mining",
    "cryptomining_pool_dns_request": "DNS Request for a Cryptocurrency Mining Pool",
    "cryptomining_pool_ssl_connection": "SSL/TLS Connection to a Cryptocurrency Mining Pool",
    "customer_detection_template": "Custom",
    "cve_2017_12635": "CVE-2017-12635 Apache CouchDB Exploit Attempt",
    "cve_2018_1111": "CVE-2018-1111 Red Hat DHCP Exploit Attempt",
    "cve_2018_13379": "CVE-2018-13379 Fortinet FortiOS Exploit",
    "cve_2018_15961": "CVE-2018-15961 Adobe ColdFusion Exploit Attempt",
    "cve_2018_7600": "Drupal Exploit Attempt",
    "cve_2019_0193": "CVE-2019-0193 Apache Solr Exploit Attempt",
    "cve_2019_0604": "CVE-2019-0604 Microsoft SharePoint Exploit Attempt",
    "cve_2019_0708": "CVE-2019-0708 RDP Exploit Attempt",
    "cve_2019_10149": "CVE-2019-10149 Exim Exploit Attempt",
    "cve_2019_11510": "CVE-2019-11510 Pulse Connect Secure Exploit Attempt",
    "cve_2019_11580": "CVE-2019-11580: Atlassian Crowd Vulnerability",
    "cve_2019_15846": "CVE-2019-15846 Exim Exploit Attempt",
    "cve_2019_17558": "CVE-2019-17558 Apache Solr Exploit",
    "cve_2019_19781_exploit": "CVE-2019-19781 Citrix ADC and Gateway Exploit",
    "cve_2019_19781_scan": "CVE-2019-19781 Citrix ADC and Gateway Scan",
    "cve_2019_2725": "Oracle WebLogic Exploit",
    "cve_2019_8394": "CVE-2019-8394 Zoho ManageEngine Exploit Attempt",
    "cve_2019_9670": "CVE-2019-9670 Synacor Zimbra Collaboration Suite Exploit Attempt",
    "cve_2020_0601": "CVE-2020-0601 Windows CryptoAPI ECC Validation Vulnerability",
    "cve_2020_0796": "CVE-2020-0796 Windows 10 SMBv3 Exploit Attempt",
    "cve_2020_10189": "CVE-2020-10189 Zoho ManageEngine Exploit",
    "cve_2020_11651": "CVE-2020-11651 Salt Exploit Attempt",
    "cve_2020_12695": "CVE-2020-12695 UPnP Exploit Attempt",
    "cve_2020_1301": "CVE-2020-1301 SMBv1 Exploit",
    "cve_2020_1350": "CVE-2020-1350 SIGRed Exploit Attempt",
    "cve_2020_1472": "CVE-2020-1472 Zerologon Scan",
    "cve_2020_1472_exploit": "CVE-2020-1472 Zerologon Exploit Attempt",
    "cve_2020_15505": "CVE-2020-15505 MobileIron Core and Connector Exploit Attempt",
    "cve_2020_16898": "CVE-2020-16898 Windows TCP/IP Stack Exploit Attempt",
    "cve_2020_16899": "CVE-2020-16899 Windows TCP/IP Stack Exploit Attempt",
    "cve_2020_17051": "CVE-2020-17051 Windows NFS Exploit Attempt",
    "cve_2020_1938": "CVE-2020-1938 Ghostcat Exploit",
    "cve_2020_25577": "CVE-2020-25577 FreeBSD Exploit Attempt",
    "cve_2020_25583": "CVE-2020-25583 FreeBSD Exploit Attempt",
    "cve_2020_3952": "CVE-2020-3952 VMware vCenter Exploit",
    "cve_2020_5902": "CVE-2020-5902 F5 BIG-IP Exploit",
    "cve_2020_6207": "CVE-2020-6207 SAP Solution Manager Exploit Attempt",
    "cve_2020_6287": "CVE-2020-6287 SAP RECON Vulnerability",
    "cve_2020_7247": "CVE-2020-7247 OpenSMTPD Exploit Attempt",
    "cve_2021_1497": "CVE-2021-1497 Cisco HyperFlex HX Exploit Attempt",
    "cve_2021_1498": "CVE-2021-1498 Cisco HyperFlex HX Exploit Attempt",
    "cve_2021_21972_exploit": "CVE-2021-21972 VMware vCenter Exploit",
    "cve_2021_21972_scan": "CVE-2021-21972 VMware vCenter Scan",
    "cve_2021_21974": "CVE-2021-21974 VMware ESXi OpenSLP Exploit Attempt",
    "cve_2021_21985": "CVE-2021-21985 VMware vCenter Exploit",
    "cve_2021_22005": "CVE-2021-22005 VMware vCenter Exploit",
    "cve_2021_22006": "CVE-2021-22006 VMware vCenter Exploit",
    "cve_2021_22205": "CVE-2021-22205 GitLab CE and EE Exploit Attempt",
    "cve_2021_22893": "CVE-2021-22893 Pulse Connect Secure Exploit Attempt",
    "cve_2021_22986": "CVE-2021-22986 F5 BIG-IP and BIG-IQ Exploit",
    "cve_2021_22991": "CVE-2021-22991 F5 BIG-IP Exploit",
    "cve_2021_26084": "CVE-2021-26084 Atlassian Confluence Exploit Attempt",
    "cve_2021_26432": "CVE-2021-26432 Windows NFS ONCRPC Exploit Attempt",
    "cve_2021_26877": "CVE-2021-26877 Windows DNS Server Exploit Attempt",
    "cve_2021_26897": "CVE-2021-26897 Windows DNS Server Exploit Attempt",
    "cve_2021_28324": "CVE-2021-28324 Windows 10 SMBv3 Exploit Attempt",
    "cve_2021_31166": "CVE-2021-31166 Windows HTTP Stack Exploit Attempt",
    "cve_2021_31181": "CVE-2021-31181 Microsoft SharePoint Exploit Attempt",
    "cve_2021_34467": "CVE-2021-34467 Microsoft SharePoint Exploit Attempt",
    "cve_2021_34473": "CVE-2021-34473 Microsoft Exchange Server Exploit",
    "cve_2021_34527": "CVE-2021-34527 Windows Print Spooler Exploit Attempt",
    "cve_2021_35394": "CVE-2021-35394 Realtek SDK Exploit Attempt",
    "cve_2021_35395": "CVE-2021-35395 Realtek SDK Exploit Attempt",
    "cve_2021_38647": "CVE-2021-38647 OMIGOD Exploit",
    "cve_2021_42321": "CVE-2021-42321 Microsoft Exchange Exploit Attempt",
    "cve_2021_43798": "CVE-2021-43798 Grafana Exploit Attempt",
    "cve_2021_44228_jndi_injection_attempt": "Log4Shell JNDI Injection Attempt",
    "cve_2021_44228_outbound_activity": "Outbound Log4Shell Activity",
    "cve_2022_0543": "CVE-2022-0543 Redis Exploit",
    "cve_2022_1388": "CVE-2022-1388 F5 BIG-IP Exploit",
    "cve_2022_21907": "CVE-2022-21907 Windows HTTP Stack Exploit Attempt",
    "cve_2022_22947": "CVE-2022-22947 Spring Cloud Gateway Exploit Attempt",
    "cve_2022_22963": "CVE-2022-22963 Spring Cloud Function Exploit Attempt",
    "database_brute_force": "Database Brute Force",
    "database_enumeration": "Database Enumeration",
    "database_issues": "Database Issues",
    "database_takeover": "Database Takeover Attack",
    "database_transaction_failures": "Database Transaction Failures",
    "data_exfil_by_vpn": "VPN Client Data Exfiltration",
    "data_exfiltration": "Data Exfiltration",
    "data_transfer_issues": "Data Transfer Issues",
    "db_processing_spike": "Poor Database Performance",
    "dcom_lateral_movement": "DCOM Remote Command Launch",
    "dcshadow": "DCShadow Attack",
    "dcsync": "DCSync Attack",
    "delayed_citrix_data_transfer": "Delayed Citrix Data Transfer",
    "delayed_database_data_transfer": "Delayed Database Data Transfer",
    "delayed_data_transfer": "Delayed Data Transfer",
    "delayed_email_data_transfer": "Delayed Email Data Transfer",
    "delayed_ftp_data_transfer": "Delayed FTP Data Transfer",
    "delayed_http_data_transfer": "Delayed HTTP Data Transfer",
    "delayed_ip_address_configuration": "Delayed IP Address Configuration",
    "delayed_kerberos_auth": "Delayed Kerberos Auth",
    "delayed_kerberos_data_transfer": "Delayed Kerberos Data Transfer",
    "delayed_ldap_auth": "Delayed LDAP Auth",
    "delayed_ldap_data_transfer": "Delayed LDAP Data Transfer",
    "delayed_memcache_data_transfer": "Delayed Memcache Data Transfer",
    "delayed_redis_data_transfer": "Delayed Redis Data Transfer",
    "delayed_web_services": "Delayed Web Services",
    "delayed_wifi_auth": "Delayed WiFi Auth",
    "dhcp_decline_error": "DHCP Decline Error",
    "dhcp_errors": "DHCP Errors",
    "dhcp_issues": "DHCP Issues",
    "dhcp_restart_error": "DHCP Restart Error",
    "dns_brute_force": "DNS Brute Force",
    "dns_errors": "DNS Errors",
    "dns_internal_reverse_lookup_scan": "DNS Internal Reverse Lookup Scan",
    "dns_issues": "DNS Issues",
    "dns_lookup_failures": "DNS Lookup Failures",
    "dns_rebind": "DNS Rebinding",
    "dns_request_timeouts": "DNS Request Timeouts",
    "dns_timeouts": "DNS Timeouts",
    "dns_tunnel": "DNS Tunnel",
    "dns_zone_transfer": "DNS Zone Transfer",
    "domain_fronting": "Domain Fronting",
    "domain_generation_algorithm": "Domain Generation Algorithm",
    "domain_generation_algorithm_resolved": "DGA Domain Resolution",
    "domain_generation_algorithm_unresolved": "DGA Domain Queries",
    "domain_trust_enumeration": "Domain Trust Enumeration",
    "domain_trusts_enumeration": "Domain Trusts Enumeration",
    "doublepulsar_rdp_implant": "DoublePulsar RDP Implant",
    "doublepulsar_rdp_scan": "DoublePulsar RDP Scan",
    "doublepulsar_smb_implant": "DoublePulsar SMB/CIFS Implant Activity",
    "doublepulsar_smb_scan": "DoublePulsar SMB/CIFS Scan",
    "email_errors": "Email Errors",
    "email_issues": "Email Issues",
    "email_mailbox_unavailable_error": "Email Mailbox Unavailable Error",
    "email_service_unavailable_error": "Email Service Unavailable Error",
    "empire_c2_http": "Empire C&C HTTP Connection",
    "empire_c2_tls": "Empire C&C SSL/TLS Connection",
    "eternalblue_exploit": "EternalBlue Exploit",
    "excessive_ip_fragmentation": "Overlapping IP Fragmentation",
    "experimental": "Experimental Detection",
    "experimentalMetric": "Experimental Detection for Protocol Activity",
    "experimentalMetricAnomaly": "Experimental Detection for a Single Metric",
    "experimentalSource": "Experimental Detection for a Single Source",
    "expired_cert": "Expired SSL Server Certificates",
    "external_db_req": "Request to External Database Server",
    "external_exec_file_download": "Unusual Executable File Download",
    "external_ldap_req": "Request to External LDAP Server",
    "external_nfs_req": "Request to External NFS Server",
    "external_ssh_new_device": "New SSH Device",
    "file_access_failure": "File Access Failure",
    "ftp_access_denied_error": "FTP Access Denied Error",
    "ftp_bad_syntax_error": "FTP Bad Syntax Error",
    "ftp_brute_force": "FTP Brute Force",
    "ftp_errors": "FTP Errors",
    "ftp_file_transfer_issues": "FTP File Transfer Issues",
    "ftp_not_logged_in_error": "FTP Not Logged in Error",
    "hacking_tools": "Hacking Tool Domain Access",
    "high_citrix_latency": "High Citrix Latency",
    "http_400_status_codes": "HTTP 400 Status Codes",
    "http_bad_requests": "HTTP Bad Requests",
    "http_desync_attack": "HTTP Desync Attack",
    "http_errors": "HTTP Errors",
    "http_forbidden": "HTTP Forbidden",
    "http_gateway_timeout_error": "HTTP Gateway Timeout Error",
    "http_internal_error": "HTTP Internal Error",
    "http_method_scan": "HTTP Method Scan",
    "http_not_found": "HTTP Not Found",
    "http_path_traversal": "HTTP Path Traversal",
    "http_plaintext_password_client": "Credentials Sent over HTTP",
    "http_plaintext_password_server": "Credentials Received over HTTP",
    "http_service_unavailable_error": "HTTP Service Unavailable Error",
    "icmp_tunnel": "ICMP Tunnel",
    "inbound_cobalt_strike_connection": "Inbound Connection from a Cobalt Strike IP Address",
    "inbound_tor_connection": "Inbound Tor Node Connections",
    "interactive_traffic_remote_desktop": "Unusual Interactive Traffic from a Remote Desktop",
    "interactive_traffic_shell": "Unusual Interactive Traffic from an External Endpoint",
    "interactive_traffic_ssh": "Remote Control SSH Traffic",
    "interrupted_citrix_data_transfer": "Interrupted Citrix Data Transfer",
    "kali_ssh_server_key": "Default Kali Linux SSH Keys",
    "kaseya_ml": "REvil C&C Activity (Kaseya Supply Chain)",
    "kaseya_ml_ip": "REvil Suspicious Connection (Kaseya Supply Chain)",
    "kaseya_vsa": "Kaseya VSA Activity",
    "kerberos_attack_tool_activity": "Kerberos Attack Tool Activity",
    "kerberos_auth_errors": "Kerberos Auth Errors",
    "kerberos_auth_issues": "Kerberos Auth Issues",
    "kerberos_brute_force": "Kerberos Brute Force",
    "kerberos_duplicate_sessions_errors": "Kerberos Duplicate Sessions Errors",
    "kerberos_expired_password_errors": "Kerberos Expired Password Errors",
    "kerberos_golden_ticket_attack": "Kerberos Golden Ticket Attack",
    "kerberos_invalid_ticket_errors": "Kerberos Invalid Ticket Errors",
    "kerberos_policy_errors": "Kerberos Policy Errors",
    "kerberos_revoked_credentials_errors": "Kerberos Revoked Credentials Errors",
    "kerberos_service_unknown_errors": "Kerberos Service Unknown Errors",
    "kerberos_silver_ticket_attack": "Kerberos Silver Ticket Attack",
    "kerberos_sync_errors": "Kerberos Sync Errors",
    "kerberos_ticket_errors": "Kerberos Ticket Errors",
    "kerberos_unknown_service_errors": "Kerberos Unknown Service Errors",
    "kerberos_user_enumeration": "Kerberos User Enumeration",
    "kerberos_wrong_password_errors": "Kerberos Wrong Password Errors",
    "ldap_all_workstation_enum": "Domain Workstation Enumeration",
    "ldap_as_rep_activity": "AS-REP Roasting Activity",
    "ldap_auth_error": "LDAP Auth Error",
    "ldap_auth_errors": "LDAP Auth Errors",
    "ldap_auth_issues": "LDAP Auth Issues",
    "ldap_client_any_attribute_enum": "LDAP Wildcard Query",
    "ldap_computer_enum": "LDAP Computer Enumeration",
    "ldap_gpo_enumeration": "LDAP GPO Enumeration",
    "ldap_invalid_credentials_error": "LDAP Invalid Credentials Error",
    "ldap_object_enum": "All Object Enumeration",
    "ldap_operational_error": "LDAP Operational Error",
    "ldap_protocol_error": "LDAP Protocol Error",
    "ldap_spn_scan": "LDAP SPN Scan",
    "llmnr_poisoning": "LLMNR Poisoning",
    "local_admin_enumeration": "Windows Account Enumeration",
    "memcache_errors": "Memcache Errors",
    "memcache_issues": "Memcache Issues",
    "meterpreter_shell": "Meterpreter C&C Session",
    "ms_exchange_ssrf_rce": "Microsoft Exchange Server SSRF and RCE Exploit",
    "msf_cert": "Metasploit C&C SSL/TLS Connection",
    "msrpc_admin_access_check": "Unusual Remote Admin Connection Requests",
    "msrpc_alias_member_enum": "Alias Member Enumeration",
    "msrpc_domain_controller_enumeration": "Domain Controller Enumeration",
    "msrpc_group_member_enum": "Group Member Enumeration",
    "msrpc_loggedon_user_enum": "Logged-On User Enumeration",
    "msrpc_netsession_enum": "User Session Enumeration",
    "msrpc_network_share_enum": "Network Share Enumeration",
    "msrpc_rdp_session_enum": "RDP Session Enumeration",
    "msrpc_registry_enumeration_via_winreg": "Windows Registry Enumeration",
    "msrpc_scheduled_task_via_atsvc": "Scheduled Task Activity (ATSVC)",
    "msrpc_scheduled_task_via_ITaskSchedulerService": "Scheduled Task Activity (ITaskSchedulerService)",
    "multiple_email_errors": "Multiple Email Errors",
    "multiple_ftp_errors": "Multiple FTP Errors",
    "multiple_kerberos_auth_errors": "Multiple Kerberos Authentication Errors",
    "multiple_ldap_auth_errors": "Multiple LDAP Auth Errors",
    "multiple_smb_cifs_errors": "Multiple SMB/CIFS Errors",
    "nbt_ns_poisoning": "NBT-NS Poisoning",
    "network_privilege_escalation": "Network Privilege Escalation",
    "new_adws_activity": "New Active Directory Web Service (ADWS) Activity",
    "new_dhcp_activity": "New DHCP Activity",
    "new_doh_activity": "New DNS over HTTPS (DoH) Activity",
    "new_external_connection": "New External Connection",
    "new_external_db_connection": "New External Database Connection",
    "new_external_iiop_connection": "New External IIOP Connection",
    "new_external_ldap_connection": "New External LDAP Connection",
    "new_external_nfs_connection": "New External NFS Connection",
    "new_external_rdp_connection": "New External RDP Connection",
    "new_external_rmi_connection": "New External Java RMI Connection",
    "new_external_ssh_connection": "New External SSH Connection",
    "new_external_telnet_connection": "New External Telnet Connection",
    "new_external_vnc_connection": "New External VNC Connection",
    "new_iot_connection": "New External IoT Connection",
    "new_local_dns_server": "New Local DNS Server Activity",
    "new_smb_cifs_file_transfer": "New SMB/CIFS Executable File Transfer",
    "new_telnet_activity": "New Telnet Activity",
    "nfs_file_access_failure": "NFS File Access Failure",
    "ntlm_relay": "NTLM Relay Attack",
    "ntlmv1_authentication": "NTLMv1 Authentication",
    "numerous_emails": "Numerous Emails",
    "onepercent_ml": "Confirmed OnePercent Group Ransomware IOC",
    "outbound_cobalt_strike_connection": "Outbound Connection to a Cobalt Strike IP Address",
    "outbound_socks_connection": "New Outbound SOCKS Connection",
    "outbound_tor_connection": "Outbound Tor Node Connections",
    "overwhelmed_citrix_data_transfer": "Overwhelmed Citrix Data Transfer",
    "overwhelmed_database_data_transfer": "Overwhelmed Database Data Transfer",
    "overwhelmed_data_transfer": "Overwhelmed Data Transfer",
    "overwhelmed_email_data_transfer": "Overwhelmed Email Data Transfer",
    "overwhelmed_ftp_data_transfer": "Overwhelmed FTP Data Transfer",
    "overwhelmed_http_data_transfer": "Overwhelmed HTTP Data Transfer",
    "overwhelmed_kerberos_data_transfer": "Overwhelmed Kerberos Data Transfer",
    "overwhelmed_ldap_data_transfer": "Overwhelmed LDAP Data Transfer",
    "overwhelmed_memcache_data_transfer": "Overwhelmed Memcache Data Transfer",
    "overwhelmed_redis_data_transfer": "Overwhelmed Redis Data Transfer",
    "ping_scan": "Ping Scan",
    "poor_aaa_performance": "Poor AAA Performance",
    "poor_dhcp_performance": "Poor DHCP Performance",
    "poor_http_performance": "Poor HTTP Performance",
    "potential_covert_channel": "HTTP Tunnel",
    "psexec_activity": "Remote Service Launch",
    "ransomware_activity": "Ransomware Activity",
    "rare_database_table_access": "Rare Database Table Access",
    "rare_ssh_port": "Rare SSH Port",
    "rdp_brute_force": "RDP Brute Force",
    "rdp_unusual_location": "Inbound Remote Desktop Traffic from an Unusual Location",
    "redis_errors": "Redis Errors",
    "redis_issues": "Redis Issues",
    "remote_reg_setvalue": "Remote Registry Modification",
    "reverse_ssh_connection": "Reverse SSH Connection",
    "rfb_brute_force": "VNC Brute Force",
    "ripple20_dns_rce": "CVE-2020-11901 Ripple20 Exploit Attempt",
    "ripple20_icmp_scan": "Ripple20 ICMP Scan",
    "ripple20_icmp_treck": "Treck TCP/IP Network Stack Detected",
    "ripple20_ip_in_ip": "Ripple20 IP in IP Exploit Attempt",
    "ripple20_ip_in_ip_ipaddr": "Ripple20 IP in IP Exploit Attempt",
    "rpc_log_deletion_srv": "Remote Log Deletion",
    "rpc_remote_shutdown": "Remote System Shutdown",
    "samr_domain_admin_enum": "Domain Admin Enumeration",
    "samr_domain_computer_enum": "Domain Workstation Enumeration",
    "samr_domain_group_enum": "Domain Group Enumeration",
    "samr_domain_user_enum": "Domain User Enumeration",
    "samr_domain_workstation_enum": "Domain Workstation Enumeration",
    "samr_local_admin_enum": "Local Admin Enumeration",
    "samr_local_user_enum": "Local User Enumeration",
    "scheduled_task_enumeration": "Scheduled Task Enumeration",
    "sensitive_data_transfer": "Unusual Sensitive Data Transfer",
    "shellshock_dhcp": "Shellshock DHCP Exploit Attempt",
    "shellshock_http": "Shellshock HTTP Exploit Attempt",
    "sip_brute_force": "SIP Brute Force",
    "smb_autostart_path": "File Transfer to Windows Autostart Path",
    "smb_cifs_access_denied_errors": "SMB/CIFS Access Denied Errors",
    "smb_cifs_brute_force": "SMB/CIFS Brute Force",
    "smb_cifs_errors": "SMB/CIFS Errors",
    "smb_cifs_file_access_failure": "SMB/CIFS File Access Failure",
    "smb_cifs_privileged_pipe": "SMB/CIFS Privileged Pipe",
    "smb_cifs_share_enumeration": "SMB/CIFS Share Enumeration",
    "smb_cifs_valid_login_errors": "SMB/CIFS Account Errors",
    "smb_named_pipe_beaconing": "SMB/CIFS Named Pipe Beaconing",
    "smtp_helo_ehlo_buffer_overflow": "Unusual Email Domain Length",
    "smtp_processing_spike": "Poor SMTP Server Performance",
    "smtp_syntax_error": "SMTP Syntax Error",
    "spike_in_email_traffic_volume": "Spike in Email Traffic Volume",
    "spike_in_ldap_requests": "Spike in LDAP Requests",
    "spike_in_rdp_sessions": "Spike in RDP Sessions",
    "spike_in_rfb_sessions": "Spike in VNC Sessions",
    "spike_in_round_trip_time": "Transaction Delays",
    "spike_in_ssh_sessions": "Spike in SSH Sessions",
    "spike_in_telnet_connections": "Spike in Telnet Connections",
    "spoofed_self_signed_ssl_certificate": "Spoofed SSL/TLS Certificate",
    "spring4shell": "CVE-2022-22965 Spring4Shell Exploit Attempt",
    "sqli_attack": "SQL Injection (SQLi) Attack",
    "ssh_brute_force": "SSH Brute Force",
    "ssh_unusual_location": "Inbound SSH Traffic from an Unusual Location",
    "ssh_unusual_location_c2": "Outbound SSH Traffic to an Unusual Location",
    "ssl_scan": "SSL Scan",
    "stalled_data_transfer": "Stalled Data Transfer",
    "sudden_decrease_in_application_bandwidth": "Sudden Decrease in Application Bandwidth",
    "sudden_decrease_in_device_bandwidth": "Sudden Decrease in Device Bandwidth",
    "sudden_decrease_in_network_bandwidth": "Sudden Decrease in Network Bandwidth",
    "sunburst": "SUNBURST C&C Activity",
    "supernova_web_shell_command": "SUPERNOVA Web Shell",
    "suspicious_cifs": "Suspicious SMB/CIFS Resource Accessed",
    "suspicious_file_download_external": "Suspicious External File Download",
    "suspicious_file_download_internal": "Suspicious Internal File Download",
    "suspicious_ftp_data_reads": "FTP Data Staging",
    "suspicious_ftp_download": "Suspicious FTP Download",
    "suspicious_hta_download": "Unusual HTML Application (HTA) File Download",
    "suspicious_http_file": "Suspicious HTTP File Received",
    "suspicious_http_port": "Non-standard HTTP Port",
    "suspicious_ja3_fingerprint": "Suspicious JA3 Fingerprint",
    "suspicious_new_device": "Suspicious New Device Detected",
    "suspicious_nfs_data_reads": "NFS Data Staging",
    "suspicious_nfs_file_reads": "Suspicious NFS File Reads",
    "suspicious_nfs_file_share_access": "Suspicious NFS File Share Access",
    "suspicious_rdp_client": "RDP Attack Tool Activity",
    "suspicious_smb_cifs_data_reads": "SMB/CIFS Data Staging",
    "suspicious_smb_cifs_file_reads": "Suspicious SMB/CIFS File Reads",
    "suspicious_smb_cifs_file_share_access": "Suspicious SMB/CIFS File Share Access",
    "suspicious_smb_cifs_file_transfer": "Unusual SMB/CIFS Executable File Transfer",
    "suspicious_smb_named_pipe": "Suspicious SMB/CIFS Named Pipe",
    "suspicious_tld": "Suspicious Top-level Domain",
    "suspicious_user_agent": "Suspicious User Agent",
    "tcp_null_fin_or_xmas_scan": "TCP NULL, FIN, or XMAS Scan",
    "tcp_syn_scan": "TCP SYN Scan",
    "tcp_urg_flag_client": "TCP Stack Exploit Attempt (Client)",
    "tcp_urg_flag_server": "TCP Stack Exploit Attempt (Server)",
    "telnet_password": "Telnet Password",
    "ti_dns_host": "DNS Client Request to a Suspicious Host",
    "ti_http_host": "HTTP Client Request to a Suspicious Host",
    "ti_http_uri": "HTTP Client Request to a Suspicious URI",
    "ti_ssl_sni": "SSL/TLS Connection to a Suspicious Host",
    "ti_tcp_incoming": "Inbound Suspicious Connections",
    "ti_tcp_outgoing": "Outbound Suspicious Connection",
    "tomcat_jsp_upload": "Apache Tomcat JSP Exploit Attempt",
    "udp_port_scan": "UDP Port Scan",
    "unapproved_saas": "Unapproved Cloud Service Access",
    "unauthorized_caller_error": "Unauthorized Caller Error",
    "unconventional_data_transfer": "Unconventional Data Transfer",
    "unconventional_new_external_host": "Unconventional External Connection",
    "unconventional_new_internal_host": "Unconventional Internal Connection",
    "unconventional_new_protocol": "Unconventional Protocol Communication",
    "unconventional_rdp_behavior": "Unconventional RDP Behavior",
    "unconventional_rdp_data_transfer": "Unconventional RDP Data Transfer",
    "unconventional_rfb_behavior": "Unconventional VNC Behavior",
    "unconventional_rfb_data_transfer": "Unconventional VNC Data Transfer",
    "unconventional_smb_cifs_data_transfer": "Unconventional SMB/CIFS Data Transfer",
    "unconventional_ssh_behavior": "Unconventional SSH Behavior",
    "unconventional_ssh_data_transfer": "Unconventional SSH Data Transfer",
    "unconventional_telnet_data_transfer": "Unconventional Telnet Data Transfer",
    "unencrypted_zoom": "Unencrypted Zoom Data",
    "unexpected_dropped_connections": "Unexpected Dropped Connections",
    "unexpected_service_access": "Unexpected Service Access",
    "unknown_public_dns_server": "Unknown Public DNS Server",
    "unknown_s3_bucket_upload": "Data Exfiltration to Unknown S3 Bucket",
    "unsafe_ldap_auth": "Unsafe LDAP Authentication",
    "unusual_iot_protocol": "Unusual IoT Protocol Activity",
    "unusual_kerberos_fingerprint": "Unusual Kerberos Fingerprint",
    "unusual_protocol_for_enterprise_software": "Unusual Protocol for Enterprise Software",
    "unusual_s3_download": "Unusual Download from S3 Bucket",
    "unusual_user_login_time": "Unusual Login Time",
    "vnc_unusual_location": "Inbound VNC Traffic from an Unusual Location",
    "voip_call_failure": "VoIP Call Failure",
    "voip_unavailability_error": "VoIP Unavailability Error",
    "vpn_gateway_unusual_location": "VPN Gateway Access from an Unusual Location",
    "weak_cipher": "Weak Cipher Suites",
    "weak_kerberos_encryption_attempt": "Weak Kerberos Encryption",
    "web_directory_scan": "Web Directory Scan",
    "web_issues": "Web Issues",
    "weblogic_admin_console_handle_rce": "Oracle WebLogic Administration Console Exploit Attempt",
    "weblogic_xml_deserialization": "Oracle WebLogic Deserialization Exploit Attempt",
    "web_service_issues": "Web Service Issues",
    "wifi_auth_issues": "WiFi Auth Issues",
    "wmi_activity": "New WMI Method Launch",
    "wmi_create_process": "New WMI Process Creation",
    "wmi_enumeration_query": "New WMI Enumeration Query",
    "wordpress_brute_force": "WordPress Brute Force",
    "wsman_activity": "PowerShell Remoting Activity",
    "xss_attack": "Cross-Site Scripting (XSS) Attack"
}

try:
    playbook.addProperty("category_map", CATEGORY_MAP)
    playbook.addProperty("type_map", TYPE_MAP)
    script_inputs = playbook.inputs
except:
    workflow.addProperty("category_map", CATEGORY_MAP)
    workflow.addProperty("type_map", TYPE_MAP)
    script_inputs = rule.properties


Playbooks

Playbook Name

Description

Activation Type

Object

Status

Condition

ExtraHop Reveal(x): Add Artifact (PB)

Add Devices data table field as a SOAR artifact.

Manual

extrahop_devices

enabled

extrahop_devices.dns_name has_a_value OR extrahop_devices.ipaddr4 has_a_value OR extrahop_devices.macaddr has_a_value

ExtraHop Reveal(x): Assign Tag (PB)

Assign a tag to a list of devices ids for Extrahop Reveal(x).

Manual

extrahop_devices

enabled

extrahop_devices.devs_id has_a_value

ExtraHop Reveal(x): Create Tag (PB)

Create a new tag for Extrahop Reveal(x).

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Get Activity Maps (PB)

Get activity maps information from Extrahop Reveal(x) and write to the ExtraHop Activitymaps data table.

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Get Tags (PB)

Get tags information from Extrahop Reveal(x) and write to the ExtraHop Tags data table.

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Get Watchlist (PB)

Retrieve all devices that are in the watchlist from Extrahop Reveal(x) .

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Refresh Case (PB)

Refresh SOAR case with detection and device information from Extrahop Reveal(x) .

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Search Detections (PB)

Search for detections information from Extrahop Reveal(x).

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Search Devices (PB)

Search for devices information from Extrahop Reveal(x) using a filter.

Manual

incident

enabled

incident.properties.extrahop_detection_id has_a_value

ExtraHop Reveal(x): Search Packets (PB)

Search for and download packets stored on the ExtraHop Reveal(x) system and add as an attachment. Valid output types are: pcap, keylog_txt or zip.

Manual

artifact

enabled

artifact.type equals DNS Name OR artifact.type equals IP Address OR artifact.type equals MAC Address

ExtraHop Reveal(x): Update Case (PB)

Automatic playbook to update ExtraHop SOAR case with detection information from Extrahop Reveal(x) .

Automatic

incident

enabled

incident.properties.extrahop_detection_id has_a_value AND object_added

ExtraHop Reveal(x): Update Detection (PB)

Automatic playbook to update ExtraHop detection if the status is changed on the associated SOAR incident. Add a resolution note to the detection.

Automatic

incident

enabled

incident.plan_status changed_to Closed AND incident.resolution_summary not_contains Closed by ExtraHop

ExtraHop Reveal(x): Update Watchlist (PB)

Add or remove an ExtraHop device to or from the watchlist.

Manual

extrahop_devices

enabled

-


Custom Layouts

  • Import the Data Tables and Custom Fields like the screenshot below:

    screenshot: custom_layouts

Data Table - ExtraHop Activity Maps

screenshot: dt-extrahop-activity-maps

API Name:

extrahop_activitymaps

Columns:

Column Name

API Access Name

Type

Tooltip

Description

ams_description

text

-

ID

ams_id

text

-

Mod time

mod_time

datetimepicker

-

Mode

mode

text

-

Name

ams_name

text

-

Owner

owner

text

-

Query execution date

query_execution_date

text

-

Rights

rights

text

-

Short code

short_code

text

-

Show alert status

show_alert_status

text

-

Walks

walks

textarea

-

Weighting

weighting

text

-


Data Table - ExtraHop Detections

screenshot: dt-extrahop-detections screenshot: dt-extrahop-detections_2 screenshot: dt-extrahop-detections_3

API Name:

extrahop_detections

Columns:

Column Name

API Access Name

Type

Tooltip

Appliance ID

appliance_id

text

The identifier for a sensor.

Assignee

assignee

text

-

Categories

categories

text

-

Description

det_description

text

-

Detection ID

det_id

text

-

Detection URL

detection_url

textarea

-

End time

end_time

datetimepicker

-

Is user created

is_user_created

text

-

Mitre tactics

mitre_tactics

textarea

-

Mitre techniques

mitre_techniques

textarea

-

Mod time

mod_time

datetimepicker

Returns detections that were updated after the specified date, expressed in milliseconds since the epoch.

Participants

participants

textarea

-

Properties

properties

textarea

-

Query execution date

query_execution_date

text

-

Resolution

resolution

text

-

Risk score

risk_score

text

-

Start time

start_time

datetimepicker

-

Status

status

text

-

Ticket ID

ticket_id

text

-

Ticket URL

ticket_url

textarea

-

Title

title

text

-

Type

type

text

-

Update time

update_time

datetimepicker

Returns detections related to events that occurred after the specified date, expressed in milliseconds since the epoch. Note that ExtraHop Machine Learning Services analyze historical data to generate detections, and so there is a time delay between when the events that cause those detections occur and when the detections are generated. If you search for detections in the same update_time window multiple times, the later search might return detections that were not returned by the earlier search.


Data Table - ExtraHop Devices

screenshot: dt-extrahop-devices screenshot: dt-extrahop-devices_2

API Name:

extrahop_devices

Columns:

Column Name

API Access Name

Type

Tooltip

Activity

activity

text

-

Default name

default_name

text

-

Description

devs_description

text

-

Device ID

devs_id

number

REST API ID

Device URL

device_url

textarea

Linkback to device on ExtraHop.

Discovery time

discover_time

datetimepicker

-

Display name

display_name

text

-

DNS name

dns_name

text

-

ExtraHop ID

extrahop_id

text

ExtraHop Discovery ID

IPaddr4

ipaddr4

text

-

IPaddr6

ipaddr6

text

-

Last seen time

last_seen_time

datetimepicker

-

MACaddr

macaddr

text

-

Modification time

mod_time

datetimepicker

-

On watchlist

on_watchlist

text

-

Query execution date

query_execution_date

text

-

Role

role

text

-

User modification time

user_mod_time

datetimepicker

-

Vendor

vendor

text

-


Data Table - ExtraHop Tags

screenshot: dt-extrahop-tags

API Name:

extrahop_tags

Columns:

Column Name

API Access Name

Type

Tooltip

ID

tag_id

text

Tag ID

Mod time

mod_time

datetimepicker

Tag modification time

Query execution date

query_execution_date

text

-

Tag

tag

text

Tag name


Data Table - ExtraHop Watchlist

screenshot: dt-extrahop-watchlist

API Name:

extrahop_watchlist

Columns:

Column Name

API Access Name

Type

Tooltip

Display name

display_name

text

-

ExtraHop ID

extrahop_id

text

-

IPaddr4

ipaddr4

text

-

IPaddr6

ipaddr6

text

-

MACaddr

macaddr

text

-

Query execution date

query_execution_date

text

-


Custom Fields

Label

API Access Name

Type

Prefix

Placeholder

Tooltip

ExtraHop Assignee

extrahop_assignee

text

properties

-

-

ExtraHop Console URL

extrahop_console_url

text

properties

-

ExtraHop base console url.

ExtraHop Detection ID

extrahop_detection_id

number

properties

-

Extrahop detecion ID.

ExtraHop Detection Link

extrahop_detection_link

textarea

properties

-

Link back to ExtraHop detection

ExtraHop Detection Updated

extrahop_detection_updated

datetimepicker

properties

-

Field to indicate detection has been updated

ExtraHop End Time

extrahop_end_time

datetimepicker

properties

-

-

ExtraHop Mod Time

extrahop_mod_time

datetimepicker

properties

-

-

ExtraHop Risk Score

extrahop_risk_score

number

properties

-

-

ExtraHop Site Name

extrahop_site_name

text

properties

-

The name of the ExtraHop appliance.

ExtraHop Site UUID

extrahop_site_uuid

text

properties

-

The uuidof the ExtraHop appliance.

ExtraHop Status

extrahop_status

text

properties

-

-

ExtraHop Ticket ID

extrahop_ticket_id

text

properties

-

-

ExtraHop Update Notification

extrahop_update_notification

textarea

properties

-

-

ExtraHop Update Time

extrahop_update_time

datetimepicker

properties

-

-


Playbooks

Playbook Name

Description

Object

Status

ExtraHop Reveal(x): Add Artifact (PB)

Add Devices data table field as a SOAR artifact.

extrahop_devices

enabled

ExtraHop Reveal(x): Assign Tag (PB)

Assign a tag to a list of devices ids for Extrahop Reveal(x).

extrahop_devices

enabled

ExtraHop Reveal(x): Create tag (PB)

Create a new tag for ExtraHop Reveal(x).

incident

enabled

ExtraHop Reveal(x): Get Activity Maps (PB)

Get activity maps information from Extrahop Reveal(x) and write to the ExtraHop Activitymaps data table.

incident

enabled

ExtraHop Reveal(x): Get Tags (PB)

Get tags information from Extrahop Reveal(x) and write to the ExtraHop Tags data table.

incident

enabled

ExtraHop Reveal(x): Get Watchlist (PB)

Retrieve all devices that are in the watchlist from Extrahop Reveal(x).

incident

enabled

ExtraHop Reveal(x): Refresh Case (PB)

Manually refresh SOAR case with detection and device information from Extrahop Reveal(x).

incident

enabled

ExtraHop Reveal(x): Search Detections (PB)

Search for detections information from Extrahop Reveal(x).

incident

enabled

ExtraHop Reveal(x): Search Devices (PB)

Search for devices information from Extrahop Reveal(x) using a filter.

incident

enabled

ExtraHop Reveal(x): Search Packets (PB)

Search for and download packets stored on the ExtraHop Reveal(x) system and add as an attachment. Supported output formats: pcap, keylog_txt, pcapng, zip, extract.

artifact

enabled

ExtraHop Reveal(x): Update Detection (PB)

Automatic playbook to update ExtraHop detection if the status is changed on the associated SOAR incident. Add a resolution note to the detection.

incident

enabled

ExtraHop Reveal(x): Update Case (PB)

Automatic playbook to update ExtraHop SOAR case with detection information from Extrahop.

incident

enabled

ExtraHop Reveal(x): Update Watchlist (PB)

Add or remove an ExtraHop device to or from the watchlist.

extrahop_devices

enabledt


Templates for SOAR Cases

It may necessary to modify the templates used to create or close SOAR cases based on a customer’s required custom fields. Below are the default templates used which can be copied, modified and used with app_config’s soar_create_case_template and soar_close_case_template settings to override the default templates.

soar_close_incident.jinja

When overriding the template in App Host, specify the file path as /var/rescircuits.

{
  {# JINJA template for closing a SOAR incident from an ExtraHop detection. #}
  "plan_status": "C",
  "resolution_id": "{{ resolution | soar_substitute('{"None": "Unresolved", "no_action_taken": "Not an Issue", "action_taken": "Resolved"}') }}",
  "resolution_summary": "Closed by ExtraHop, Detection resolution = {{ resolution }}",
  "properties": {
    "extrahop_status": "{{ status | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_ticket_id": "{{ ticket_id |soar_substitute('{"None": "None"}') }}",
    "extrahop_assignee": "{{ assignee | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_update_notification": "<span style='color:red;'>The ExtraHop Detection has been closed.</span><br><div>To refresh the incident run the playbook: Extrahop Reveal(x) Refresh Case.<div/>"
  }
}

soar_create_incident.jinja

When overriding the template in App Host, specify the file path as /var/rescircuits.

{
  {# JINJA template for creating a new SOAR incident from an ExtraHop detection. #}
  "name": "ExtraHop detection - {{ title }}",
  {# Remove escapes and backticks unnecessary for payload, introduced by api for some detections. #}
  "description": {
    "format": "html",
    "content": {{description | e | replace('\n','<br>')  | replace('\_', '_') | replace ('\.', '.') | tojson}}
  },
  {# start_date cannot be after discovered_date #}
  "discovered_date": {{ start_time }},
  "start_date": {{ start_time }},
  {# if detection users are different than SOAR users, consider using a mapping table using soar_substitute: #}
  {# "owner_id": "{{ assignedTo|soar_substitute('{"Automation": "soar_user1@ent.com", "defender_user2@co.com": "soar_user2@ent.com", "DEFAULT": "default_user@ent.com" }') }}", #}
  "plan_status": "{{ status|string|soar_substitute('{"None": "A", "acknowledged": "A", "in_progress": "A", "closed": "C"}') }}",
{% if 1.0 <= risk_score <= 30 %}
  "severity_code": "Low",
{% elif 31 <= risk_score <= 79 %}
  "severity_code": "Medium",
{% else %}
  "severity_code": "High",
{% endif %}
  "properties": {
    "extrahop_detection_id": {{ id }},
    "extrahop_mod_time": {{ mod_time }},
    "extrahop_update_time": {{ update_time }},
     {% if end_time %}
        "extrahop_end_time": {{ end_time }},
     {% endif %}
    "extrahop_risk_score": {{ risk_score }},
    "extrahop_status": "{{ status | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_ticket_id": "{{ ticket_id |soar_substitute('{"None": "None"}') }}",
    "extrahop_assignee": "{{ assignee | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_detection_link": "<a target='blank' href='{{ detection_url }}'>ExtraHop detection</a>",
    "extrahop_console_url": "{{ console_url }}",
    "extrahop_site_name": "{{ network.name }}",
    "extrahop_site_uuid": "{{ network.appliance_uuid }}"
  },
  "comments": [
    {
      "text": {
          "format": "text",
          "content": "Created by ExtraHop from a detection."
      }
    }
  ]
}

soar_ticketid_incident.jinja

When overriding the template in App Host, specify the file path as /var/rescircuits.

{
  {# JINJA template for updating a SOAR incident ticket id when SOAR case linked to an ExtraHop detection. #}
  "properties": {
    "extrahop_ticket_id": "{{ ticket_id }}"
  }
}

soar_update_incident.jinja

When overriding the template in App Host, specify the file path as /var/rescircuits.

{
  {# JINJA template for updating a SOAR incident from an ExtraHop detection. #}
  "name": "ExtraHop detection - {{ title }}",
  {# Remove escapes and backticks unnecessary for payload, introduced by api for some detections. #}
  "description": {
    "format": "html",
    "content": {{description | e | replace('\n','<br>')  | replace('\_', '_') | replace ('\.', '.') | tojson}}
  },
{% if end_time %}
  "end_date": {{ end_time }},
{% endif %}
  {# if detection users are different than SOAR users, consider using a mapping table using soar_substitute: #}
  {# "owner_id": "{{ assignedTo|soar_substitute('{"Automation": "soar_user1@ent.com", "defender_user2@co.com": "soar_user2@ent.com", "DEFAULT": "default_user@ent.com" }') }}", #}
  "plan_status": "{{ status|string|soar_substitute('{"None": "A", "acknowledged": "A", "in_progress": "A", "closed": "C"}') }}",
{% if 1.0 <= risk_score <= 30 %}
  "severity_code": "Low",
{% elif 31 <= risk_score <= 79 %}
  "severity_code": "Medium",
{% else %}
  "severity_code": "High",
{% endif %}
  "properties": {
    "extrahop_update_time": {{ update_time }},
    "extrahop_mod_time": {{ mod_time }},
     {% if end_time %}
        "extrahop_end_time": {{ end_time }},
     {% endif %}
    "extrahop_risk_score": {{ risk_score }},
    "extrahop_status": "{{ status | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_ticket_id": "{{ ticket_id |soar_substitute('{"None": "None"}') }}",
    "extrahop_assignee": "{{ assignee | string |soar_substitute('{"None": "None"}') }}",
    "extrahop_detection_updated": {{ epoch_now }},
    "extrahop_update_notification": "<span style='color:red;'>The ExtraHop Detection has been updated.</span><br><div>To refresh the case run the playbook: Extrahop Reveal(x): Refresh Case (PB).<div/>"
  }
}

Troubleshooting & Support

Refer to the documentation listed in the Requirements section for troubleshooting information.

For Support

This is an IBM supported app. Please search ibm.com/mysupport for assistance.