BreachRx
Automate your privacy Incident Response workflow through the BreachRx platform.
Case Management · BreachRx
Details
| ID | BreachRx |
|---|---|
| Provider | BreachRx |
| Category | Case Management |
| From Version | 6.2.0 |
| Docker Image | demisto/graphql:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
Automate your privacy Incident Response workflow through the BreachRx platform.
This integration was integrated and tested with version 1.20 of BreachRx
Configure BreachRx in Cortex
| Parameter | Description | Required |
|---|---|---|
| Your BreachRx URL | True | |
| GraphQL API URL | True | |
| API Key | The API Key to use for connection | True |
| Secret Key | The API Key to use for connection | True |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
breachrx-incident-create
Create a privacy Incident on the BreachRx platform.
Base Command
breachrx-incident-create
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_name | The name to use when creating the privacy Incident on the BreachRx platform. | Optional |
| description | A brief description to explain the privacy Incident on the BreachRx platform. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BreachRx.Incident.id | string | The ID of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.name | string | The name of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.description | string | The description of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.identifier | string | The unique identifier of the privacy Incident on the BreachRx platform. |
breachrx-incident-actions-get
Fetch all actions for a BreachRx privacy Incident.
Base Command
breachrx-incident-actions-get
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_name | The name of the BreachRx incident to associate with this incident. | Optional |
| incident_identifier | The unique identifier of the BreachRx incident to associate with this incident. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BreachRx.Incident.Actions.id | string | The ID of an Action on a BreachRx privacy Incident. |
| BreachRx.Incident.Actions.name | string | The name of an Action on a BreachRx privacy Incident. |
| BreachRx.Incident.Actions.description | string | The description of an Action on a BreachRx privacy Incident. |
| BreachRx.Incident.Actions.user.email | string | The email of the assigned user of an Action on a BreachRx privacy Incident, if that Action is assigned to a user (null otherwise). |
breachrx-incident-import
Link a BreachRx privacy Incident with an XSOAR Incident.
Base Command
breachrx-incident-import
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_name | The name of the BreachRx incident to associate with this incident. | Optional |
| incident_identifier | The unique identifier of the BreachRx incident to associate with this incident. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BreachRx.Incident.id | string | The ID of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.name | string | The name of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.identifier | string | The unique identifier of the privacy Incident on the BreachRx platform. |
breachrx-incident-get
Find a BreachRx privacy Incident on the connected BreachRx platform.
Base Command
breachrx-incident-get
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_name | The name of the BreachRx incident to associate with this incident. | Optional |
| incident_identifier | The unique identifier of the BreachRx incident to associate with this incident. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BreachRx.Incident.id | string | The ID of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.name | string | The name of the privacy Incident on the BreachRx platform. |
| BreachRx.Incident.identifier | string | The unique identifier of the privacy Incident on the BreachRx platform. |
Configuration parameters
url— Your BreachRx URL (required)api_url— GraphQL API URL (required)credentials— API Key (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)
Commands (4)
-
breachrx-incident-actions-getFetch all actions for a BreachRx privacy Incident.
-
breachrx-incident-createCreate a privacy Incident on the BreachRx platform.
-
breachrx-incident-getFind a BreachRx privacy Incident on the connected BreachRx platform.
-
breachrx-incident-importLink a BreachRx privacy Incident with an XSOAR Incident.
from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import from CommonServerUserPython import * # noqa from collections.abc import Callable import traceback from urllib.parse import urlparse from gql import gql, Client from gql.transport.requests import RequestsHTTPTransport from requests.auth import HTTPBasicAuth create_incident_mutation = gql(""" mutation CreateIncident( $severity: String!, $name: String!, $type: String!, $description: String ) { createIncident( type: $type, severity: $severity, name: $name, description: $description ) { id name severity { name } types { type { name } } description identifier } }""") get_incident_severities = gql("""{ incidentSeverities { name ordering } }""") get_incident_types = gql("""{ types { name } }""") get_actions_for_incident = gql(""" query GetActionsForIncident($incidentId: Int!) { actions(where: { incidentId: { equals: $incidentId } }) { id name description phase { name id } user { fullName email } } }""") get_incident_by_name = gql(""" query GetIncidentByName($name: String, $identifier: String) { incidents(first: 1, where: { name: { contains: $name, mode: insensitive } identifier: { contains: $identifier, mode: insensitive } }) { id name severity { name } types { type { name } } description identifier } }""") class BreachRxClient: def __init__(self, base_url: str, api_key: str, secret_key: str, org_name: str, verify: bool): self.api_key = api_key self.secret_key = secret_key self.org_name = org_name auth = HTTPBasicAuth(api_key, secret_key) transport = RequestsHTTPTransport(url=base_url, auth=auth, headers={"orgname": org_name}, timeout=60, verify=verify) self.client = Client(transport=transport, fetch_schema_from_transport=False) def get_incident_severities(self): return self.client.execute(get_incident_severities)["incidentSeverities"] def get_incident_types(self): return self.client.execute(get_incident_types)["types"] def create_incident(self, name: Optional[str], description: Optional[str]): severities = self.get_incident_severities() types = self.get_incident_types() request = create_incident_mutation request.variable_values = { "severity": severities[0]["name"], "name": name, "type": types[0]["name"], "description": description, } return self.client.execute(request)["createIncident"] def get_incident(self, name: Optional[str], identifier: Optional[str]): request = get_incident_by_name request.variable_values = {"name": name, "identifier": identifier} results = self.client.execute(request)["incidents"] if results: return results.pop() else: return None def get_actions_for_incident(self, incident_id): request = get_actions_for_incident request.variable_values = {"incidentId": incident_id} return self.client.execute(request)["actions"] def test_module(client: BreachRxClient): try: client.get_incident_severities() return "ok" except Exception: raise Exception("Authorization Error: make sure your API Key and Secret Key are correctly set") def create_incident_command( client: BreachRxClient, incident_name: str | None = None, description: str | None = None ) -> CommandResults: if not incident_name: incident_name = demisto.incident().get("name") if not description: description = f"""An Incident copied from the Palo Alto Networks XSOAR platform. <br> <br> XSOAR Incident Name: {demisto.incident().get('name')}""" response = client.create_incident(incident_name, description) incident_name = response["name"] return CommandResults( outputs_prefix="BreachRx.Incident", outputs_key_field="id", outputs=response, raw_response=response, readable_output=f"Incident created with name={incident_name}.", ) def get_incident_actions_command( client: BreachRxClient, incident_name: str | None = None, incident_identifier: str | None = None ) -> Union[CommandResults, str]: incidents = demisto.dt(demisto.context(), "BreachRx.Incident") if not incidents: if not incident_name and not incident_identifier: raise Exception( "Error: No BreachRx privacy Incident associated with this Incident, and no Incident search terms provided." ) incidents = [client.get_incident(incident_name, incident_identifier)] if not incidents: raise Exception("Error: No BreachRx privacy Incident found using the search terms provided.") if not isinstance(incidents, list): incidents = [incidents] for incident in incidents: incident["actions"] = client.get_actions_for_incident(incident["id"]) for action in incident["actions"]: action["phase_name"] = action["phase"]["name"] readable_output = "" for incident in incidents: actions_markdown_table = tableToMarkdown("Actions", incident["actions"], headers=["name", "phase_name"]) readable_output += f"# {incident['name']} ({incident['id']})\n" + actions_markdown_table + "\n" return CommandResults( outputs_prefix="BreachRx.Incident", outputs_key_field="id", outputs=incidents, raw_response=incidents, readable_output=readable_output, ) def import_incident_command( client: BreachRxClient, incident_name: str | None = None, incident_identifier: str | None = None ) -> Union[CommandResults, str]: incident = client.get_incident(incident_name, incident_identifier) if not incident: raise Exception("Error: No BreachRx privacy Incident found using the search terms provided.") return CommandResults( outputs_prefix="BreachRx.Incident", outputs_key_field="id", outputs=incident, raw_response=incident, readable_output=f"Incident imported with name={incident.get('name')}.", ) def get_incident_command( client: BreachRxClient, incident_name: str | None = None, incident_identifier: str | None = None ) -> Union[CommandResults, str]: incident = client.get_incident(incident_name, incident_identifier) if incident: return CommandResults( raw_response=incident, readable_output=f'Incident found with name="{incident.get("name")}" and identifier="{incident.get("identifier")}".', ) else: return "No Incident found with those search terms." COMMANDS = { "test-module": test_module, "breachrx-incident-create": create_incident_command, "breachrx-incident-actions-get": get_incident_actions_command, "breachrx-incident-import": import_incident_command, "breachrx-incident-get": get_incident_command, } def is_valid_url(url: str): try: result = urlparse(url) return all([result.scheme, result.netloc]) except ValueError: return False def main() -> None: # pragma: no cover try: params = demisto.params() args = demisto.args() command = demisto.command() base_url = params["api_url"] org_name = params["url"].split(".")[0].replace("https://", "") api_key = params.get("credentials", {}).get("identifier") secret_key = params.get("credentials", {}).get("password") verify = params.get("insecure", False) if not is_valid_url(base_url): raise Exception("The GraphQL API URL is not a valid URL.") if not is_valid_url(params["url"]): raise Exception("The BreachRx instance URL is not a valid URL.") client = BreachRxClient(base_url, api_key, secret_key, org_name, verify) command_func: Any[Callable, None] = COMMANDS.get(command) if command_func: return_results(command_func(client, **args)) else: raise NotImplementedError(f"{command} command is not implemented.") except Exception as e: demisto.error(traceback.format_exc()) return_error(f"Failed to execute {command} command.\nError:\n{e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()