diff --git a/Packs/SekoiaXDR/.pack-ignore b/Packs/SekoiaXDR/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/SekoiaXDR/.secrets-ignore b/Packs/SekoiaXDR/.secrets-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/SekoiaXDR/Author_image.png b/Packs/SekoiaXDR/Author_image.png new file mode 100644 index 000000000000..d5417ca562f7 Binary files /dev/null and b/Packs/SekoiaXDR/Author_image.png differ diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Contact.txt b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Contact.txt new file mode 100644 index 000000000000..2d954d1acfec --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Contact.txt @@ -0,0 +1,16 @@ +## Contact Information + +Support and maintenance for this integration are provided by the author. Please use the following contact details: +- Email: contact@sekoia.io +- URL: [https://www.sekoia.io/en/contact/](https://www.sekoia.io/en/contact/) + +## Additional documentation + +The following documentation can be useful to understand the integration: + +| Information | Description | +| --- | --- | +| [Mirroring](https://xsoar.pan.dev/docs/integrations/mirroring_integration) | Adittional information for mirroring | +| [Post process scripts](https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.5/Cortex-XSOAR-Administrator-Guide/Post-Processing-for-Incidents) | Adittional information for post process scripts | +| [Sekoia XDR documentation](https://docs.sekoia.io/xdr/) | Sekoia XDR Documentation | +| [Rest API Documentation](https://docs.sekoia.io/xdr/develop/rest_api/alert/) | Sekoia XDR API Documentation | diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Process.txt b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Process.txt new file mode 100644 index 000000000000..c114d1beaf30 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Process.txt @@ -0,0 +1,55 @@ +# Sekoia XDR - Process + +## Configure Sekoia XDR + +1. Navigate to **Settings > Integrations > Servers & Services**. +2. Search for **Sekoia XDR**. +3. Select the **parameters** of the instance where you can configure: + - Fetch alerts from Sekoia XDR (filtering by status or type). + - Include events, assets and kill-chain data on the fetching. + - Exclude certain fields from the events search. + - Replace "dots" symbols from the event field names. + - Type of mirroring (None, Incoming, Outgoing or Both). + - Allow automatic close of incidents in XSOAR (Mirror). + - Allow automatic reopen of incidents in XSOAR (Mirror). +4. Click Test to validate the URLs, token, and connection. + +### Parameters: + +| Parameter | Description | +| --- | --- | +| Mapper (incoming) and (outgoing) | Important to copy the OOTB mappers for the mirroring to work | +| Server URL | Sekoia API URL (without backslash at the end): https://api.sekoia.io | +| API Key | The API Key generated on Sekoia XDR | +| First fetch time | Filter the first fetching time range, format required i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17" | +| Fetch alerts with selected status | You can filter what to fetch by alert type or alert status. | +| Types of alerts to fetch | You can filter the type of alerts to fetch. | +| Filert alerts by urgencies | Filter by urgencies range in the following format: MIN_urgency,MAX_urgency. i.e: 80,100. | +| Max. incidents to fetch | Maximum incidents to fetch per interval (By default set to 10). | +| Fetch mode | Select with a dropdown if you want to fetch the alerts with or without the events. | +| Include asset information | Select with a checkbox if you want to include asset information on fetching. | +| Include kill-chain information | Select with checkboxs if you want to include kill-chain information on fetching. | +| Replace dots in events | Replace the "dots" from the events by other symbols like _ or - that will be easier to reference as JSON with XSOAR. | +| Exclude events | You can insert events to be excluded from the search of events, if they are not in the dropdown write and press enter. | +| Incident mirroring direction | Select the mirroring: None, Incoming, Outgoing or both directions. +| Reopen mirrored incidents | Mark this checkbox to enable automatic reopening of XSOAR incidents when the alerts are reopened in Sekoia | +| Close mirrored incidents | Mark this checkbox to enable automatic closing of XSOAR incidents when the alert is closed or rejected in Sekoia | +| Close notes | Notes to add when the XSOAR incident it automatically closed by mirroring. | +| Include events in mirroring | Mark this checkbox to include events in the mirroring of the alerts. | +| Include kill chain information in mirroring | Mark this checkbox to include kill chain information in the mirroring of the alerts. | +| Timezone | Input your timezone, use the following formats from https://en.wikipedia.org/wiki/List_of_tz_database_time_zones (i.e. 'UTC', 'Europe/Madrid', 'US/Eastern', 'Etc/Greenwich', 'Canada/Eastern'). | + + +### Mirroring: + +This integration have the functionality of mirroring **Incoming**, **Outgoing** and **Incoming and Outgoing**. +Mirroring provides an automatic sync between Sekoia XDR and Cortex XSOAR. + +The important parts to configure for mirroring are: +- **Mirroring direction:** decide the direction to be used for the mirroring (In,Out or Both). +- **Mappers:** this content pack comes with OOTB mappers that can be used to copy all the mapping fields required. +- **Layout:** this content comes with a OOTB Layout, please duplicate it as it contain buttons, display scripts, etc. +- **Post processing script:** used to automatically close or reject the Sekoia Alert when the XSOAR incident is closed. +>To apply the OOTB post process script duplicate it and apply under the incident type to use: +> Settings>Objects Setup>Types + diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Tools.txt b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Tools.txt new file mode 100644 index 000000000000..a0acddd0be4d --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/Lists/Sekoia_XDR_Tools.txt @@ -0,0 +1,14 @@ +## Troubleshooting + +To troubleshoot possible issues with the integration: +- **Debug mode:** In the integration instance select the option Debug and download the logs under Settings>About>Troubleshooting>Download logs. +- **Mirror values:** To troubleshoot mirroring issues apart from debug mode is possible to check under context that the dbot fields are set. +- This fields under context are: dbotMirrorInstance, dbotMirrorDirection and dbotMirrorId. If they are not set please review the mappers. +- The field dbotMirrorLastSync under context will be updated when the mirroring updates something on the incident, this can be also observed under War Room. + +## Best practices + +- When mirroring is enable please allow at least 1 minute to see the changes reflected, the mirroring process is executed every 1 minute. +- When reopening option is marked the XSOAR incident will be reopened under 2 conditions: + - The alert is reopened from Sekoia which will reopen the incident in XSOAR. + - The XSOAR incident is reopened: when this is done from XSOAR after reopen the incident please quickly change the status of the Sekoia alert or the mirroring will close it automatically due to the mirroring. diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md b/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md new file mode 100644 index 000000000000..4adb2e9d4032 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md @@ -0,0 +1,861 @@ +Fetch alerts and events from SEKOIA.IO XDR. +To use this integration, please create an API Key with the appropiate permissions. +This integration was integrated and tested with version 1.0 of Sekoia XDR. + +## Configure Sekoia XDR on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for Sekoia XDR. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | Fetch incidents | | False | + | Incident type | | False | + | Server URL (i.e. ) | | True | + | API Key | | True | + | First fetch time - Filter their creation dates, starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17" | | True | + | Trust any certificate (not secure) | | False | + | Use system proxy settings | | False | + | Fetch alerts with the selected status. | | False | + | List of types of alerts to fetch. (Write and press enter to insert types that are not in the list) | | False | + | Filter alerts by their urgencies range in the following format: "MIN_urgency,MAX_urgency". i.e: 80,100. | | False | + | Maximum incidents to fetch per interval (By default set to 10). | | True | + | Fetch mode | | True | + | Include assets information in the alerts when fetching. | When seleted, it includes the assets information in the when an alert is fetched in Sekoia. | False | + | Include kill chain information in the alerts when fetching. | When seleted, it includes the kill chain information in the when an alert is fetched in Sekoia. | False | + | Replace the "dots" from the event field names for a different character easier to reference in XSOAR. | | True | + | Indicate if there is any information you want to exclude from the results of the events search. i.e: original.message, message, agent.name, etc. | This is the names of the headers presented in the events table. If the header is not in the dropdown list write it and press enter. | False | + | Incident Mirroring Direction | Choose the direction to mirror the incident: None\(Disable mirroring\), Incoming \(from Sekoia XDR to Cortex XSOAR\) , Outgoing \(from Cortex XSOAR to Sekoia XDR\), or Incoming and Outgoing \(from/to Cortex XSOAR and Sekoia XDR\). | True | + | Reopen Mirrored Cortex XSOAR Incidents (Incoming Mirroring) | When selected, reopening the Sekoia XDR alert will reopen the Cortex XSOAR incident. | False | + | Close Mirrored Cortex XSOAR Incidents (Incoming Mirroring) | When selected, closing the Sekoia XDR alert with a "Closed" or "Reject" status will close the Cortex XSOAR incident. | False | + | Notes to add when the incident it automatically closed by mirroring: | Change the closing notes that will be added to the tickets closed automatically by the automation. | True | + | Include events in the mirroring of the alerts. | When seleted, it includes the events in the mirroring when an alert is updated in Sekoia. | False | + | Include kill chain information in the mirroring of the alerts. | When seleted, it includes the kill chain information of the alert in the mirroring when an alert is updated in Sekoia. | False | + | Input your timezone, use the following formats from (i.e. 'UTC', 'Europe/Madrid', 'US/Eastern', 'Etc/Greenwich', 'Canada/Eastern') | This will be used to present dates in the appropiate timezones, used for comment timestamps, etc. | True | + | Incidents Fetch Interval | | False | + +4. Click **Test** to validate the URLs, token, and connection. + +## Commands + +You can execute these commands from the Cortex XSOAR 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. + +### sekoia-list-alerts + +*** +Command to retrieve a list of Alerts from Sekoia XDR. + +#### Base Command + +`sekoia-list-alerts` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| limit | Limit a number of items (allowed range is 1-100), default is 20. Default is 20. | Optional | +| status | Match alerts by their status name (separated by commas). Possible values are: Pending, Acknowledged, Ongoing, Rejected, Closed. | Optional | +| created_at | Filter alerts by their creation dates, starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17". | Optional | +| updated_at | Filter alerts by their update dates starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17". | Optional | +| urgency | Filter alerts by their urgencies range in the following format: "MIN_urgency,MAX_urgency". i.e: 80,100. | Optional | +| alerts_type | Match alerts by their type categories (separated by commas). Possible values are: spam, ddos, outage, phishing, unauthorized-use-of-resources, unauthorised-information-access, appscan, scanner, brute-force, exploit. | Optional | +| sort_by | Sort the alerts by any information. Possible values are: created_at, updated_at, target, urgency, status. Default is created_at. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.ListAlerts.updated_at | unknown | The time at which the alert was updated. | +| SekoiaXDR.ListAlerts.updated_by | unknown | The user who last updated the alert. | +| SekoiaXDR.ListAlerts.uuid | unknown | The unique identifier of the alert. | +| SekoiaXDR.ListAlerts.title | unknown | The title of the alert. | +| SekoiaXDR.ListAlerts.time_to_respond | unknown | The time it took to respond to the alert. | +| SekoiaXDR.ListAlerts.short_id | unknown | The short identifier of the alert. | +| SekoiaXDR.ListAlerts.community_uuid | unknown | The unique identifier of the community associated with the alert. | +| SekoiaXDR.ListAlerts.kill_chain_short_id | unknown | The short identifier of the kill chain associated with the alert. | +| SekoiaXDR.ListAlerts.number_of_unseen_comments | unknown | The number of unseen comments on the alert. | +| SekoiaXDR.ListAlerts.updated_by_type | unknown | The type of user who last updated the alert. | +| SekoiaXDR.ListAlerts.source | unknown | The source of the alert. | +| SekoiaXDR.ListAlerts.alert_type.value | unknown | The type of the alert. | +| SekoiaXDR.ListAlerts.alert_type.category | unknown | The category type of the alert. | +| SekoiaXDR.ListAlerts.time_to_acknowledge | unknown | The time it took to acknowledge the alert. | +| SekoiaXDR.ListAlerts.stix | unknown | The STIX data associated with the alert. | +| SekoiaXDR.ListAlerts.first_seen_at | unknown | The time the alert was first seen. | +| SekoiaXDR.ListAlerts.ttps.type | unknown | The type of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.name | unknown | The name of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.id | unknown | The unique identifier of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.description | unknown | The description of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.type | unknown | The type of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.name | unknown | The name of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.id | unknown | The unique identifier of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.description | unknown | The description of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.time_to_ingest | unknown | The time it took to ingest the alert. | +| SekoiaXDR.ListAlerts.target | unknown | The target of the alert. | +| SekoiaXDR.ListAlerts.time_to_resolve | unknown | The time it took to resolve the alert. | +| SekoiaXDR.ListAlerts.created_at | unknown | The time at which the alert was created. | +| SekoiaXDR.ListAlerts.last_seen_at | unknown | The time at which the alert was last seen. | +| SekoiaXDR.ListAlerts.assets | unknown | The assets associated with the alert. | +| SekoiaXDR.ListAlerts.rule.severity | unknown | The severity level of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.type | unknown | The type of rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.uuid | unknown | The unique identifier of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.name | unknown | The name of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.description | unknown | The description of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.pattern | unknown | The pattern of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.similar | unknown | The number of similar alerts to this one. | +| SekoiaXDR.ListAlerts.status.name | unknown | The name of the status of the alert. | +| SekoiaXDR.ListAlerts.status.description | unknown | The description of the status of the alert. | +| SekoiaXDR.ListAlerts.status.uuid | unknown | The unique identifier of the status of the alert. | +| SekoiaXDR.ListAlerts.urgency.criticity | unknown | The level of criticity of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.current_value | unknown | The current value of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.severity | unknown | The severity level of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.display | unknown | The display of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.value | unknown | The value of the urgency of the alert. | +| SekoiaXDR.ListAlerts.created_by | unknown | The user who created the alert. | +| SekoiaXDR.ListAlerts.number_of_total_comments | unknown | The total number of comments on the alert. | +| SekoiaXDR.ListAlerts.time_to_detect | unknown | The time it took to detect the alert. | +| SekoiaXDR.ListAlerts.entity.name | unknown | The name of the entity associated with the alert. | +| SekoiaXDR.ListAlerts.entity.uuid | unknown | The unique identifier of the entity associated with the alert. | +| SekoiaXDR.ListAlerts.created_by_type | unknown | The type of user who created the alert. | +| SekoiaXDR.ListAlerts.details | unknown | The details of the alert. | + +### sekoia-get-alert + +*** +Command to retrieve a specific Alert by uuid or short_id from Sekoia XDR. + +#### Base Command + +`sekoia-get-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Alert.short_id | string | Short ID of the alert. | +| SekoiaXDR.Alert.title | string | Title of the alert. | +| SekoiaXDR.Alert.urgency | string | urgency of the alert. | + +### sekoia-events-execute-query + +*** +Command to create an event search job on Sekoia XDR, after this execute "sekoia-status-events-query" to see the status of the query job and "sekoia-results-events-query" to retrieve the results.. + +#### Base Command + +`sekoia-events-execute-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| earliest_time | Valid expressions: -3d: from three days ago, -2w: from two weeks before now, -7d: seven days before now. | Required | +| lastest_time | Valid expressions: +3d: three days in the future, +2w: two weeks in the future, now: current time. | Required | +| query | The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga". | Required | +| max_last_events | Maximum number of listed events. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Query.uuid | unknown | The unique identifier for the event. | +| SekoiaXDR.Events.Query.term | unknown | The search term associated with the event. | +| SekoiaXDR.Events.Query.started_at | unknown | The time at which the event started. | +| SekoiaXDR.Events.Query.short_histogram.cases | unknown | The number of cases associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.total | unknown | The total number of events associated with the search term. | +| SekoiaXDR.Events.Query.short_histogram.alerts | unknown | The number of alerts associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.length | unknown | The length of the histogram for the event. | +| SekoiaXDR.Events.Query.created_by | unknown | The user who created the event. | +| SekoiaXDR.Events.Query.expired | unknown | A boolean indicating whether the event has expired. | +| SekoiaXDR.Events.Query.latest_time | unknown | The latest time associated with the event. | +| SekoiaXDR.Events.Query.expiration_date | unknown | The date on which the event will expire. | +| SekoiaXDR.Events.Query.created_at | unknown | The time at which the event was created. | +| SekoiaXDR.Events.Query.status | unknown | The status of the event. | +| SekoiaXDR.Events.Query.view_uuid | unknown | The unique identifier for the view associated with the event. | +| SekoiaXDR.Events.Query.canceled_at | unknown | The time at which the event was canceled. | +| SekoiaXDR.Events.Query.only_eternal | unknown | A boolean indicating whether the event is only eternal. | +| SekoiaXDR.Events.Query.results_ttl | unknown | The time-to-live for the event results. | +| SekoiaXDR.Events.Query.canceled_by | unknown | The user who canceled the event. | +| SekoiaXDR.Events.Query.term_lang | unknown | The language of the search term associated with the event. | +| SekoiaXDR.Events.Query.ended_at | unknown | The time at which the event ended. | +| SekoiaXDR.Events.Query.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Query.max_last_events | unknown | The maximum number of events to include in the results. | +| SekoiaXDR.Events.Query.canceled_by_type | unknown | The type of the user who canceled the event. | +| SekoiaXDR.Events.Query.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Query.created_by_type | unknown | The type of the user who created the event. | +| SekoiaXDR.Events.Query.community_uuids | unknown | The list of community UUIDs associated with the event. | +| SekoiaXDR.Events.Query.filters.field | unknown | The field associated with the filter. | +| SekoiaXDR.Events.Query.filters.value | unknown | The value associated with the filter. | +| SekoiaXDR.Events.Query.filters.operator | unknown | The operator used in the filter. | +| SekoiaXDR.Events.Query.filters.excluded | unknown | Indicates whether the filter is excluded or not. | +| SekoiaXDR.Events.Query.filters.disabled | unknown | Indicates whether the filter is disabled or not. | + +### sekoia-events-status-query + +*** +Command to query the status of the search job "sekoia-execute-events-query" previously executed on Sekoia XDR. + +#### Base Command + +`sekoia-events-status-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| uuid | UUID of the query excuted previously with the "sekoia-query-events" command. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Status.uuid | unknown | The unique identifier for the event. | +| SekoiaXDR.Events.Status.term | unknown | The term associated with the event. | +| SekoiaXDR.Events.Status.started_at | unknown | The time at which the event started. | +| SekoiaXDR.Events.Status.short_histogram.cases | unknown | The number of cases associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.alerts | unknown | The number of alerts associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.length | unknown | The length associated with the event. | +| SekoiaXDR.Events.Status.created_by | unknown | The user who created the event. | +| SekoiaXDR.Events.Status.expired | unknown | Whether the event is expired. | +| SekoiaXDR.Events.Status.latest_time | unknown | The latest time associated with the event. | +| SekoiaXDR.Events.Status.expiration_date | unknown | The date when the event expires. | +| SekoiaXDR.Events.Status.created_at | unknown | The time when the event was created. | +| SekoiaXDR.Events.Status.status | unknown | The current status of the event. | +| SekoiaXDR.Events.Status.view_uuid | unknown | The view associated with the event. | +| SekoiaXDR.Events.Status.canceled_at | unknown | The time when the event was canceled. | +| SekoiaXDR.Events.Status.only_eternal | unknown | Whether only eternal events are associated with the event. | +| SekoiaXDR.Events.Status.results_ttl | unknown | The time-to-live for the event results. | +| SekoiaXDR.Events.Status.canceled_by | unknown | The user who canceled the event. | +| SekoiaXDR.Events.Status.term_lang | unknown | The language associated with the term for the event. | +| SekoiaXDR.Events.Status.ended_at | unknown | The time when the event ended. | +| SekoiaXDR.Events.Status.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Status.max_last_events | unknown | The maximum number of events to retrieve. | +| SekoiaXDR.Events.Status.canceled_by_type | unknown | The type of user who canceled the event. | +| SekoiaXDR.Events.Status.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Status.created_by_type | unknown | The type of user who created the event. | +| SekoiaXDR.Events.Status.community_uuids[0] | unknown | The community associated with the event. | +| SekoiaXDR.Events.Status.filters.field | unknown | The field used for filtering events. | +| SekoiaXDR.Events.Status.filters.field | unknown | The field used in the filter. | +| SekoiaXDR.Events.Status.filters.value | unknown | The value of the filter. | +| SekoiaXDR.Events.Status.filters.operator | unknown | The operator used in the filter. | +| SekoiaXDR.Events.Status.filters.excluded | unknown | A boolean indicating whether the filter is excluded or not. | +| SekoiaXDR.Events.Status.filters.disabled | unknown | A boolean indicating whether the filter is disabled or not. | + +### sekoia-events-results-query + +*** +Command to retrieve the events from the search job "sekoia-execute-events-query" previously done on Sekoia XDR. + +#### Base Command + +`sekoia-events-results-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| uuid | UUID of the query excuted previously with the "sekoia-query-events" command. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Results | unknown | The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. | + +### sekoia-search-events + +*** +Command to search and retrieve the events from an alert. This is a combination of 3 commands: jobquery-events, jobquery-events-status and jobquery-retrieve events. + +#### Base Command + +`sekoia-search-events` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| earliest_time | Valid expressions: -3d: from three days ago, -2w: from two weeks before now, -7d: seven days before now. | Required | +| lastest_time | Valid expressions: +3d: three days in the future, +2w: two weeks in the future, now: current time. | Required | +| query | The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga". | Required | +| max_last_events | Maximum number of listed events. | Optional | +| exclude_info | Indicate if there is any information you want to exclude from the results of the events. i.e: original.message, message, agent.name, etc. This are the names of the headers presented in the table. If is not in the list write it and press enter. Possible values are: original.message, message, __event_id, agent.name, alert_short_ids, client.address, client.ip, client.user.id, customer.community_name, customer.community_uuid, customer.id, customer.intake_key, customer.intake_name, customer.intake_uuid, ecs.version, entity.id, entity.name, entity.uuid, event.created, event.dialect, event.dialect_uuid, event.id, event.outcome, http.request.method, http.request.referrer, related.ip, sekoiaio.activity.client.id, sekoiaio.activity.client.type, sekoiaio.customer.community_name, sekoiaio.customer.community_uuid, sekoiaio.customer.id, sekoiaio.entity.id, sekoiaio.entity.name, sekoiaio.entity.uuid, sekoiaio.intake.dialect, sekoiaio.intake.dialect_uuid, sekoiaio.intake.key, sekoiaio.intake.name, sekoiaio.intake.parsing_status, sekoiaio.intake.uuid, timestamp, url.domain, url.original, url.path, url.port, url.query, url.registered_domain, url.scheme, url.subdomain, url.top_level_domain, user_agent.original. | Optional | +| interval_in_seconds | Interval in seconds between each poll. Default is 2. | Optional | +| timeout_in_seconds | Polling timeout in seconds. Default is 60. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Results | unknown | The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. | + +### sekoia-update-status-alert + +*** +Command to update the status of a specific Alert by uuid or short_id. + +#### Base Command + +`sekoia-update-status-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | +| status | The status you want to apply. (Acknowledged, Rejected, Ongoing, Closed)). Possible values are: Acknowledged, Rejected, Ongoing, Closed. | Optional | +| comment | A comment to describe why the alert status has changed. | Optional | + +#### Context Output + +There is no context output for this command. + +### sekoia-post-comment-alert + +*** +Command to post comments to alerts in Sekoia XDR. + +#### Base Command + +`sekoia-post-comment-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | +| comment | Content of the comment to be posted on the alert. | Required | +| author | Author of the comment. | Optional | + +#### Context Output + +There is no context output for this command. + +### sekoia-get-comments + +*** +Command to get all the comments from an alert in Sekoia XDR. + +#### Base Command + +`sekoia-get-comments` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Comments.total | unknown | The total number of items in the comments. | +| SekoiaXDR.Comments.items.date | unknown | The date at which the comment was created. | +| SekoiaXDR.Comments.items.created_by | unknown | The user who created the comment. | +| SekoiaXDR.Comments.items.uuid | unknown | The unique identifier for the comment. | +| SekoiaXDR.Comments.items.content | unknown | The content of the comment. | +| SekoiaXDR.Comments.items.created_by_type | unknown | The type of the user who created the comment. | +| SekoiaXDR.Comments.items.unseen | unknown | Indicates whether the comment has been seen by the user. | +| SekoiaXDR.Comments.items.author | unknown | The author of the comment. | + +### sekoia-get-workflow-alert + +*** +Command to get the possible transitions of status on the alert. + +#### Base Command + +`sekoia-get-workflow-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.StatusTransitions.actions.name | unknown | The name of the action. | +| SekoiaXDR.StatusTransitions.actions.description | unknown | The description of the action. | +| SekoiaXDR.StatusTransitions.actions.id | unknown | The ID of the action. | + +### sekoia-get-cases-alert + +*** +Command to retrieve the case related to an Alert from Sekoia XDR. + +#### Base Command + +`sekoia-get-cases-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| alert_id | The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Optional | +| case_id | The short_id of the case to retrieve. i.e: "CAQNurTJM8q2". | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Cases.updated_at | unknown | The time at which the case was updated. | +| SekoiaXDR.Cases.updated_by | unknown | The user who updated the case. | +| SekoiaXDR.Cases.uuid | unknown | The unique identifier of the case. | +| SekoiaXDR.Cases.title | unknown | The title of the case. | +| SekoiaXDR.Cases.priority | unknown | The priority level of the case. | +| SekoiaXDR.Cases.short_id | unknown | The short ID of the case. | +| SekoiaXDR.Cases.community_uuid | unknown | The unique identifier of the community to which the case belongs. | +| SekoiaXDR.Cases.updated_by_type | unknown | The type of user who updated the case. | +| SekoiaXDR.Cases.first_seen_at | unknown | The time at which the case was first seen. | +| SekoiaXDR.Cases.number_of_comments | unknown | The number of comments on the case. | +| SekoiaXDR.Cases.alerts.updated_at | unknown | The time at which the alert was updated. | +| SekoiaXDR.Cases.alerts.updated_by | unknown | The user who updated the alert. | +| SekoiaXDR.Cases.alerts.uuid | unknown | The unique identifier of the alert. | +| SekoiaXDR.Cases.alerts.title | unknown | The title of the alert. | +| SekoiaXDR.Cases.alerts.time_to_respond | unknown | The time it took to respond to the alert. | +| SekoiaXDR.Cases.alerts.short_id | unknown | The short ID of the alert. | +| SekoiaXDR.Cases.alerts.community_uuid | unknown | The unique identifier of the community to which the alert belongs. | +| SekoiaXDR.Cases.alerts.kill_chain_short_id | unknown | The short ID of the kill chain. | +| SekoiaXDR.Cases.alerts.number_of_unseen_comments | unknown | The number of unseen comments on the alert. | +| SekoiaXDR.Cases.alerts.updated_by_type | unknown | The type of user who updated the alert. | +| SekoiaXDR.Cases.alerts.source | unknown | The source of the alert. | +| SekoiaXDR.Cases.alerts.alert_type.value | unknown | The type of the alert. | +| SekoiaXDR.Cases.alerts.alert_type.category | unknown | The category type of the alert. | +| SekoiaXDR.Cases.alerts.time_to_acknowledge | unknown | The time it took to acknowledge the alert. | +| SekoiaXDR.Cases.alerts.stix | unknown | The STIX data of the alert. | +| SekoiaXDR.Cases.alerts.first_seen_at | unknown | The time at which the alert was first seen. | +| SekoiaXDR.Cases.alerts.ttps.type | unknown | The type of TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.name | unknown | The name of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.id | unknown | The ID of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.description | unknown | The description of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.type | unknown | The type of adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.name | unknown | The name of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.id | unknown | The ID of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.description | unknown | The description of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.time_to_ingest | unknown | The time it took to ingest the alert. | +| SekoiaXDR.Cases.alerts.target | unknown | The target of the alert. | +| SekoiaXDR.Cases.alerts.time_to_resolve | unknown | The time it took to resolve the alert. | +| SekoiaXDR.Cases.alerts.created_at | unknown | The time at which the alert was created. | +| SekoiaXDR.Cases.alerts.last_seen_at | unknown | The time at which the alert was last seen. | +| SekoiaXDR.Cases.alerts.assets | unknown | The assets associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.severity | unknown | The severity level of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.type | unknown | The type of rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.uuid | unknown | The unique identifier of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.name | unknown | The name of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.description | unknown | The description of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.pattern | unknown | The pattern of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.similar | unknown | The number of similar alerts. | +| SekoiaXDR.Cases.alerts.status.name | unknown | The name of the status of the alert. | +| SekoiaXDR.Cases.alerts.status.description | unknown | The description of the status of the alert. | +| SekoiaXDR.Cases.alerts.status.uuid | unknown | The unique identifier of the status of the alert. | +| SekoiaXDR.Cases.alerts.urgency.criticity | unknown | The level of criticality of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.current_value | unknown | The current value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.severity | unknown | The severity level of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.display | unknown | The display value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.value | unknown | The value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.created_by | unknown | The user who created the alert. | +| SekoiaXDR.Cases.alerts.number_of_total_comments | unknown | The total number of comments on the alert. | +| SekoiaXDR.Cases.alerts.time_to_detect | unknown | The time it took to detect the alert. | +| SekoiaXDR.Cases.alerts.entity.name | unknown | The name of the entity associated with the alert. | +| SekoiaXDR.Cases.alerts.entity.uuid | unknown | The unique identifier of the entity associated with the alert. | +| SekoiaXDR.Cases.alerts.created_by_type | unknown | The type of user who created the alert. | +| SekoiaXDR.Cases.alerts.details | unknown | The details of the alert. | +| SekoiaXDR.Cases.number_of_alerts | unknown | The number of alerts in the case. | +| SekoiaXDR.Cases.created_at | unknown | The time at which the case was created. | +| SekoiaXDR.Cases.last_seen_at | unknown | The time at which the case was last seen. | +| SekoiaXDR.Cases.status | unknown | The status of the case. | +| SekoiaXDR.Cases.description | unknown | The description of the case. | +| SekoiaXDR.Cases.status_uuid | unknown | The unique identifier of the status of the case. | +| SekoiaXDR.Cases.created_by | unknown | The user who created the case. | +| SekoiaXDR.Cases.tags | unknown | The tags associated with the case. | +| SekoiaXDR.Cases.created_by_type | unknown | The type of user who created the case. | +| SekoiaXDR.Cases.subscribers.avatar_uuid | unknown | The unique identifier of the avatar of the subscriber. | +| SekoiaXDR.Cases.subscribers.type | unknown | The type of subscriber. | + +### sekoia-get-asset + +*** +Get an asset by its UUID from Sekoia XDR. + +#### Base Command + +`sekoia-get-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Asset.owners | unknown | The owners of the asset. | +| SekoiaXDR.Asset.category.types.description | unknown | The description of the category type of the asset. | +| SekoiaXDR.Asset.category.types.name | unknown | The name of the category type of the asset. | +| SekoiaXDR.Asset.category.types.uuid | unknown | The UUID of the category type of the asset. | +| SekoiaXDR.Asset.category.description | unknown | The description of the category of the asset. | +| SekoiaXDR.Asset.category.name | unknown | The name of the category of the asset. | +| SekoiaXDR.Asset.category.uuid | unknown | The UUID of the category of the asset. | +| SekoiaXDR.Asset.created_at | unknown | The time at which the asset was created. | +| SekoiaXDR.Asset.keys.value | unknown | The value of the keys of the asset. | +| SekoiaXDR.Asset.keys.name | unknown | The name of the keys of the asset. | +| SekoiaXDR.Asset.keys.uuid | unknown | The UUID of the keys of the asset. | +| SekoiaXDR.Asset.attributes.value | unknown | The value of the attributes of the asset. | +| SekoiaXDR.Asset.attributes.name | unknown | The name of the attributes of the asset. | +| SekoiaXDR.Asset.attributes.uuid | unknown | The UUID of the attributes of the asset. | +| SekoiaXDR.Asset.updated_at | unknown | The time at which the asset was updated. | +| SekoiaXDR.Asset.asset_type.description | unknown | The description of the asset type. | +| SekoiaXDR.Asset.asset_type.name | unknown | The name of the asset type. | +| SekoiaXDR.Asset.asset_type.uuid | unknown | The UUID of the asset type. | +| SekoiaXDR.Asset.criticity.value | unknown | The criticality value of the asset. | +| SekoiaXDR.Asset.criticity.display | unknown | The display value of the criticality of the asset. | +| SekoiaXDR.Asset.description | unknown | The description of the asset. | +| SekoiaXDR.Asset.community_uuid | unknown | The UUID of the community of the asset. | +| SekoiaXDR.Asset.name | unknown | The name of the asset. | +| SekoiaXDR.Asset.uuid | unknown | The UUID of the asset. | + +### get-remote-data + +*** +This command gets new information about the incidents in the remote system and updates existing incidents in Cortex XSOAR. + +#### Base Command + +`get-remote-data` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The remote alert ID. | Optional | +| lastUpdate | ISO format date with timezone, e.g., 2023-03-01T16:41:30.589575+02:00. The incident is only updated if it was modified after the last update time. Default is 0. | Optional | + +#### Context Output + +There is no context output for this command. + +### get-modified-remote-data + +*** +available from Cortex XSOAR version 6.1.0. This command queries for incidents that were modified since the last update. + +#### Base Command + +`get-modified-remote-data` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| lastUpdate | ISO format date with timezone, e.g., 2023-03-01T16:41:30.589575+02:00. The incident is only returned if it was modified after the last update time. Default is 0. | Optional | + +#### Context Output + +There is no context output for this command. + +### sekoia-list-assets + +*** +Command to retrieve a list of Assets from Sekoia XDR. + +#### Base Command + +`sekoia-list-assets` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| limit | Limit a number of items. Default is 10. | Optional | +| assets_type | Type of assets to list (computer, network, etc). | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Assets.total | unknown | The total number of items in the response. | +| SekoiaXDR.Assets.items.0.owners.0 | unknown | The ID of the owner of the asset. | +| SekoiaXDR.Assets.items.0.category.types.0.description | unknown | The description of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.types.0.name | unknown | The name of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.types.0.uuid | unknown | The UUID of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.description | unknown | The description of the asset category. | +| SekoiaXDR.Assets.items.0.category.name | unknown | The name of the asset category. | +| SekoiaXDR.Assets.items.0.category.uuid | unknown | The UUID of the asset category. | +| SekoiaXDR.Assets.items.0.created_at | unknown | The time at which the asset was created. | +| SekoiaXDR.Assets.items.0.keys.0.value | unknown | The value of the asset key. | +| SekoiaXDR.Assets.items.0.keys.0.name | unknown | The name of the asset key. | +| SekoiaXDR.Assets.items.0.keys.0.uuid | unknown | The UUID of the asset key. | +| SekoiaXDR.Assets.items.0.attributes.0.value | unknown | The value of the asset attribute. | +| SekoiaXDR.Assets.items.0.attributes.0.name | unknown | The name of the asset attribute. | +| SekoiaXDR.Assets.items.0.attributes.0.uuid | unknown | The UUID of the asset attribute. | +| SekoiaXDR.Assets.items.0.updated_at | unknown | The time at which the asset was last updated. | +| SekoiaXDR.Assets.items.0.asset_type.description | unknown | The description of the asset type. | +| SekoiaXDR.Assets.items.0.asset_type.name | unknown | The name of the asset type. | +| SekoiaXDR.Assets.items.0.asset_type.uuid | unknown | The UUID of the asset type. | +| SekoiaXDR.Assets.items.0.criticity.value | unknown | The numeric value of the asset criticality. | +| SekoiaXDR.Assets.items.0.criticity.display | unknown | The display value of the asset criticality. | +| SekoiaXDR.Assets.items.0.description | unknown | The description of the asset. | +| SekoiaXDR.Assets.items.0.community_uuid | unknown | The UUID of the community to which the asset belongs. | +| SekoiaXDR.Assets.items.0.name | unknown | The name of the asset. | +| SekoiaXDR.Assets.items.0.uuid | unknown | The UUID of the asset. | + +### sekoia-get-user + +*** +Command to get information about a user in Sekoia XDR. Used also in the command !sekoia-get-comments to have the name of the persons who made the comments. + +#### Base Command + +`sekoia-get-user` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| user_uuid | UUID of the user to obtain the information from. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.User.creator.description | unknown | The description of the creator. | +| SekoiaXDR.User.creator.name | unknown | The name of the creator. | +| SekoiaXDR.User.creator.uuid | unknown | The UUID of the creator. | +| SekoiaXDR.User.updated_at | unknown | The time at which the object was last updated. | +| SekoiaXDR.User.created_by | unknown | The UUID of the user who created the object. | +| SekoiaXDR.User.total_members | unknown | The total number of members in the community. | +| SekoiaXDR.User.subcommunities | unknown | The UUIDs of the subcommunities. | +| SekoiaXDR.User.parent_community_uuid | unknown | The UUID of the parent community. | +| SekoiaXDR.User.applications.description | unknown | The description of the application. | +| SekoiaXDR.User.applications.name | unknown | The name of the application. | +| SekoiaXDR.User.applications.uuid | unknown | The UUID of the application. | +| SekoiaXDR.User.is_parent | unknown | Whether the community is a parent community. | +| SekoiaXDR.User.name | unknown | The name of the community. | +| SekoiaXDR.User.members.uuid | unknown | The UUID of the member. | +| SekoiaXDR.User.members.created_at | unknown | The time at which the member was created. | +| SekoiaXDR.User.members.user.firstname | unknown | The first name of the user associated with the member. | +| SekoiaXDR.User.members.user.mfa_enabled | unknown | Whether multi-factor authentication is enabled for the user associated with the member. | +| SekoiaXDR.User.members.user.uuid | unknown | The UUID of the user associated with the member. | +| SekoiaXDR.User.members.user.company_name | unknown | The company name of the user associated with the member. | +| SekoiaXDR.User.members.user.lastname | unknown | The last name of the user associated with the member. | +| SekoiaXDR.User.members.user.created_at | unknown | The time at which the user associated with the member was created. | +| SekoiaXDR.User.members.user.picture_mode | unknown | The picture mode of the user associated with the member. | +| SekoiaXDR.User.members.user.last_activity | unknown | The last activity time of the user associated with the member. | +| SekoiaXDR.User.members.user.updated_at | unknown | The time at which the user associated with the member was last updated. | +| SekoiaXDR.User.members.user.auth_provider | unknown | The authentication provider of the user associated with the member. | +| SekoiaXDR.User.members.user.email | unknown | The email address of the user associated with the member. | +| SekoiaXDR.User.members.user.invitation_v2.email | unknown | The email address for the invitation associated with the user associated with the member. | +| SekoiaXDR.User.members.name | unknown | The name of the member. | +| SekoiaXDR.User.members.updated_at | unknown | The time at which the member was last updated. | +| SekoiaXDR.User.members.status_changed_at | unknown | The time at which the status of the member was last changed. | +| SekoiaXDR.User.members.status | unknown | The status of the member. | +| SekoiaXDR.User.session_timeout | unknown | The session timeout for the community. | +| SekoiaXDR.User.is_mfa_enforced | unknown | Whether multi-factor authentication is enforced for the community. | +| SekoiaXDR.User.uuid | unknown | The UUID of the community. | +| SekoiaXDR.User.created_at | unknown | The time at which the community was created. | +| SekoiaXDR.User.picture_mode | unknown | The picture mode for the community. | +| SekoiaXDR.User.homepage_url | unknown | The homepage URL for the community. | +| SekoiaXDR.User.created_by_type | unknown | The type of the user who created the community. | +| SekoiaXDR.User.disable_inactive_avatars | unknown | Whether inactive avatars are disabled for the community. | +| SekoiaXDR.User.description | unknown | The description of the community. | + +### sekoia-add-attributes-asset + +*** +Command to add attributes to an asset in Sekoia XDR. + +#### Base Command + +`sekoia-add-attributes-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| name | The name of attributes. | Required | +| value | The value of attributes. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-add-keys-asset + +*** +Command to add keys to an asset in Sekoia XDR. + +#### Base Command + +`sekoia-add-keys-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| name | The name of the key to be added. | Required | +| value | The value of the key to be added. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-get-kill-chain + +*** +Command to retrieve the definition of a Cyber Kill Chain Step. + +#### Base Command + +`sekoia-get-kill-chain` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| kill_chain_uuid | UUID or short_id of the kill chain. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.KillChain.stix_name | unknown | The name of the STIX object. | +| SekoiaXDR.KillChain.description | unknown | The description of the STIX object. | +| SekoiaXDR.KillChain.name | unknown | The common name of the STIX object. | +| SekoiaXDR.KillChain.uuid | unknown | The unique identifier of the STIX object. | +| SekoiaXDR.KillChain.short_id | unknown | The short identifier of the STIX object. | +| SekoiaXDR.KillChain.order_id | unknown | The order identifier of the STIX object. | + +### update-remote-system + +*** +Pushes local changes to the remote system. + +#### Base Command + +`update-remote-system` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | + +#### Context Output + +There is no context output for this command. + +### get-mapping-fields + +*** +This command pulls the remote schema for the different incident types, and their associated incident fields, from the remote system. + +#### Base Command + +`get-mapping-fields` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | + +#### Context Output + +There is no context output for this command. + +### sekoia-remove-attribute-asset + +*** +Command to remove an attribute from an asset in Sekoia XDR. Note: use !sekoia-get-asset to find the attribute_uuid to delete. + +#### Base Command + +`sekoia-remove-attribute-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| attribute_uuid | UUID of the attribute to delete. Note: use !sekoia-get-asset to find the attribute_uuid to delete. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-remove-key-asset + +*** +Command to remove an attribute from an asset in Sekoia XDR. Note: use !sekoia-get-asset to find the key_uuid to delete. + +#### Base Command + +`sekoia-remove-key-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| key_uuid | UUID of the key to remove. Note: use !sekoia-get-asset to find the key_uuid to delete. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-http-request + +*** +Command that performs a HTTP request to Sekoia using the integration authentication configured. + +#### Base Command + +`sekoia-http-request` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| method | Method to use with the http request (GET,POST,etc). Default is GET. | Required | +| url_sufix | The URL sufix after , i.e. /sic/alerts/ or /asset-management/assets/. | Required | +| parameters | Query parameters, i.e. limit -> 10 , match['status_name'] -> Ongoing. | Optional | + +#### Context Output + +There is no context output for this command. + +## Incident Mirroring + +You can enable incident mirroring between Cortex XSOAR incidents and Sekoia XDR corresponding events (available from Cortex XSOAR version 6.0.0). +To set up the mirroring: + +1. Enable *Fetching incidents* in your instance configuration. +2. In the *Mirroring Direction* integration parameter, select in which direction the incidents should be mirrored: + + | **Option** | **Description** | + | --- | --- | + | None | Turns off incident mirroring. | + | Incoming | Any changes in Sekoia XDR events (mirroring incoming fields) will be reflected in Cortex XSOAR incidents. | + | Outgoing | Any changes in Cortex XSOAR incidents will be reflected in Sekoia XDR events (outgoing mirrored fields). | + | Incoming and Outgoing | | + +3. Optional: Check the *Close Mirrored XSOAR Incident* integration parameter to close the Cortex XSOAR incident when the corresponding event is closed in Sekoia XDR. + +Newly fetched incidents will be mirrored in the chosen direction. However, this selection does not affect existing incidents. +**Important Note:** To ensure the mirroring works as expected, mappers are required, both for incoming and outgoing, to map the expected fields in Cortex XSOAR and Sekoia XDR. diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py new file mode 100644 index 000000000000..ee479266e6cc --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py @@ -0,0 +1,1528 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 +from CommonServerUserPython import * # noqa: F401 + +import json +import urllib3 +import dateparser +import time +from typing import Any, Dict, Tuple, List, Optional, cast +from datetime import datetime +import re +import pytz + +# Disable insecure warnings +urllib3.disable_warnings() + + +""" CONSTANTS """ + +DATE_FORMAT = "%Y-%m-%dT%H:%M:%S" +MAX_INCIDENTS_TO_FETCH = 50 # Default value to be used if the parameter is not set on the integration config. +MAX_EVENTS = 250 # Default value to limit the amount of events retrieved. +INTERVAL_SECONDS_EVENTS = 1 +TIMEOUT_EVENTS = 30 +INCIDENT_TYPE_NAME = "Sekoia XDR" +SEKOIA_INCIDENT_FIELDS = { + "short_id": "The ID of the alert to edit", + "status": "The name of the status.", + "xsoar_id": "The XSOAR incident", +} + +STATUS_TRANSITIONS = { + "Ongoing": "Validate", + "Acknowledged": "Acknowledge", + "Rejected": "Reject", + "Closed": "Close", +} + +MIRROR_DIRECTION = { + "None": None, + "Incoming": "In", + "Outgoing": "Out", + "Incoming and Outgoing": "Both", +} + + +""" CLIENT CLASS """ + + +class Client(BaseClient): + """Client class to interact with the service API""" + + def get_validate_resource(self) -> str: + """ + Request Sekoia.io to validate the API Key + """ + try: + self._http_request( + method="GET", + url_suffix="/v1/auth/validate", + raise_on_status=True, + ) + return "ok" + except DemistoException as e: + raise DemistoException(f"Integration error: the request failed due to: {e}") + + def list_alerts( + self, + alerts_limit: Optional[int], + alerts_status: Optional[str], + alerts_createdAt: Optional[str], + alerts_updatedAt: Optional[str], + alerts_urgency: Optional[str], + alerts_type: Optional[str], + sort_by: Optional[str], + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if alerts_limit: + request_params["limit"] = alerts_limit + + """ Matching parameters""" + if alerts_status: + request_params["match[status_name]"] = alerts_status + if alerts_createdAt: + request_params["date[created_at]"] = alerts_createdAt + if alerts_updatedAt: + request_params["date[updated_at]"] = alerts_updatedAt + if alerts_urgency: + request_params["range[urgency]"] = alerts_urgency + if alerts_type: + request_params["match[type_value]"] = alerts_type + + """ Sorting parameters""" + if sort_by: + request_params["sort"] = sort_by + + return self._http_request( + method="GET", url_suffix="/v1/sic/alerts", params=request_params + ) + + def get_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", url_suffix="/v1/sic/alerts/" + alert_uuid + ) + + def update_status_alert( + self, alert_uuid: str, action_uuid: str, comment: Optional[str] + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if action_uuid: + request_params["action_uuid"] = action_uuid + if comment: + request_params["comment"] = comment + + return self._http_request( + method="PATCH", + url_suffix="/v1/sic/alerts/" + alert_uuid + "/workflow", + json_data=request_params, + ) + + def post_comment_alert( + self, alert_uuid: str, content: str, author: str + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if content: + request_params["content"] = content + if author: + request_params["author"] = author + + return self._http_request( + method="POST", + url_suffix="/v1/sic/alerts/" + alert_uuid + "/comments", + json_data=request_params, + ) + + def get_comments_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix="/v1/sic/alerts/" + alert_uuid + "/comments", + ) + + def get_workflow_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix="/v1/sic/alerts/" + alert_uuid + "/workflow", + ) + + def query_events( + self, + events_earliest_time: str, + events_latest_time: str, + events_term: str, + max_last_events: str, + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if events_earliest_time: + request_params["earliest_time"] = events_earliest_time + if events_latest_time: + request_params["latest_time"] = events_latest_time + if events_term: + request_params["term"] = events_term + if max_last_events: + request_params["max_last_events"] = max_last_events + + return self._http_request( + method="POST", + url_suffix="/v1/sic/conf/events/search/jobs", + json_data=request_params, + ) + + def query_events_status(self, event_search_job_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix="/v1/sic/conf/events/search/jobs/" + event_search_job_uuid, + ) + + def retrieve_events(self, event_search_job_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix="/v1/sic/conf/events/search/jobs/" + + event_search_job_uuid + + "/events", + ) + + def get_cases_alert(self, alert_uuid: str, case_id: str) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Matching parameters""" + if alert_uuid: + request_params["match[alert_uuid]"] = alert_uuid + if case_id: + request_params["match[short_id]"] = case_id + + return self._http_request( + method="GET", url_suffix="v1/sic/cases", params=request_params + ) + + def get_asset(self, asset_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix="/v1/asset-management/assets/" + asset_uuid, + ) + + def list_asset(self, limit: str, assets_type: str) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if limit: + request_params["limit"] = limit + + """ Matching parameters""" + if assets_type: + request_params["match[type_name]"] = assets_type + + return self._http_request( + method="GET", + url_suffix="/v1/asset-management/assets", + params=request_params, + ) + + def add_attributes_asset( + self, asset_uuid: str, name: str, value: str + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if name: + request_params["name"] = name + if value: + request_params["value"] = value + + return self._http_request( + method="POST", + url_suffix="/v1/asset-management/assets/" + asset_uuid + "/attr", + params=request_params, + ) + + def add_keys_asset(self, asset_uuid: str, name: str, value: str) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if name: + request_params["name"] = name + if value: + request_params["value"] = value + + return self._http_request( + method="POST", + url_suffix="/v1/asset-management/assets/" + asset_uuid + "/keys", + params=request_params, + ) + + def remove_attribute_asset( + self, asset_uuid: str, attribute_uuid: str + ) -> List[Dict[str, Any]]: + return self._http_request( + method="DELETE", + url_suffix="/v1/asset-management/assets/" + + asset_uuid + + "/attr/" + + attribute_uuid, + resp_type="text", + ) + + def remove_key_asset(self, asset_uuid: str, key_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="DELETE", + url_suffix="/v1/asset-management/assets/" + + asset_uuid + + "/keys/" + + key_uuid, + resp_type="text", + ) + + def get_user(self, user_uuid: str) -> Dict[str, Any]: + return self._http_request(method="GET", url_suffix="/v1/users/" + user_uuid) + + def get_kill_chain(self, kill_chain_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", url_suffix="/v1/sic/kill-chains/" + kill_chain_uuid + ) + + def http_request( + self, method: str, url_suffix: str, params: dict + ) -> Dict[str, Any]: + if not params: + params = {} + + return self._http_request(method=method, url_suffix=url_suffix, params=params) + + +""" HELPER FUNCTIONS """ + + +def arg_to_timestamp(arg: Any, arg_name: str, required: bool = False) -> int: + """ + Converts an XSOAR argument to a timestamp (seconds from epoch). + This function is used to quickly validate an argument provided to XSOAR + via ``demisto.args()`` into an ``int`` containing a timestamp (seconds + since epoch). It will throw a ValueError if the input is invalid. + If the input is None, it will throw a ValueError if required is ``True``, + or ``None`` if required is ``False``. + + Args: + arg: argument to convert + arg_name: argument name. + required: throws exception if ``True`` and argument provided is None + + Returns: + returns an ``int`` containing a timestamp (seconds from epoch) if conversion works + returns ``None`` if arg is ``None`` and required is set to ``False`` + otherwise throws an Exception + """ + if arg is None and required is True: + raise ValueError(f'Missing "{arg_name}"') + + if (isinstance(arg, str) and arg.isdigit()) or isinstance(arg, int | float): + # timestamp is a str containing digits - we just convert it to int + # or convert to int if the input is a float + return int(arg) + if isinstance(arg, str): + # we use dateparser to handle strings either in ISO8601 format, or + # relative time stamps. + # For example: format 2019-10-23T00:00:00 or "3 days", etc + date = dateparser.parse(arg, settings={"TIMEZONE": "UTC"}) + if date is None: + # if d is None it means dateparser failed to parse it + raise ValueError(f"Invalid date: {arg_name}") + + return int(date.timestamp()) + raise ValueError(f'Invalid date: "{arg_name}"') + + +def timezone_format(epoch: int) -> str: + """ + Converts an epoch timestamp into a formatted date in + a specific timezone defined in the integration parameter. + + Args: + epoch: argument to convert in epoch format + + Returns: + returns an ``str`` containing a formatted datestring in the timezone selected + """ + utc_datetime = datetime.utcfromtimestamp(epoch) + timezone = demisto.params().get("timezone", "UTC") + timezoneFormat = pytz.timezone(timezone) + format_datetime = utc_datetime.astimezone(timezoneFormat) + return format_datetime.strftime("%Y-%m-%dT%H:%M:%S") + + +def time_converter(time): + + # Regular expression patterns + iso_8601_pattern = re.compile( + r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$" + ) + unix_timestamp_pattern = re.compile(r"^\d+$") + + if iso_8601_pattern.match(time): + update_time = datetime.fromisoformat(time) + elif unix_timestamp_pattern.match(time): + update_time = datetime.fromtimestamp(int(time), pytz.utc) + else: + raise ValueError("Invalid time format") + + return update_time.strftime(DATE_FORMAT) + + +def convert_to_demisto_severity(severity: str) -> int: + """ + Maps Sekoia XDR urgency to Cortex XSOAR severity. + Converts the Sekoia XDR alert urgency level ('Low','Moderate','High','Major','Urgent') to Cortex XSOAR incident + severity (1 to 4). + + Args: + urgency (str): urgency display text as returned from the Sekoia XDR API. + + Returns: + int: Cortex XSOAR Severity (1 to 4) + """ + + return { + "Low": IncidentSeverity.LOW, + "Moderate": IncidentSeverity.MEDIUM, + "High": IncidentSeverity.HIGH, + "Major": IncidentSeverity.HIGH, + "Urgent": IncidentSeverity.CRITICAL, + }[severity] + + +def exclude_info_events(event_info: dict, exclude_info: str) -> list: + """ + Exclude information from the events. + This function will exclude information from the events that is duplicated or not needed. + + Args: + event_info (dict): JSON to be transformed removing some of the information. + exclude_info (str): the event fields to be removed from the results. + + Returns: + dict: JSON transformed with the information removed. + """ + splitted_exclude_info = exclude_info.split(",") + + """ Exclude headers from the readable output """ + headers = list(event_info["items"][0].keys()) + for header in splitted_exclude_info: + if header in headers: + headers.remove(header) + return headers + + +def undot(json_data: dict) -> str: + """ + Remove/Replace dots from the key names of a JSON. + This function transform the name of the JSON keys that contain "dots" to make it easier to reference them in XSOAR. + + Args: + json_data (dict): JSON to be transformed. + + Returns: + dict: JSON with the key names that contain "dots" transformed. + """ + replace_symbol = demisto.params().get("replace_dots_event", "_") + + if isinstance(json_data, str): + data = json.loads(json_data) + elif isinstance(json_data, dict): + data = json_data + else: + raise TypeError( + "JSON data sent to undot function must be a string or a dictionary" + ) + + # Iterate over each item in the items array + for item in data["items"]: + # Replace dots with underscores in each key + for key in list(item.keys()): + new_key = key.replace(".", replace_symbol) + if new_key != key: + item[new_key] = item.pop(key) + # Convert back to JSON and return it + return json.dumps(data) + + +""" COMMAND FUNCTIONS """ + + +def fetch_incidents( + client: Client, + max_results: int, + last_run: Dict[str, int], + first_fetch_time: Optional[int], + alert_status: Optional[str], + alert_urgency: Optional[str], + alert_type: Optional[str], + fetch_mode: Optional[str], + mirror_direction: Optional[str], + fetch_with_assets: Optional[bool], + fetch_with_kill_chain: Optional[bool], +) -> Tuple[Dict[str, int], List[dict]]: + """ + This function retrieves new alerts every interval (default is 1 minute). + It has to implement the logic of making sure that incidents are fetched only onces and no incidents are missed. + By default it's invoked by XSOAR every minute. It will use last_run to save the timestamp of the last incident it + processed. If last_run is not provided, it should use the integration parameter first_fetch_time to determine when + to start fetching the first time. + + Args: + client (Client): Sekoia XDR client to use. + max_results (int): Maximum numbers of incidents per fetch. + last_run (dict): A dict with a key containing the latest incident created time we got from last fetch. + first_fetch_time(int): If last_run is None (first time we are fetching), it contains the timestamp in + milliseconds on when to start fetching incidents. + alert_status (str): status of the alert to search for. + alert_urgency (str): alert urgency range to search for. Format: "MIN_urgency,MAX_urgency". i.e: 80,100. + alert_type (str): type of alerts to search for. + fetch_mode (str): If the alert will be fetched with or without the events. + mirror_direction (str): The direction of the mirroring can be set to None or to Incoming. + fetch_with_assets (bool): If the alert will include the assets information on the fetching. + fetch_with_kill_chain (bool): If the alert will include the kill chain information on the fetching. + Returns: + dict: Next run dictionary containing the timestamp that will be used in ``last_run`` on the next fetch. + list: List of incidents that will be created in XSOAR. + """ + # Get the last fetch time, if exists + # last_run is a dict with a single key, called last_fetch + last_fetch = last_run.get("last_fetch") + + # The case where no last_fetch or first_fetch_time are present. + if last_fetch is None and first_fetch_time is None: + raise DemistoException( + "Failure to fetch incidents. Can't find neither \ + last_fetch and first_fetch_time" + ) + # Handle first fetch time + elif last_fetch is None: + # if missing, use what provided via first_fetch_time + last_fetch = first_fetch_time + else: + # otherwise use the stored last fetch + last_fetch = int(last_fetch) + + # Convert time from epoch to ISO8601 in the correct format and add the ,now also + alerts_createdAt = time_converter(str(last_fetch)) + ",now" + + # for type checking, making sure that latest_created_time is int + latest_created_time = cast(int, last_fetch) + + # Initialize an empty list of incidents to return + # Each incident is a dict with a string as a key + incidents: List[Dict[str, Any]] = [] + alerts = client.list_alerts( + alerts_limit=max_results, + alerts_status=alert_status, + alerts_createdAt=alerts_createdAt, + alerts_updatedAt=None, + alerts_urgency=alert_urgency, + alerts_type=alert_type, + sort_by="created_at", + ) + + for alert in alerts["items"]: + # If no created_time set is as epoch (0). We use time in ms so we must + # convert it from the Sekoia XDR API response + incident_created_time = int(alert.get("created_at", "0")) + incident_created_time_ms = incident_created_time * 1000 + + # to prevent duplicates, we are only adding incidents with creation_time > last fetched incident + if last_fetch and incident_created_time <= last_fetch: + continue + + # If no name is present it will throw an exception + incident_name = alert["title"] + urgency = alert["urgency"] + + if fetch_mode == "Fetch With All Events": + # Add the events to the alert + earliest_time = alert["first_seen_at"] + lastest_time = "now" + term = "alert_short_ids:" + alert["short_id"] + interval_in_seconds = INTERVAL_SECONDS_EVENTS + timeout_in_seconds = TIMEOUT_EVENTS + max_last_events = MAX_EVENTS + + # Add the events to the alert + args = { + "earliest_time": earliest_time, + "lastest_time": lastest_time, + "query": term, + "interval_in_seconds": interval_in_seconds, + "timeout_in_seconds": timeout_in_seconds, + "max_last_events": max_last_events, + } + events = search_events_command(client, args) + alert["events"] = events.outputs + + if fetch_with_assets: + # Add assets information to the alert + asset_list = [] + for asset in alert["assets"]: + try: + asset_info = client.get_asset(asset_uuid=asset) + asset_list.append(asset_info) + except Exception as e: + # Handle the exception if there is any problem with the API call + demisto.debug(f"Error fetching asset {asset}: {e}") + # Continue with the next asset + continue + alert["assets"] = asset_list + + if fetch_with_kill_chain and alert["kill_chain_short_id"]: + # Add kill chain information to the alert + try: + kill_chain = client.get_kill_chain( + kill_chain_uuid=alert["kill_chain_short_id"] + ) + alert["kill_chain"] = kill_chain + except Exception as e: + # Handle the exception if there is any problem with the API call + demisto.debug( + f"Error fetching kill chain information {kill_chain}: {e}" + ) + + # If the integration parameter is set to mirror add the instance name to be mapped to dbotMirrorInstance + incident = { + "name": incident_name, + "occurred": timestamp_to_datestring(incident_created_time_ms), + "severity": convert_to_demisto_severity(urgency.get("display", "Low")), + } + # If the integration parameter is set to mirror add the appropriate fields to the incident + if mirror_direction != "None": + alert["mirror_instance"] = demisto.integrationInstance() + incident["rawJSON"] = json.dumps(alert) + incident["dbotMirrorDirection"] = MIRROR_DIRECTION.get( + str(mirror_direction) + ) + incident["dbotMirrorId"] = alert["short_id"] + + incidents.append(incident) + + # Update last run and add incident if the incident is newer than last fetch + if incident_created_time > latest_created_time: + latest_created_time = incident_created_time + + # Save the next_run as a dict with the last_fetch key to be stored + next_run = {"last_fetch": latest_created_time} + return next_run, incidents + + +# =========== Mirroring Mechanism =========== + + +def get_remote_data_command( + client: Client, + args: dict, + close_incident: bool, + close_note: str, + mirror_events: bool, + mirror_kill_chain: bool, + reopen_incident: bool, +): + """get-remote-data command: Returns an updated alert and error entry (if needed) + + Args: + client (Client): Sekoia XDR client to use. + args (dict): The command arguments + close_incident (bool): Indicates whether to close the corresponding XSOAR incident if the alert + has been closed on Sekoia's end. + close_note (str): Indicates the notes to be including when the incident gets closed by mirroring. + mirror_events (bool): If the events will be included in the mirroring of the alerts or not. + mirror_kill_chain: If the kill chain information from the alerts will be mirrored. + reopen_incident: Indicates whether to reopen the corresponding XSOAR incident if the alert + has been reopened on Sekoia's end. + Returns: + GetRemoteDataResponse: The Response containing the update alert to mirror and the entries + """ + + demisto.debug("#### Entering MIRRORING IN - get_remote_data_command ####") + + parsed_args = GetRemoteDataArgs(args) + alert = client.get_alert(alert_uuid=parsed_args.remote_incident_id) + + alert_short_id, alert_status = alert["short_id"], alert["status"]["name"] + last_update = arg_to_timestamp( + arg=args.get("lastUpdate"), arg_name="lastUpdate", required=True + ) + alert_last_update = arg_to_timestamp( + arg=alert.get("updated_at"), arg_name="updated_at", required=False + ) + + demisto.debug( + f"Alert {alert_short_id} with status {alert_status} : last_update is {last_update} , alert_last_update is {alert_last_update}" # noqa: E501 + ) + + entries = [] + + # Add the events to the alert + if mirror_events and alert["status"]["name"] not in ["Closed", "Rejected"]: + earliest_time = alert["first_seen_at"] + lastest_time = "now" + term = "alert_short_ids:" + alert["short_id"] + interval_in_seconds = INTERVAL_SECONDS_EVENTS + timeout_in_seconds = TIMEOUT_EVENTS + max_last_events = MAX_EVENTS + + args = { + "earliest_time": earliest_time, + "lastest_time": lastest_time, + "query": term, + "interval_in_seconds": interval_in_seconds, + "timeout_in_seconds": timeout_in_seconds, + "max_last_events": max_last_events, + } + events = search_events_command(client, args) + alert["events"] = events.outputs + + # Add the kill chain information to the alert + if mirror_kill_chain and alert["kill_chain_short_id"]: + try: + kill_chain = client.get_kill_chain( + kill_chain_uuid=alert["kill_chain_short_id"] + ) + alert["kill_chain"] = kill_chain + except Exception as e: + # Handle the exception if there is any problem with the API call + demisto.debug(f"Error fetching kill_chain : {e}") + + # This adds all the information from the XSOAR incident. + demisto.debug( + f"Alert {alert_short_id} with status {alert_status} have this info updated: {alert}" + ) + + investigation = demisto.investigation() + demisto.debug(f"The investigation information is {investigation}") + + incident_id = investigation["id"] + incident_status = investigation["status"] + + demisto.debug( + f"The XSOAR incident is {incident_id} with status {incident_status} is being mirrored with the alert {alert_short_id} that have the status {alert_status}." # noqa: E501 + ) + + # Close the XSOAR incident using mirroring + if ( + (close_incident) + and (alert_status in ["Closed", "Rejected"]) + and (investigation["status"] != 1) + ): + demisto.debug( + f"Alert {alert_short_id} with status {alert_status} was closed or rejected in Sekoia, closing incident {incident_id} in XSOAR" # noqa: E501 + ) + entries = [ + { + "Type": EntryType.NOTE, + "Contents": { + "dbotIncidentClose": True, + "closeReason": f"{alert_status} - Mirror", + "closeNotes": close_note, + }, + "ContentsFormat": EntryFormat.JSON, + } + ] + + # Reopen the XSOAR incident using mirroring + if ( + (reopen_incident) + and (alert_status not in ["Closed", "Rejected"]) + and (investigation["status"] == 1) + ): + demisto.debug( + f"Alert {alert_short_id} with status {alert_status} was reopened in Sekoia, reopening incident {incident_id} in XSOAR" + ) + entries = [ + { + "Type": EntryType.NOTE, + "Contents": {"dbotIncidentReopen": True}, + "ContentsFormat": EntryFormat.JSON, + } + ] + + demisto.debug("#### Leaving MIRRORING IN - get_remote_data_command ####") + + return GetRemoteDataResponse(mirrored_object=alert, entries=entries) + + +def get_modified_remote_data_command(client: Client, args): + """Gets the list of all alert ids that have change since a given time + + Args: + client (Client): Sekoia XDR client to use. + args (dict): The command argument + + Returns: + GetModifiedRemoteDataResponse: The response containing the list of ids of notables changed + """ + modified_alert_ids = [] + remote_args = GetModifiedRemoteDataArgs(args) + last_update = remote_args.last_update + last_update_utc = dateparser.parse( + last_update, settings={"TIMEZONE": "UTC"} + ) # converts to a UTC timestamp + formatted_last_update = last_update_utc.strftime("%Y-%m-%dT%H:%M:%S.%f+00:00") # type: ignore + + demisto.debug(formatted_last_update) + converted_time = time_converter(formatted_last_update) + last_update_time = converted_time + ",now" + + raw_alerts = client.list_alerts( + alerts_updatedAt=last_update_time, + alerts_limit=100, + alerts_status=None, + alerts_createdAt=None, + alerts_urgency=None, + alerts_type=None, + sort_by="updated_at", + ) + + for item in raw_alerts["items"]: + modified_alert_ids.append(item["short_id"]) + + return_results( + GetModifiedRemoteDataResponse(modified_incident_ids=modified_alert_ids) + ) + + +def update_remote_system_command(client: Client, args): + """update-remote-system command: pushes local changes to the remote system + + :type client: ``Client`` + :param client: XSOAR client to use + + :type args: ``Dict[str, Any]`` + :param args: + all command arguments, usually passed from ``demisto.args()``. + ``args['data']`` the data to send to the remote system + ``args['entries']`` the entries to send to the remote system + ``args['incidentChanged']`` boolean telling us if the local incident indeed changed or not + ``args['remoteId']`` the remote incident id + args: A dictionary containing the data regarding a modified incident, including: data, entries, incident_changed, + remote_incident_id, inc_status, delta + + :return: + ``str`` containing the remote incident id - really important if the incident is newly created remotely + + :rtype: ``str`` + """ + demisto.debug("#### Entering MIRRORING OUT - update_remote_system_command ####") + parsed_args = UpdateRemoteSystemArgs(args) + delta = parsed_args.delta + remote_incident_id = parsed_args.remote_incident_id + xsoar_incident = parsed_args.data.get("xsoar_id") + demisto.debug( + f"Remote_incident_id {remote_incident_id} with local id {xsoar_incident} \ + had this changes {parsed_args.incident_changed} \ + with delta {delta} and parsed_args {parsed_args.data}" + ) + try: + if parsed_args.incident_changed: + sekoia_status = delta.get("status", None) + if sekoia_status: + demisto.debug( + f"The incident #{xsoar_incident} had the sekoia status of the alert {remote_incident_id} changed to: {sekoia_status}. Sending changes to Sekoia." # noqa: E501 + ) + sekoia_transition = STATUS_TRANSITIONS.get(sekoia_status) + + workflow = client.get_workflow_alert(alert_uuid=remote_incident_id) + for action in workflow["actions"]: + if action["name"] == sekoia_transition: + change_status = client.update_status_alert( + alert_uuid=remote_incident_id, + action_uuid=action["id"], + comment=None, + ) + demisto.debug(f"Changing status : {change_status}") + else: + demisto.debug( + f"There's no changes in our incident with local id {xsoar_incident}" + ) + + except Exception as e: + demisto.error( + f"Error in Sekoia outgoing mirror for incident {remote_incident_id}. " + f"Error message: {str(e)}" + ) + + return remote_incident_id + + +def get_mapping_fields_command() -> GetMappingFieldsResponse: + """ + this command pulls the remote schema for the different incident types, and their associated incident fields, + from the remote system. + :return: A list of keys you want to map + """ + sekoia_incident_type_scheme = SchemeTypeMapping(type_name=INCIDENT_TYPE_NAME) + for argument, description in SEKOIA_INCIDENT_FIELDS.items(): + sekoia_incident_type_scheme.add_field(name=argument, description=description) + + mapping_response = GetMappingFieldsResponse() + mapping_response.add_scheme_type(sekoia_incident_type_scheme) + + return mapping_response + + +# =========== Mirroring Mechanism =========== + + +def list_alerts_command(client: Client, args: Dict[str, Any]) -> CommandResults: + + alerts = client.list_alerts( + alerts_limit=args.get("limit"), + alerts_status=args.get("status"), + alerts_createdAt=args.get("created_at"), + alerts_updatedAt=args.get("updated_at"), + alerts_urgency=args.get("urgency"), + alerts_type=args.get("alerts_type"), + sort_by=args.get("sort_by"), + ) + + return CommandResults( + outputs_prefix="SekoiaXDR.ListAlerts", + outputs_key_field="short_id", + outputs=alerts["items"], + ) + + +def get_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = str(args.get("id")) + + alert = client.get_alert(alert_uuid=alert_uuid) + readable_output = tableToMarkdown(f"Alert {alert_uuid}:", alert) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Alert", + outputs_key_field="uuid", + outputs=alert, + ) + + +def query_events_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + earliest_time = str(args.get("earliest_time")) + lastest_time = str(args.get("lastest_time")) + term = str(args.get("query")) + max_last_events = str(args.get("max_last_events")) + + jobQuery = client.query_events( + events_earliest_time=earliest_time, + events_latest_time=lastest_time, + events_term=term, + max_last_events=max_last_events, + ) + readable_output = tableToMarkdown( + f"Event search created using the term {term}:", jobQuery + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="uuid", + outputs=jobQuery, + ) + + +def query_events_status_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + search_job_uuid = str(args.get("uuid")) + + status = client.query_events_status(event_search_job_uuid=search_job_uuid) + readable_output = tableToMarkdown(f"Status of the job {search_job_uuid}:", status) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="search_job_uuid", + outputs=status, + ) + + +def retrieve_events_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + search_job_uuid = str(args.get("uuid")) + + events = client.retrieve_events(event_search_job_uuid=search_job_uuid) + readable_output = tableToMarkdown( + f"Events retrieved for the search {search_job_uuid}:", events + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="search_job_uuid", + outputs=events, + ) + + +def search_events_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + earliest_time = str(args.get("earliest_time")) + lastest_time = str(args.get("lastest_time")) + term = str(args.get("query")) + max_last_events = str(args.get("max_last_events")) + timeout_in_seconds = int(args.get("timeout_in_seconds") or 0) + exclude_info_arg = args.get("exclude_info") + exclude_info_param = demisto.params().get("exclude_info_events") + replace_symbol = demisto.params().get("replace_dots_event") + + search = client.query_events( + events_earliest_time=earliest_time, + events_latest_time=lastest_time, + events_term=term, + max_last_events=max_last_events, + ) + search_job_uuid = search["uuid"] + + start_time = time.time() + bool_flag = True + while bool_flag: + # Break when the time of the query is bigger than the timeout + if time.time() - start_time > timeout_in_seconds: + demisto.debug( + "The query of the events have timeout without a valid status result." + ) + break + query_status = client.query_events_status(event_search_job_uuid=search_job_uuid) + status = query_status["status"] + if status == 2: + events = client.retrieve_events(event_search_job_uuid=search_job_uuid) + total = max_last_events or events["total"] + + # If there is event info to exclude sent on arguments + if exclude_info_arg and len(events["items"]) > 0: + """Collect the headers with the removed info and replace the dots""" + headers = exclude_info_events( + event_info=events, exclude_info=exclude_info_arg + ) + headers = [header.replace(".", replace_symbol) for header in headers] + """ Remove dots from events key names""" + events_undot = undot(json_data=events) + readable_output = tableToMarkdown( + f"{total} events out of " + + str(events["total"]) + + f" retrieved for the {term}:", + events_undot, + headers=headers, + ) + + # If there is event info to exclude in the parameters but not sent in the arguments + elif ( + exclude_info_param + and len(events["items"]) > 0 + and exclude_info_arg is None + ): + """Collect the headers with the removed info and replace the dots""" + headers = exclude_info_events( + event_info=events, exclude_info=",".join(exclude_info_param) + ) + headers = [header.replace(".", replace_symbol) for header in headers] + """ Remove dots from events key names""" + events_undot = undot(json_data=events) + readable_output = tableToMarkdown( + f"{total} events out of " + + str(events["total"]) + + f" retrieved for the {term}:", + events_undot, + headers=headers, + ) + + # If there is no event info to exclude in the parameters nor in the arguments + elif ( + (exclude_info_arg is None) + and (not exclude_info_param) + and (len(events["items"]) > 0) + ): + events_undot = undot(json_data=events) + readable_output = tableToMarkdown( + f"{total} events out of " + + str(events["total"]) + + f" retrieved for the {term}:", + events_undot, + ) + + # ELSE + else: + readable_output = tableToMarkdown( + f"{total} events out of " + + str(events["total"]) + + f" retrieved for the {term}:", + events["items"], + ) + + bool_flag = False + else: + demisto.debug(f"The query is still running with the status {status}") + + time.sleep(int(args.get("interval_in_seconds") or 0)) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events.Results", + outputs_key_field="search_job_uuid", + outputs=events["items"], + ) + + +def update_status_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, updated_status, comment = ( + str(args.get("id")), + str(args.get("status")), + args.get("comment"), + ) + sekoia_transition = STATUS_TRANSITIONS.get(updated_status) + readable_output = "Unknown alert" + + workflow = client.get_workflow_alert(alert_uuid=alert_uuid) + + for action in workflow["actions"]: + if action["name"] == sekoia_transition: + update = client.update_status_alert( + alert_uuid=alert_uuid, action_uuid=action["id"], comment=comment + ) + if update or update == {}: + readable_output = ( + "### Alert " + alert_uuid + " updated to status: " + updated_status + ) + else: + raise DemistoException( + "Failure to update the status of the alert. \ + Run the command !sekoia-get-workflow-alert to see the possible\ + transitions and review the code." + ) + + return CommandResults(readable_output=readable_output, outputs=update) + + +def post_comment_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, comment, author = ( + str(args.get("id")), + str(args.get("comment")), + str(args.get("author")), + ) + + response = client.post_comment_alert( + alert_uuid=alert_uuid, content=comment, author=author + ) + readable_output = tableToMarkdown( + f"Alert {alert_uuid} updated with the comment: \n {comment}:", response + ) + + return CommandResults(readable_output=readable_output, outputs=response) + + +def get_comments_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = str(args.get("id")) + + response = client.get_comments_alert(alert_uuid=alert_uuid) + + for item in response["items"]: + # Add author of the comment + if item["author"].startswith("user"): + user = client.get_user(user_uuid=item["created_by"]) + item["user"] = f"{user.get('firstname')} {user.get('lastname')}" + elif item["author"].startswith("apikey"): + item["user"] = "Commented via API" + elif item["author"].startswith("application"): + item["user"] = "Sekoia.io" + else: + item["user"] = item["author"] + # Add formatted date of the comment + item["date"] = timezone_format(item["date"]) + + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following comments:", response["items"] + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Comments", + outputs_key_field="alert_uuid", + outputs=response["items"], + ) + + +def get_workflow_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = str(args.get("id")) + + response = client.get_workflow_alert(alert_uuid=alert_uuid) + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following available status transitions:", + response["actions"], + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.StatusTransitions", + outputs_key_field="alert_uuid", + outputs=response["actions"], + ) + + +def get_cases_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, case_id = str(args.get("alert_id")), str(args.get("case_id")) + + response = client.get_cases_alert(alert_uuid=alert_uuid, case_id=case_id) + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following cases:", response["items"] + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Cases", + outputs_key_field="alert_uuid", + outputs=response["items"], + ) + + +def get_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid = str(args.get("asset_uuid")) + + asset = client.get_asset(asset_uuid=asset_uuid) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} have the following information:", asset + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Asset", + outputs_key_field="uuid", + outputs=asset, + ) + + +def list_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + limit, assets_type = str(args.get("limit")), str(args.get("assets_type")) + + assets = client.list_asset(limit=limit, assets_type=assets_type) + readable_output = tableToMarkdown( + f"List of {assets['total']} assets found:", assets["items"] + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Assets", + outputs_key_field="asset_uuid", + outputs=assets["items"], + ) + + +def get_user_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + user_uuid = str(args.get("user_uuid")) + + user = client.get_user(user_uuid=user_uuid) + readable_output = tableToMarkdown( + f"User {user_uuid} have the following information:", user + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.User", + outputs_key_field="user_uuid", + outputs=user, + ) + + +def add_attributes_asset_command( + client: Client, args: Dict[str, Any] +) -> CommandResults: + """Parameters""" + asset_uuid, name, value = ( + str(args.get("asset_uuid")), + str(args.get("name")), + str(args.get("value")), + ) + + asset_attributes = client.add_attributes_asset( + asset_uuid=asset_uuid, name=name, value=value + ) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} was updated with new attributes:", asset_attributes + ) + + return CommandResults( + readable_output=readable_output, + outputs_key_field="asset_uuid", + outputs=asset_attributes, + ) + + +def add_keys_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid, name, value = ( + str(args.get("asset_uuid")), + str(args.get("name")), + str(args.get("value")), + ) + + asset_keys = client.add_keys_asset(asset_uuid=asset_uuid, name=name, value=value) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} was updated with new keys:", asset_keys + ) + + return CommandResults( + readable_output=readable_output, + outputs_key_field="asset_uuid", + outputs=asset_keys, + ) + + +def remove_attribute_asset_command( + client: Client, args: Dict[str, Any] +) -> CommandResults: + """Parameters""" + asset_uuid, attribute_uuid = str(args.get("asset_uuid")), str( + args.get("attribute_uuid") + ) + + client.remove_attribute_asset(asset_uuid=asset_uuid, attribute_uuid=attribute_uuid) + readable_output = ( + f"Asset {asset_uuid} had the following attribute removed:\n{attribute_uuid}" + ) + + return CommandResults(readable_output=readable_output) + + +def remove_key_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid, key_uuid = str(args.get("asset_uuid")), str(args.get("key_uuid")) + + client.remove_key_asset(asset_uuid=asset_uuid, key_uuid=key_uuid) + readable_output = f"Asset {asset_uuid} had the following key removed:\n{key_uuid}" + + return CommandResults(readable_output=readable_output) + + +def get_kill_chain_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + kill_chain_uuid = str(args.get("kill_chain_uuid")) + + kill_chain = client.get_kill_chain(kill_chain_uuid=kill_chain_uuid) + readable_output = tableToMarkdown( + f"Kill chain {kill_chain_uuid} have the following information:", kill_chain + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.KillChain", + outputs_key_field="uuid", + outputs=kill_chain, + ) + + +def http_request_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + method, url_sufix, params = ( + str(args.get("method")), + str(args.get("url_sufix")), + dict(args.get("parameters") or {}), + ) + request = client.http_request(method=method, params=params, url_suffix=url_sufix) + readable_output = tableToMarkdown( + f"The HTTP {method} request with params {params} returned the following information:", + request, + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.http_request", + outputs_key_field="uuid", + outputs=request, + ) + + +def test_module(client: Client) -> str: + """ + Tests API connectivity and authentication' + When 'ok' is returned it indicates the integration works like it is supposed to and connection to the service is successful. + Raises exceptions if something goes wrong. + + Args: + client (Client): Sekoia XDR client to use. + + Returns: + str: 'ok' if test passed, anything else will raise an exception and will fail the test. + """ + # Check a JWT token’s validity + # https://docs.sekoia.io/develop/rest_api/identity_and_authentication/#tag/User-Authentication/operation/get_validate_resource + + try: + client.get_validate_resource() + except DemistoException as e: + doc = """Please visit the API Key documentation for more information: + https://docs.sekoia.io/getting_started/generate_api_keys/""" + + if "T300" in str(e): + return f"Authorization Error: The token is invalid. {doc}" + elif "T301" in str(e): + return f"Authorization Error: The token has expired. {doc}" + elif "T302" in str(e): + return f"Authorization Error: The token has been revoked. {doc}" + else: + raise e + return "ok" + + +def main() -> None: + """ + main function, parses params and runs command functions + """ + + params, args, command = demisto.params(), demisto.args(), demisto.command() + + # get the service API url and api key + api_key = params.get("credentials", {}).get("password") + base_url = params.get("url") + + # if your Client class inherits from BaseClient, SSL verification is + # handled out of the box by it, just pass ``verify_certificate`` and ``proxy`` to + # the Client constructor + verify_certificate = not params.get("insecure", False) + proxy = params.get("proxy", False) + + # How much time before the first fetch to retrieve incidents + first_fetch_time = arg_to_datetime( + arg=params.get("first_fetch", "3 days"), + arg_name="First fetch time", + required=True, + ) + first_fetch_timestamp = ( + int(first_fetch_time.timestamp()) if first_fetch_time else None + ) + + demisto.debug(f"Command being called is {command}") + try: + headers = {"Authorization": f"Bearer {api_key}"} + client = Client( + base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy + ) + + if command == "test-module": + # This is the call made when pressing the integration Test button. + result = test_module(client) + return_results(result) + + elif command == "fetch-incidents": + # Set and define the fetch incidents command to run after activated via integration settings. + alerts_status = ",".join(params.get("alerts_status", None)) + alerts_type = ",".join(params.get("alerts_type", None)) + alerts_urgency = params.get("alerts_urgency", None) + fetch_mode = params.get("fetch_mode") + fetch_with_assets = params.get("fetch_with_assets") + fetch_with_kill_chain = params.get("fetch_with_kill_chain") + mirror_direction = params.get("mirror_direction") + + # Convert the argument to an int using helper function or set to MAX_INCIDENTS_TO_FETCH + max_results = params.get("max_fetch", MAX_INCIDENTS_TO_FETCH) + last_run: Dict[str, Any] = ( + demisto.getLastRun() + ) # getLastRun() gets the last run dict + + next_run, incidents = fetch_incidents( + client=client, + max_results=max_results, + last_run=last_run, + first_fetch_time=first_fetch_timestamp, + alert_status=alerts_status, + alert_urgency=alerts_urgency, + alert_type=alerts_type, + fetch_mode=fetch_mode, + mirror_direction=mirror_direction, + fetch_with_assets=fetch_with_assets, + fetch_with_kill_chain=fetch_with_kill_chain, + ) + + # saves next_run for the time fetch-incidents is invoked + demisto.setLastRun(next_run) + # fetch-incidents calls ``demisto.incidents()`` to provide the list of incidents to create + demisto.incidents(incidents) + + elif command == "sekoia-list-alerts": + return_results(list_alerts_command(client, args)) + elif command == "sekoia-get-alert": + return_results(get_alert_command(client, args)) + elif command == "sekoia-events-execute-query": + return_results(query_events_command(client, args)) + elif command == "sekoia-events-status-query": + return_results(query_events_status_command(client, args)) + elif command == "sekoia-events-results-query": + return_results(retrieve_events_command(client, args)) + elif command == "sekoia-search-events": + return_results(search_events_command(client, args)) + elif command == "sekoia-update-status-alert": + return_results(update_status_alert_command(client, args)) + elif command == "sekoia-post-comment-alert": + return_results(post_comment_alert_command(client, args)) + elif command == "sekoia-get-comments": + return_results(get_comments_alert_command(client, args)) + elif command == "sekoia-get-workflow-alert": + return_results(get_workflow_alert_command(client, args)) + elif command == "sekoia-get-cases-alert": + return_results(get_cases_alert_command(client, args)) + elif command == "sekoia-get-asset": + return_results(get_asset_command(client, args)) + elif command == "sekoia-list-assets": + return_results(list_asset_command(client, args)) + elif command == "sekoia-get-user": + return_results(get_user_command(client, args)) + elif command == "sekoia-add-attributes-asset": + return_results(add_attributes_asset_command(client, args)) + elif command == "sekoia-add-keys-asset": + return_results(add_keys_asset_command(client, args)) + elif command == "sekoia-remove-attribute-asset": + return_results(remove_attribute_asset_command(client, args)) + elif command == "sekoia-remove-key-asset": + return_results(remove_key_asset_command(client, args)) + elif command == "sekoia-get-kill-chain": + return_results(get_kill_chain_command(client, args)) + elif command == "sekoia-http-request": + return_results(http_request_command(client, args)) + elif command == "get-remote-data": + return_results( + get_remote_data_command( + client, + args, + close_incident=demisto.params().get("close_incident"), # type: ignore + close_note=demisto.params().get("close_note"), # type: ignore + mirror_events=demisto.params().get("mirror_events"), # type: ignore + mirror_kill_chain=demisto.params().get("mirror_kill_chain"), # type: ignore + reopen_incident=demisto.params().get("reopen_incident"), # type: ignore + ) + ) + elif command == "get-modified-remote-data": + get_modified_remote_data_command(client, args) + elif command == "update-remote-system": + update_remote_system_command(client, args) + elif command == "get-mapping-fields": + return_results(get_mapping_fields_command()) + else: + raise NotImplementedError(f"Command {command} is not implemented") + + # Log exceptions and return errors + except Exception as e: + return_error(f"Failed to execute {command} command.\nError:\n{str(e)}") + + +""" ENTRY POINT """ + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml new file mode 100644 index 000000000000..2779eb3e1715 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml @@ -0,0 +1,1156 @@ +commonfields: + id: Sekoia XDR + version: -1 +name: Sekoia XDR +display: Sekoia XDR +category: Analytics & SIEM +description: "Fetch alerts and events from SEKOIA.IO XDR.\nTo use this integration, please create an API Key with the appropriate permissions. " +detaileddescription: |- + ### Sekoia XDR Integration + #### Author: Sekoia.io + Support and maintenance for this integration are provided by the author. Please use the following contact details: + - Email: contact@sekoia.io + - URL: [https://www.sekoia.io/en/contact/](https://www.sekoia.io/en/contact/) + *** + ## Sekoia XDR + - The mandatory fields are the API Key and the base URL of the API (i.e. https://api.sekoia.io/v1/sic/) + --- + [View documentation for the API calls](https://docs.sekoia.io/xdr/) +configuration: +- display: Fetch incidents + name: isFetch + type: 8 + required: false +- display: Incident type + name: incidentType + type: 13 + required: false +- display: Server URL (i.e. https://api.sekoia.io) + name: url + defaultvalue: https://api.sekoia.io + type: 0 + required: true +- display: "" + displaypassword: API Key + name: credentials + type: 9 + required: true + hiddenusername: true +- display: 'First fetch time - Filter their creation dates, starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17"' + name: first_fetch + defaultvalue: -7d,now + type: 0 + required: true +- display: Trust any certificate (not secure) + name: insecure + type: 8 + required: false +- display: Use system proxy settings + name: proxy + type: 8 + required: false +- display: Fetch alerts with the selected status. + name: alerts_status + defaultvalue: Pending,Acknowledged,Ongoing + type: 16 + required: false + options: + - Pending + - Acknowledged + - Ongoing + - Rejected + - Closed +- display: List of types of alerts to fetch. (Write and press enter to insert types that are not in the list) + name: alerts_type + type: 16 + required: false + options: + - spam + - ddos + - outage + - phishing + - unauthorized-use-of-resources + - unauthorised-information-access + - appsacan + - scanner + - brute-force + - exploit + - sniffing + - ransomware + - malware + - trojan + - rootkit + - worm + - virus + - privileged-account-compromise + - unprivileged-account-compromise + - application-compromise + - bot + - defacement + - system-compromise + - backdoor + - privilege-escalation + - lateral-move + - reconnaissance + - c&c + - payload + - tunnel + - exfiltration + - blacklist +- display: 'Filter alerts by their urgencies range in the following format: "MINurgency,MAXurgency". i.e: 80,100.' + name: Alerts urgency + type: 0 + required: false +- display: Maximum incidents to fetch per interval (By default set to 10). + name: max_fetch + defaultvalue: "10" + type: 0 + required: true +- display: Fetch mode + name: fetch_mode + defaultvalue: Fetch Without Events + type: 15 + required: true + options: + - Fetch Without Events + - Fetch With All Events +- display: Include assets information in the alerts when fetching. + name: fetch_with_assets + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When seleted, it includes the assets information in the when an alert is fetched in Sekoia. +- display: Include kill chain information in the alerts when fetching. + name: fetch_with_kill_chain + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When seleted, it includes the kill chain information in the when an alert is fetched in Sekoia. +- display: Replace the "dots" from the event field names for a different character easier to reference in XSOAR. + name: replace_dots_event + defaultvalue: _ + type: 15 + required: true + options: + - _ + - "-" +- display: "Indicate if there is any information you want to exclude from the results of the events search. i.e: original.message, message, agent.name, etc. " + name: exclude_info_events + type: 16 + required: false + options: + - original.message + - message + - __event_id + - agent.name + - alert_short_ids + - client.address + - client.ip + - client.user.id + - customer.community_name + - customer.community_uuid + - customer.id + - customer.intake_key + - customer.intake_name + - customer.intake_uuid + - ecs.version + - entity.id + - entity.name + - entity.uuid + - event.created + - event.dialect + - event.dialect_uuid + - event.id + - event.outcome + - http.request.method + - sekoiaio.customer.community_name + additionalinfo: This is the names of the headers presented in the events table. If the header is not in the dropdown list write it and press enter. +- display: Incident Mirroring Direction + name: mirror_direction + defaultvalue: None + type: 15 + required: true + options: + - None + - Incoming + - Outgoing + - Incoming and Outgoing + additionalinfo: "Choose the direction to mirror the incident: None(Disable mirroring), Incoming (from Sekoia XDR to Cortex XSOAR) , Outgoing (from Cortex XSOAR to Sekoia XDR), or Incoming and Outgoing (from/to Cortex XSOAR and Sekoia XDR)." +- display: Reopen Mirrored Cortex XSOAR Incidents (Incoming Mirroring) + name: reopen_incident + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When selected, reopening the Sekoia XDR alert will reopen the Cortex XSOAR incident. +- display: Close Mirrored Cortex XSOAR Incidents (Incoming Mirroring) + name: close_incident + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When selected, closing the Sekoia XDR alert with a "Closed" or "Reject" status will close the Cortex XSOAR incident. +- display: "Notes to add when the incident it automatically closed by mirroring:" + name: close_note + defaultvalue: Closed by Sekoia. + type: 0 + required: true + additionalinfo: Change the closing notes that will be added to the tickets closed automatically by the automation. +- display: Include events in the mirroring of the alerts. + name: mirror_events + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When seleted, it includes the events in the mirroring when an alert is updated in Sekoia. +- display: Include kill chain information in the mirroring of the alerts. + name: mirror_kill_chain + defaultvalue: "false" + type: 8 + required: false + additionalinfo: When seleted, it includes the kill chain information of the alert in the mirroring when an alert is updated in Sekoia. +- display: "Input your timezone, use formats from the list of tz database time zones (i.e. 'UTC', 'Europe/Madrid', 'US/Eastern', 'Etc/Greenwich', 'Canada/Eastern') " + name: timezone + defaultvalue: Europe/Paris + type: 0 + required: true + additionalinfo: This will be used to present dates in the appropiate timezones, used for comment timestamps, etc. +- display: Incidents Fetch Interval + name: incidentFetchInterval + defaultvalue: "1" + type: 19 + required: false +script: + script: "-" + type: python + commands: + - name: sekoia-list-alerts + arguments: + - name: limit + description: Limit a number of items (allowed range is 1-100), default is 20. + defaultValue: "20" + - name: status + auto: PREDEFINED + predefined: + - Pending + - Acknowledged + - Ongoing + - Rejected + - Closed + description: Match alerts by their status name (separated by commas). + isArray: true + - name: created_at + description: 'Filter alerts by their creation dates, starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17".' + - name: updated_at + description: 'Filter alerts by their update dates starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17".' + - name: urgency + description: 'Filter alerts by their urgencies range in the following format: "MINurgency,MAXurgency". i.e: 80,100.' + - name: Alerts type + auto: PREDEFINED + predefined: + - spam + - ddos + - outage + - phishing + - unauthorized-use-of-resources + - unauthorised-information-access + - appscan + - scanner + - brute-force + - exploit + description: Match alerts by their type categories (separated by commas). + isArray: true + - name: sort_by + default: true + auto: PREDEFINED + predefined: + - created_at + - updated_at + - target + - urgency + - status + description: Sort the alerts by any information. + defaultValue: created_at + outputs: + - contextPath: SekoiaXDR.ListAlerts.updated_at + description: The time at which the alert was updated. + - contextPath: SekoiaXDR.ListAlerts.updated_by + description: The user who last updated the alert. + - contextPath: SekoiaXDR.ListAlerts.uuid + description: The unique identifier of the alert. + - contextPath: SekoiaXDR.ListAlerts.title + description: The title of the alert. + - contextPath: SekoiaXDR.ListAlerts.time_to_respond + description: The time it took to respond to the alert. + - contextPath: SekoiaXDR.ListAlerts.short_id + description: The short identifier of the alert. + - contextPath: SekoiaXDR.ListAlerts.community_uuid + description: The unique identifier of the community associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.kill_chain_short_id + description: The short identifier of the kill chain associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.number_of_unseen_comments + description: The number of unseen comments on the alert. + - contextPath: SekoiaXDR.ListAlerts.updated_by_type + description: The type of user who last updated the alert. + - contextPath: SekoiaXDR.ListAlerts.source + description: The source of the alert. + - contextPath: SekoiaXDR.ListAlerts.alert_type.value + description: The type of the alert. + - contextPath: SekoiaXDR.ListAlerts.alert_type.category + description: The category type of the alert. + - contextPath: SekoiaXDR.ListAlerts.time_to_acknowledge + description: The time it took to acknowledge the alert. + - contextPath: SekoiaXDR.ListAlerts.stix + description: The STIX data associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.first_seen_at + description: The time the alert was first seen. + - contextPath: SekoiaXDR.ListAlerts.ttps.type + description: The type of the TTP associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.ttps.name + description: The name of the TTP associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.ttps.id + description: The unique identifier of the TTP associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.ttps.description + description: The description of the TTP associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.adversaries.type + description: The type of the adversary associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.adversaries.name + description: The name of the adversary associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.adversaries.id + description: The unique identifier of the adversary associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.adversaries.description + description: The description of the adversary associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.time_to_ingest + description: The time it took to ingest the alert. + - contextPath: SekoiaXDR.ListAlerts.target + description: The target of the alert. + - contextPath: SekoiaXDR.ListAlerts.time_to_resolve + description: The time it took to resolve the alert. + - contextPath: SekoiaXDR.ListAlerts.created_at + description: The time at which the alert was created. + - contextPath: SekoiaXDR.ListAlerts.last_seen_at + description: The time at which the alert was last seen. + - contextPath: SekoiaXDR.ListAlerts.assets + description: The assets associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.severity + description: The severity level of the rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.type + description: The type of rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.uuid + description: The unique identifier of the rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.name + description: The name of the rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.description + description: The description of the rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.rule.pattern + description: The pattern of the rule that triggered the alert. + - contextPath: SekoiaXDR.ListAlerts.similar + description: The number of similar alerts to this one. + - contextPath: SekoiaXDR.ListAlerts.status.name + description: The name of the status of the alert. + - contextPath: SekoiaXDR.ListAlerts.status.description + description: The description of the status of the alert. + - contextPath: SekoiaXDR.ListAlerts.status.uuid + description: The unique identifier of the status of the alert. + - contextPath: SekoiaXDR.ListAlerts.urgency.criticity + description: The level of criticity of the urgency of the alert. + - contextPath: SekoiaXDR.ListAlerts.urgency.current_value + description: The current value of the urgency of the alert. + - contextPath: SekoiaXDR.ListAlerts.urgency.severity + description: The severity level of the urgency of the alert. + - contextPath: SekoiaXDR.ListAlerts.urgency.display + description: The display of the urgency of the alert. + - contextPath: SekoiaXDR.ListAlerts.urgency.value + description: The value of the urgency of the alert. + - contextPath: SekoiaXDR.ListAlerts.created_by + description: The user who created the alert. + - contextPath: SekoiaXDR.ListAlerts.number_of_total_comments + description: The total number of comments on the alert. + - contextPath: SekoiaXDR.ListAlerts.time_to_detect + description: The time it took to detect the alert. + - contextPath: SekoiaXDR.ListAlerts.entity.name + description: The name of the entity associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.entity.uuid + description: The unique identifier of the entity associated with the alert. + - contextPath: SekoiaXDR.ListAlerts.created_by_type + description: The type of user who created the alert. + - contextPath: SekoiaXDR.ListAlerts.details + description: The details of the alert. + description: Command to retrieve a list of Alerts from Sekoia XDR. + - name: sekoia-get-alert + arguments: + - name: id + required: true + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + outputs: + - contextPath: SekoiaXDR.Alert.short_id + description: Short ID of the alert. + type: string + - contextPath: SekoiaXDR.Alert.title + description: Title of the alert. + type: string + - contextPath: SekoiaXDR.Alert.urgency + description: urgency of the alert. + type: string + description: Command to retrieve a specific Alert by uuid or short_id from Sekoia XDR. + - name: sekoia-events-execute-query + arguments: + - name: earliest_time + required: true + description: "Valid expressions: -3d: from three days ago, -2w: from two weeks before now, -7d: seven days before now." + - name: lastest_time + required: true + description: "Valid expressions: +3d: three days in the future, +2w: two weeks in the future, now: current time." + - name: query + required: true + description: 'The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga".' + - name: max_last_events + description: Maximum number of listed events. + outputs: + - contextPath: SekoiaXDR.Events.Query.uuid + description: The unique identifier for the event. + - contextPath: SekoiaXDR.Events.Query.term + description: The search term associated with the event. + - contextPath: SekoiaXDR.Events.Query.started_at + description: The time at which the event started. + - contextPath: SekoiaXDR.Events.Query.short_histogram.cases + description: The number of cases associated with the event. + - contextPath: SekoiaXDR.Events.Query.short_histogram.total + description: The total number of events associated with the search term. + - contextPath: SekoiaXDR.Events.Query.short_histogram.alerts + description: The number of alerts associated with the event. + - contextPath: SekoiaXDR.Events.Query.short_histogram.earliest_time + description: The earliest time associated with the event. + - contextPath: SekoiaXDR.Events.Query.short_histogram.length + description: The length of the histogram for the event. + - contextPath: SekoiaXDR.Events.Query.created_by + description: The user who created the event. + - contextPath: SekoiaXDR.Events.Query.expired + description: A boolean indicating whether the event has expired. + - contextPath: SekoiaXDR.Events.Query.latest_time + description: The latest time associated with the event. + - contextPath: SekoiaXDR.Events.Query.expiration_date + description: The date on which the event will expire. + - contextPath: SekoiaXDR.Events.Query.created_at + description: The time at which the event was created. + - contextPath: SekoiaXDR.Events.Query.status + description: The status of the event. + - contextPath: SekoiaXDR.Events.Query.view_uuid + description: The unique identifier for the view associated with the event. + - contextPath: SekoiaXDR.Events.Query.canceled_at + description: The time at which the event was canceled. + - contextPath: SekoiaXDR.Events.Query.only_eternal + description: A boolean indicating whether the event is only eternal. + - contextPath: SekoiaXDR.Events.Query.results_ttl + description: The time-to-live for the event results. + - contextPath: SekoiaXDR.Events.Query.canceled_by + description: The user who canceled the event. + - contextPath: SekoiaXDR.Events.Query.term_lang + description: The language of the search term associated with the event. + - contextPath: SekoiaXDR.Events.Query.ended_at + description: The time at which the event ended. + - contextPath: SekoiaXDR.Events.Query.earliest_time + description: The earliest time associated with the event. + - contextPath: SekoiaXDR.Events.Query.max_last_events + description: The maximum number of events to include in the results. + - contextPath: SekoiaXDR.Events.Query.canceled_by_type + description: The type of the user who canceled the event. + - contextPath: SekoiaXDR.Events.Query.total + description: The total number of events associated with the event. + - contextPath: SekoiaXDR.Events.Query.created_by_type + description: The type of the user who created the event. + - contextPath: SekoiaXDR.Events.Query.community_uuids + description: The list of community UUIDs associated with the event. + - contextPath: SekoiaXDR.Events.Query.filters.field + description: The field associated with the filter. + - contextPath: SekoiaXDR.Events.Query.filters.value + description: The value associated with the filter. + - contextPath: SekoiaXDR.Events.Query.filters.operator + description: The operator used in the filter. + - contextPath: SekoiaXDR.Events.Query.filters.excluded + description: Indicates whether the filter is excluded or not. + - contextPath: SekoiaXDR.Events.Query.filters.disabled + description: Indicates whether the filter is disabled or not. + description: Command to create an event search job on Sekoia XDR, after this execute "sekoia-status-events-query" to see the status of the query job and "sekoia-results-events-query" to retrieve the results.. + - name: sekoia-events-status-query + arguments: + - name: uuid + required: true + description: UUID of the query excuted previously with the "sekoia-query-events" command. + outputs: + - contextPath: SekoiaXDR.Events.Status.uuid + description: The unique identifier for the event. + - contextPath: SekoiaXDR.Events.Status.term + description: The term associated with the event. + - contextPath: SekoiaXDR.Events.Status.started_at + description: The time at which the event started. + - contextPath: SekoiaXDR.Events.Status.short_histogram.cases + description: The number of cases associated with the event. + - contextPath: SekoiaXDR.Events.Status.short_histogram.total + description: The total number of events associated with the event. + - contextPath: SekoiaXDR.Events.Status.short_histogram.alerts + description: The number of alerts associated with the event. + - contextPath: SekoiaXDR.Events.Status.short_histogram.earliest_time + description: The earliest time associated with the event. + - contextPath: SekoiaXDR.Events.Status.short_histogram.length + description: The length associated with the event. + - contextPath: SekoiaXDR.Events.Status.created_by + description: The user who created the event. + - contextPath: SekoiaXDR.Events.Status.expired + description: Whether the event is expired. + - contextPath: SekoiaXDR.Events.Status.latest_time + description: The latest time associated with the event. + - contextPath: SekoiaXDR.Events.Status.expiration_date + description: The date when the event expires. + - contextPath: SekoiaXDR.Events.Status.created_at + description: The time when the event was created. + - contextPath: SekoiaXDR.Events.Status.status + description: The current status of the event. + - contextPath: SekoiaXDR.Events.Status.view_uuid + description: The view associated with the event. + - contextPath: SekoiaXDR.Events.Status.canceled_at + description: The time when the event was canceled. + - contextPath: SekoiaXDR.Events.Status.only_eternal + description: Whether only eternal events are associated with the event. + - contextPath: SekoiaXDR.Events.Status.results_ttl + description: The time-to-live for the event results. + - contextPath: SekoiaXDR.Events.Status.canceled_by + description: The user who canceled the event. + - contextPath: SekoiaXDR.Events.Status.term_lang + description: The language associated with the term for the event. + - contextPath: SekoiaXDR.Events.Status.ended_at + description: The time when the event ended. + - contextPath: SekoiaXDR.Events.Status.earliest_time + description: The earliest time associated with the event. + - contextPath: SekoiaXDR.Events.Status.max_last_events + description: The maximum number of events to retrieve. + - contextPath: SekoiaXDR.Events.Status.canceled_by_type + description: The type of user who canceled the event. + - contextPath: SekoiaXDR.Events.Status.total + description: The total number of events associated with the event. + - contextPath: SekoiaXDR.Events.Status.created_by_type + description: The type of user who created the event. + - contextPath: SekoiaXDR.Events.Status.community_uuids[0] + description: The community associated with the event. + - contextPath: SekoiaXDR.Events.Status.filters.field + description: The field used for filtering events. + - contextPath: SekoiaXDR.Events.Status.filters.field + description: The field used in the filter. + - contextPath: SekoiaXDR.Events.Status.filters.value + description: The value of the filter. + - contextPath: SekoiaXDR.Events.Status.filters.operator + description: The operator used in the filter. + - contextPath: SekoiaXDR.Events.Status.filters.excluded + description: A boolean indicating whether the filter is excluded or not. + - contextPath: SekoiaXDR.Events.Status.filters.disabled + description: A boolean indicating whether the filter is disabled or not. + description: Command to query the status of the search job "sekoia-execute-events-query" previously executed on Sekoia XDR. + - name: sekoia-events-results-query + arguments: + - name: uuid + required: true + description: UUID of the query excuted previously with the "sekoia-query-events" command. + outputs: + - contextPath: SekoiaXDR.Events.Results + description: The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. + description: Command to retrieve the events from the search job "sekoia-execute-events-query" previously done on Sekoia XDR. + - name: sekoia-search-events + arguments: + - name: earliest_time + required: true + description: "Valid expressions: -3d: from three days ago, -2w: from two weeks before now, -7d: seven days before now." + - name: lastest_time + required: true + description: "Valid expressions: +3d: three days in the future, +2w: two weeks in the future, now: current time." + - name: query + required: true + description: 'The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga".' + - name: max_last_events + description: Maximum number of listed events. + - name: exclude_info + auto: PREDEFINED + predefined: + - original.message + - message + - __event_id + - agent.name + - alert_short_ids + - client.address + - client.ip + - client.user.id + - customer.community_name + - customer.community_uuid + - customer.id + - customer.intake_key + - customer.intake_name + - customer.intake_uuid + - ecs.version + - entity.id + - entity.name + - entity.uuid + - event.created + - event.dialect + - event.dialect_uuid + - event.id + - event.outcome + - http.request.method + - http.request.referrer + - related.ip + - sekoiaio.activity.client.id + - sekoiaio.activity.client.type + - sekoiaio.customer.community_name + - sekoiaio.customer.community_uuid + - sekoiaio.customer.id + - sekoiaio.entity.id + - sekoiaio.entity.name + - sekoiaio.entity.uuid + - sekoiaio.intake.dialect + - sekoiaio.intake.dialect_uuid + - sekoiaio.intake.key + - sekoiaio.intake.name + - sekoiaio.intake.parsing_status + - sekoiaio.intake.uuid + - timestamp + - url.domain + - url.original + - url.path + - url.port + - url.query + - url.registered_domain + - url.scheme + - url.subdomain + - url.top_level_domain + - user_agent.original + description: "Indicate if there is any information you want to exclude from the results of the events. i.e: original.message, message, agent.name, etc. This are the names of the headers presented in the table. If is not in the list write it and press enter." + isArray: true + - name: interval_in_seconds + default: true + description: Interval in seconds between each poll. + defaultValue: "2" + - name: timeout_in_seconds + description: Polling timeout in seconds. + defaultValue: "60" + outputs: + - contextPath: SekoiaXDR.Events.Results + description: The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. + description: "Command to search and retrieve the events from an alert. This is a combination of 3 commands: jobquery-events, jobquery-events-status and jobquery-retrieve events." + - name: sekoia-update-status-alert + arguments: + - name: id + required: true + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + - name: status + auto: PREDEFINED + predefined: + - Acknowledged + - Rejected + - Ongoing + - Closed + description: The status you want to apply. (Acknowledged, Rejected, Ongoing, Closed)). + - name: comment + description: A comment to describe why the alert status has changed. + description: Command to update the status of a specific Alert by uuid or short_id. + - name: sekoia-post-comment-alert + arguments: + - name: id + required: true + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + - name: comment + required: true + description: Content of the comment to be posted on the alert. + - name: author + description: Author of the comment. + description: Command to post comments to alerts in Sekoia XDR. + - name: sekoia-get-comments + arguments: + - name: id + required: true + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + outputs: + - contextPath: SekoiaXDR.Comments.total + description: The total number of items in the comments. + - contextPath: SekoiaXDR.Comments.items.date + description: The date at which the comment was created. + - contextPath: SekoiaXDR.Comments.items.created_by + description: The user who created the comment. + - contextPath: SekoiaXDR.Comments.items.uuid + description: The unique identifier for the comment. + - contextPath: SekoiaXDR.Comments.items.content + description: The content of the comment. + - contextPath: SekoiaXDR.Comments.items.created_by_type + description: The type of the user who created the comment. + - contextPath: SekoiaXDR.Comments.items.unseen + description: Indicates whether the comment has been seen by the user. + - contextPath: SekoiaXDR.Comments.items.author + description: The author of the comment. + description: Command to get all the comments from an alert in Sekoia XDR. + - name: sekoia-get-workflow-alert + arguments: + - name: id + required: true + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + outputs: + - contextPath: SekoiaXDR.StatusTransitions.actions.name + description: The name of the action. + - contextPath: SekoiaXDR.StatusTransitions.actions.description + description: The description of the action. + - contextPath: SekoiaXDR.StatusTransitions.actions.id + description: The ID of the action. + description: Command to get the possible transitions of status on the alert. + - name: sekoia-get-cases-alert + arguments: + - name: alert_id + description: 'The uuid or short_id of the alert to retrieve. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga".' + - name: case_id + description: 'The short_id of the case to retrieve. i.e: "CAQNurTJM8q2".' + outputs: + - contextPath: SekoiaXDR.Cases.updated_at + description: The time at which the case was updated. + - contextPath: SekoiaXDR.Cases.updated_by + description: The user who updated the case. + - contextPath: SekoiaXDR.Cases.uuid + description: The unique identifier of the case. + - contextPath: SekoiaXDR.Cases.title + description: The title of the case. + - contextPath: SekoiaXDR.Cases.priority + description: The priority level of the case. + - contextPath: SekoiaXDR.Cases.short_id + description: The short ID of the case. + - contextPath: SekoiaXDR.Cases.community_uuid + description: The unique identifier of the community to which the case belongs. + - contextPath: SekoiaXDR.Cases.updated_by_type + description: The type of user who updated the case. + - contextPath: SekoiaXDR.Cases.first_seen_at + description: The time at which the case was first seen. + - contextPath: SekoiaXDR.Cases.number_of_comments + description: The number of comments on the case. + - contextPath: SekoiaXDR.Cases.alerts.updated_at + description: The time at which the alert was updated. + - contextPath: SekoiaXDR.Cases.alerts.updated_by + description: The user who updated the alert. + - contextPath: SekoiaXDR.Cases.alerts.uuid + description: The unique identifier of the alert. + - contextPath: SekoiaXDR.Cases.alerts.title + description: The title of the alert. + - contextPath: SekoiaXDR.Cases.alerts.time_to_respond + description: The time it took to respond to the alert. + - contextPath: SekoiaXDR.Cases.alerts.short_id + description: The short ID of the alert. + - contextPath: SekoiaXDR.Cases.alerts.community_uuid + description: The unique identifier of the community to which the alert belongs. + - contextPath: SekoiaXDR.Cases.alerts.kill_chain_short_id + description: The short ID of the kill chain. + - contextPath: SekoiaXDR.Cases.alerts.number_of_unseen_comments + description: The number of unseen comments on the alert. + - contextPath: SekoiaXDR.Cases.alerts.updated_by_type + description: The type of user who updated the alert. + - contextPath: SekoiaXDR.Cases.alerts.source + description: The source of the alert. + - contextPath: SekoiaXDR.Cases.alerts.alert_type.value + description: The type of the alert. + - contextPath: SekoiaXDR.Cases.alerts.alert_type.category + description: The category type of the alert. + - contextPath: SekoiaXDR.Cases.alerts.time_to_acknowledge + description: The time it took to acknowledge the alert. + - contextPath: SekoiaXDR.Cases.alerts.stix + description: The STIX data of the alert. + - contextPath: SekoiaXDR.Cases.alerts.first_seen_at + description: The time at which the alert was first seen. + - contextPath: SekoiaXDR.Cases.alerts.ttps.type + description: The type of TTP associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.ttps.name + description: The name of the TTP associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.ttps.id + description: The ID of the TTP associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.ttps.description + description: The description of the TTP associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.adversaries.type + description: The type of adversary associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.adversaries.name + description: The name of the adversary associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.adversaries.id + description: The ID of the adversary associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.adversaries.description + description: The description of the adversary associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.time_to_ingest + description: The time it took to ingest the alert. + - contextPath: SekoiaXDR.Cases.alerts.target + description: The target of the alert. + - contextPath: SekoiaXDR.Cases.alerts.time_to_resolve + description: The time it took to resolve the alert. + - contextPath: SekoiaXDR.Cases.alerts.created_at + description: The time at which the alert was created. + - contextPath: SekoiaXDR.Cases.alerts.last_seen_at + description: The time at which the alert was last seen. + - contextPath: SekoiaXDR.Cases.alerts.assets + description: The assets associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.severity + description: The severity level of the rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.type + description: The type of rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.uuid + description: The unique identifier of the rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.name + description: The name of the rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.description + description: The description of the rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.rule.pattern + description: The pattern of the rule associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.similar + description: The number of similar alerts. + - contextPath: SekoiaXDR.Cases.alerts.status.name + description: The name of the status of the alert. + - contextPath: SekoiaXDR.Cases.alerts.status.description + description: The description of the status of the alert. + - contextPath: SekoiaXDR.Cases.alerts.status.uuid + description: The unique identifier of the status of the alert. + - contextPath: SekoiaXDR.Cases.alerts.urgency.criticity + description: The level of criticality of the urgency of the alert. + - contextPath: SekoiaXDR.Cases.alerts.urgency.current_value + description: The current value of the urgency of the alert. + - contextPath: SekoiaXDR.Cases.alerts.urgency.severity + description: The severity level of the urgency of the alert. + - contextPath: SekoiaXDR.Cases.alerts.urgency.display + description: The display value of the urgency of the alert. + - contextPath: SekoiaXDR.Cases.alerts.urgency.value + description: The value of the urgency of the alert. + - contextPath: SekoiaXDR.Cases.alerts.created_by + description: The user who created the alert. + - contextPath: SekoiaXDR.Cases.alerts.number_of_total_comments + description: The total number of comments on the alert. + - contextPath: SekoiaXDR.Cases.alerts.time_to_detect + description: The time it took to detect the alert. + - contextPath: SekoiaXDR.Cases.alerts.entity.name + description: The name of the entity associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.entity.uuid + description: The unique identifier of the entity associated with the alert. + - contextPath: SekoiaXDR.Cases.alerts.created_by_type + description: The type of user who created the alert. + - contextPath: SekoiaXDR.Cases.alerts.details + description: The details of the alert. + - contextPath: SekoiaXDR.Cases.number_of_alerts + description: The number of alerts in the case. + - contextPath: SekoiaXDR.Cases.created_at + description: The time at which the case was created. + - contextPath: SekoiaXDR.Cases.last_seen_at + description: The time at which the case was last seen. + - contextPath: SekoiaXDR.Cases.status + description: The status of the case. + - contextPath: SekoiaXDR.Cases.description + description: The description of the case. + - contextPath: SekoiaXDR.Cases.status_uuid + description: The unique identifier of the status of the case. + - contextPath: SekoiaXDR.Cases.created_by + description: The user who created the case. + - contextPath: SekoiaXDR.Cases.tags + description: The tags associated with the case. + - contextPath: SekoiaXDR.Cases.created_by_type + description: The type of user who created the case. + - contextPath: SekoiaXDR.Cases.subscribers.avatar_uuid + description: The unique identifier of the avatar of the subscriber. + - contextPath: SekoiaXDR.Cases.subscribers.type + description: The type of subscriber. + description: Command to retrieve the case related to an Alert from Sekoia XDR. + - name: sekoia-get-asset + arguments: + - name: asset_uuid + required: true + description: 'UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a".' + outputs: + - contextPath: SekoiaXDR.Asset.owners + description: The owners of the asset. + - contextPath: SekoiaXDR.Asset.category.types.description + description: The description of the category type of the asset. + - contextPath: SekoiaXDR.Asset.category.types.name + description: The name of the category type of the asset. + - contextPath: SekoiaXDR.Asset.category.types.uuid + description: The UUID of the category type of the asset. + - contextPath: SekoiaXDR.Asset.category.description + description: The description of the category of the asset. + - contextPath: SekoiaXDR.Asset.category.name + description: The name of the category of the asset. + - contextPath: SekoiaXDR.Asset.category.uuid + description: The UUID of the category of the asset. + - contextPath: SekoiaXDR.Asset.created_at + description: The time at which the asset was created. + - contextPath: SekoiaXDR.Asset.keys.value + description: The value of the keys of the asset. + - contextPath: SekoiaXDR.Asset.keys.name + description: The name of the keys of the asset. + - contextPath: SekoiaXDR.Asset.keys.uuid + description: The UUID of the keys of the asset. + - contextPath: SekoiaXDR.Asset.attributes.value + description: The value of the attributes of the asset. + - contextPath: SekoiaXDR.Asset.attributes.name + description: The name of the attributes of the asset. + - contextPath: SekoiaXDR.Asset.attributes.uuid + description: The UUID of the attributes of the asset. + - contextPath: SekoiaXDR.Asset.updated_at + description: The time at which the asset was updated. + - contextPath: SekoiaXDR.Asset.asset_type.description + description: The description of the asset type. + - contextPath: SekoiaXDR.Asset.asset_type.name + description: The name of the asset type. + - contextPath: SekoiaXDR.Asset.asset_type.uuid + description: The UUID of the asset type. + - contextPath: SekoiaXDR.Asset.criticity.value + description: The criticality value of the asset. + - contextPath: SekoiaXDR.Asset.criticity.display + description: The display value of the criticality of the asset. + - contextPath: SekoiaXDR.Asset.description + description: The description of the asset. + - contextPath: SekoiaXDR.Asset.community_uuid + description: The UUID of the community of the asset. + - contextPath: SekoiaXDR.Asset.name + description: The name of the asset. + - contextPath: SekoiaXDR.Asset.uuid + description: The UUID of the asset. + description: Get an asset by its UUID from Sekoia XDR. + - name: get-remote-data + arguments: + - name: id + description: The remote alert ID. + - name: lastUpdate + description: ISO format date with timezone, e.g., 2023-03-01T16:41:30.589575+02:00. The incident is only updated if it was modified after the last update time. + defaultValue: "0" + description: This command gets new information about the incidents in the remote system and updates existing incidents in Cortex XSOAR. + - name: get-modified-remote-data + arguments: + - name: lastUpdate + description: ISO format date with timezone, e.g., 2023-03-01T16:41:30.589575+02:00. The incident is only returned if it was modified after the last update time. + defaultValue: "0" + description: available from Cortex XSOAR version 6.1.0. This command queries for incidents that were modified since the last update. + - name: sekoia-list-assets + arguments: + - name: limit + description: Limit a number of items. + defaultValue: "10" + - name: assets_type + description: Type of assets to list (computer, network, etc). + outputs: + - contextPath: SekoiaXDR.Assets.total + description: The total number of items in the response. + - contextPath: SekoiaXDR.Assets.items.0.owners.0 + description: The ID of the owner of the asset. + - contextPath: SekoiaXDR.Assets.items.0.category.types.0.description + description: The description of the type of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.category.types.0.name + description: The name of the type of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.category.types.0.uuid + description: The UUID of the type of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.category.description + description: The description of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.category.name + description: The name of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.category.uuid + description: The UUID of the asset category. + - contextPath: SekoiaXDR.Assets.items.0.created_at + description: The time at which the asset was created. + - contextPath: SekoiaXDR.Assets.items.0.keys.0.value + description: The value of the asset key. + - contextPath: SekoiaXDR.Assets.items.0.keys.0.name + description: The name of the asset key. + - contextPath: SekoiaXDR.Assets.items.0.keys.0.uuid + description: The UUID of the asset key. + - contextPath: SekoiaXDR.Assets.items.0.attributes.0.value + description: The value of the asset attribute. + - contextPath: SekoiaXDR.Assets.items.0.attributes.0.name + description: The name of the asset attribute. + - contextPath: SekoiaXDR.Assets.items.0.attributes.0.uuid + description: The UUID of the asset attribute. + - contextPath: SekoiaXDR.Assets.items.0.updated_at + description: The time at which the asset was last updated. + - contextPath: SekoiaXDR.Assets.items.0.asset_type.description + description: The description of the asset type. + - contextPath: SekoiaXDR.Assets.items.0.asset_type.name + description: The name of the asset type. + - contextPath: SekoiaXDR.Assets.items.0.asset_type.uuid + description: The UUID of the asset type. + - contextPath: SekoiaXDR.Assets.items.0.criticity.value + description: The numeric value of the asset criticality. + - contextPath: SekoiaXDR.Assets.items.0.criticity.display + description: The display value of the asset criticality. + - contextPath: SekoiaXDR.Assets.items.0.description + description: The description of the asset. + - contextPath: SekoiaXDR.Assets.items.0.community_uuid + description: The UUID of the community to which the asset belongs. + - contextPath: SekoiaXDR.Assets.items.0.name + description: The name of the asset. + - contextPath: SekoiaXDR.Assets.items.0.uuid + description: The UUID of the asset. + description: Command to retrieve a list of Assets from Sekoia XDR. + - name: sekoia-get-user + arguments: + - name: user_uuid + required: true + description: UUID of the user to obtain the information from. + outputs: + - contextPath: SekoiaXDR.User.creator.description + description: The description of the creator. + - contextPath: SekoiaXDR.User.creator.name + description: The name of the creator. + - contextPath: SekoiaXDR.User.creator.uuid + description: The UUID of the creator. + - contextPath: SekoiaXDR.User.updated_at + description: The time at which the object was last updated. + - contextPath: SekoiaXDR.User.created_by + description: The UUID of the user who created the object. + - contextPath: SekoiaXDR.User.total_members + description: The total number of members in the community. + - contextPath: SekoiaXDR.User.subcommunities + description: The UUIDs of the subcommunities. + - contextPath: SekoiaXDR.User.parent_community_uuid + description: The UUID of the parent community. + - contextPath: SekoiaXDR.User.applications.description + description: The description of the application. + - contextPath: SekoiaXDR.User.applications.name + description: The name of the application. + - contextPath: SekoiaXDR.User.applications.uuid + description: The UUID of the application. + - contextPath: SekoiaXDR.User.is_parent + description: Whether the community is a parent community. + - contextPath: SekoiaXDR.User.name + description: The name of the community. + - contextPath: SekoiaXDR.User.members.uuid + description: The UUID of the member. + - contextPath: SekoiaXDR.User.members.created_at + description: The time at which the member was created. + - contextPath: SekoiaXDR.User.members.user.firstname + description: The first name of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.mfa_enabled + description: Whether multi-factor authentication is enabled for the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.uuid + description: The UUID of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.company_name + description: The company name of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.lastname + description: The last name of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.created_at + description: The time at which the user associated with the member was created. + - contextPath: SekoiaXDR.User.members.user.picture_mode + description: The picture mode of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.last_activity + description: The last activity time of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.updated_at + description: The time at which the user associated with the member was last updated. + - contextPath: SekoiaXDR.User.members.user.auth_provider + description: The authentication provider of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.email + description: The email address of the user associated with the member. + - contextPath: SekoiaXDR.User.members.user.invitation_v2.email + description: The email address for the invitation associated with the user associated with the member. + - contextPath: SekoiaXDR.User.members.name + description: The name of the member. + - contextPath: SekoiaXDR.User.members.updated_at + description: The time at which the member was last updated. + - contextPath: SekoiaXDR.User.members.status_changed_at + description: The time at which the status of the member was last changed. + - contextPath: SekoiaXDR.User.members.status + description: The status of the member. + - contextPath: SekoiaXDR.User.session_timeout + description: The session timeout for the community. + - contextPath: SekoiaXDR.User.is_mfa_enforced + description: Whether multi-factor authentication is enforced for the community. + - contextPath: SekoiaXDR.User.uuid + description: The UUID of the community. + - contextPath: SekoiaXDR.User.created_at + description: The time at which the community was created. + - contextPath: SekoiaXDR.User.picture_mode + description: The picture mode for the community. + - contextPath: SekoiaXDR.User.homepage_url + description: The homepage URL for the community. + - contextPath: SekoiaXDR.User.created_by_type + description: The type of the user who created the community. + - contextPath: SekoiaXDR.User.disable_inactive_avatars + description: Whether inactive avatars are disabled for the community. + - contextPath: SekoiaXDR.User.description + description: The description of the community. + description: Command to get information about a user in Sekoia XDR. Used also in the command !sekoia-get-comments to have the name of the persons who made the comments. + - name: sekoia-add-attributes-asset + arguments: + - name: asset_uuid + required: true + description: 'UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a".' + - name: name + required: true + description: The name of attributes. + - name: value + required: true + description: The value of attributes. + description: Command to add attributes to an asset in Sekoia XDR. + - name: sekoia-add-keys-asset + arguments: + - name: asset_uuid + required: true + description: 'UUID of the asset to get, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a".' + - name: name + required: true + description: The name of the key to be added. + - name: value + required: true + description: The value of the key to be added. + description: Command to add keys to an asset in Sekoia XDR. + - name: sekoia-get-kill-chain + arguments: + - name: kill_chain_uuid + required: true + description: UUID or short_id of the kill chain. + outputs: + - contextPath: SekoiaXDR.KillChain.stix_name + description: The name of the STIX object. + - contextPath: SekoiaXDR.KillChain.description + description: The description of the STIX object. + - contextPath: SekoiaXDR.KillChain.name + description: The common name of the STIX object. + - contextPath: SekoiaXDR.KillChain.uuid + description: The unique identifier of the STIX object. + - contextPath: SekoiaXDR.KillChain.short_id + description: The short identifier of the STIX object. + - contextPath: SekoiaXDR.KillChain.order_id + description: The order identifier of the STIX object. + description: Command to retrieve the definition of a Cyber Kill Chain Step. + - name: update-remote-system + arguments: [] + description: Pushes local changes to the remote system. + - name: get-mapping-fields + arguments: [] + description: This command pulls the remote schema for the different incident types, and their associated incident fields, from the remote system. + - name: sekoia-remove-attribute-asset + arguments: + - name: asset_uuid + required: true + description: 'UUID of the asset, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a".' + - name: attribute_uuid + required: true + description: "UUID of the attribute to delete. Note: use !sekoia-get-asset to find the attribute_uuid to delete." + description: "Command to remove an attribute from an asset in Sekoia XDR. Note: use !sekoia-get-asset to find the attribute_uuid to delete." + - name: sekoia-remove-key-asset + arguments: + - name: asset_uuid + required: true + description: 'UUID of the asset, the UUID should appear with "sekoia-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a".' + - name: key_uuid + required: true + description: "UUID of the key to remove. Note: use !sekoia-get-asset to find the key_uuid to delete." + description: "Command to remove an attribute from an asset in Sekoia XDR. Note: use !sekoia-get-asset to find the key_uuid to delete." + - name: sekoia-http-request + arguments: + - name: method + required: true + description: Method to use with the http request (GET,POST,etc). + defaultValue: GET + - name: url_sufix + required: true + description: "The URL sufix after https://api.sekoia.io/v1, i.e. /sic/alerts/ or /asset-management/assets/." + - name: parameters + description: Query parameters, i.e. limit -> 10 , match['status_name'] -> Ongoing. + type: keyValue + description: Command that performs a HTTP request to Sekoia using the integration authentication configured. + dockerimage: demisto/python3:3.10.13.83255 + isfetch: true + runonce: false + subtype: python3 + ismappable: true + isremotesyncin: true + isremotesyncout: true + isFetchSamples: true +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_description.md b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_description.md new file mode 100644 index 000000000000..ae90a086389a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_description.md @@ -0,0 +1,12 @@ +## SEKOIA.IO XDR ( Operation Center ) +This section explains how to configure the instance of SEKOIA.IO XDR in Cortex XSOAR. + +### API Key +Much like any other API, Sekoio's API relies on an authentication mechanism, utilizing an API key for authentication. Obtaining one requires following a series of simple steps : + +- Click on **settings** ( Look on the navbar bottom ) +- On **Workspace** part, click on **API keys** +- Click on the + API key button +- Give a name and a description to your key (description should be more than 10 characters and less than 100 characters) +- Select one or more roles to associate with your key. +- Click on Save \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_image.png b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_image.png new file mode 100644 index 000000000000..f4786f782033 Binary files /dev/null and b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_image.png differ diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py new file mode 100644 index 000000000000..1325de58dc95 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py @@ -0,0 +1,474 @@ +from CommonServerPython import * + +import SekoiaXDR + +from datetime import datetime +import pytest +import os +import json + + +MOCK_URL = "https://api.sekoia.io" + + +def util_load_json(path): + with open(path, encoding="utf-8") as f: + return json.loads(f.read()) + + +@pytest.fixture(scope="session") +def client(): + api_key = os.environ.get("SEKOIAIO_APIKEY", "aa") + headers = {"Authorization": f"Bearer {api_key}"} + client = SekoiaXDR.Client( + base_url=MOCK_URL, + headers=headers, + ) + return client + + +""" TEST HELPER FUNCTIONS """ + + +def test_arg_to_timestamp(): + assert ( + SekoiaXDR.arg_to_timestamp("2024-04-25T09:20:55", "lastupdate", True) + == 1714036855 + ) + assert SekoiaXDR.arg_to_timestamp(1714036855.55, "lastupdate", True) == 1714036855 + + three_days_ago = datetime.now() - timedelta(days=3) + assert SekoiaXDR.arg_to_timestamp("3 days", "lastupdate", True) == int( + three_days_ago.timestamp() + ) + + with pytest.raises(ValueError): + assert SekoiaXDR.arg_to_timestamp(None, "lastupdate", True) == 1714036855 + + +def test_timezone_format(): + assert SekoiaXDR.timezone_format(1714036855) == "2024-04-25T09:20:55" + assert SekoiaXDR.timezone_format(1710494455) == "2024-03-15T09:20:55" + assert SekoiaXDR.timezone_format(1678872055) == "2023-03-15T09:20:55" + + +def test_time_converter(): + assert ( + SekoiaXDR.time_converter("2024-04-20T15:30:00+00:00") == "2024-04-20T15:30:00" + ) + assert SekoiaXDR.time_converter("1678872055") == "2023-03-15T09:20:55" + with pytest.raises(ValueError): + assert SekoiaXDR.time_converter("2024-04-20T15:30:00") == "2024-04-20T15:30:00" + + +def test_convert_to_demisto_severity(): + assert SekoiaXDR.convert_to_demisto_severity("Low") == 1 + assert SekoiaXDR.convert_to_demisto_severity("Moderate") == 2 + assert SekoiaXDR.convert_to_demisto_severity("High") == 3 + assert SekoiaXDR.convert_to_demisto_severity("Major") == 3 + assert SekoiaXDR.convert_to_demisto_severity("Urgent") == 4 + + +def test_exclude_info_events(): + upload_test_data = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + + result = SekoiaXDR.exclude_info_events(upload_test_data, "sekoiaio.any_asset.name") + assert "sekoiaio.any_asset.name" not in result + + second_result = SekoiaXDR.exclude_info_events( + upload_test_data, "sekoiaio.tags.related.ip,sekoiaio.tags.host.ip" + ) + assert "sekoiaio.tags.related.ip" not in second_result + assert "sekoiaio.tags.host.ip" not in second_result + + +def test_undot(): + upload_test_data = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + result = SekoiaXDR.undot(upload_test_data) + + assert "agent_id" in result + assert "agent.id" not in result + + +""" TEST COMMANDS FUNCTIONS """ + + +def test_test_module_ok(client, requests_mock): + response = { + "csrf": "aaa", + "fresh": False, + "iat": 123456, + "identity": "apikey:123456", + "jti": "123456", + "nbf": 123456, + "type": "access", + "user_claims": None, + } + + requests_mock.get(MOCK_URL + "/v1/auth/validate", json=response) + assert SekoiaXDR.test_module(client) == "ok" + + +@pytest.mark.parametrize( + "api_response, expected", + [ + ({"message": "The token is invalid", "code": "T300"}, "The token is invalid."), + ( + {"message": "The token has expired", "code": "T301"}, + "The token has expired.", + ), + ({"message": "Token revoked", "code": "T302"}, "The token has been revoked."), + ], +) +def test_test_module_nok(client, requests_mock, api_response, expected): + requests_mock.get( + MOCK_URL + "/v1/auth/validate", json=api_response, status_code=401 + ) + + assert expected in SekoiaXDR.test_module(client) + + +# Skipped if there's no SEKOIA.IO API_KEY +@pytest.mark.skipif("{'SEKOIAIO_APIKEY'}.issubset(os.environ.keys()) == False") +def test_get_validate_resource_with_credentials(client): + result = client.get_validate_resource() + + assert result == "ok" + + +@pytest.mark.parametrize( + "method, url_suffix, params, json_test_file", + [ + ("GET", "/v1/sic/alerts", {}, "test_data/SekoiaXDR_get_alerts.json"), + ( + "GET", + "/v1/asset-management/assets", + {}, + "test_data/SekoiaXDR_get_assets.json", + ), + ], +) +def test_http_request_list( + client, requests_mock, method, url_suffix, params, json_test_file +): + mock_response = util_load_json(json_test_file) + requests_mock.get(MOCK_URL + url_suffix, json=mock_response) + + args = {"url_sufix": url_suffix, "method": method, "params": params} + result = SekoiaXDR.http_request_command(client=client, args=args) + + assert result.outputs["items"] == mock_response["items"] + + +# Skipped if there's no SEKOIA.IO API_KEY +@pytest.mark.skipif("{'SEKOIAIO_APIKEY'}.issubset(os.environ.keys()) == False") +def test_http_request_list_with_credentials(client): + args = {"url_sufix": "/v1/sic/conf/alerts", "method": "GET", "params": {}} + result = SekoiaXDR.http_request_command(client=client, args=args) + + assert result.outputs["items"] != [] + + +def test_list_alerts(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alerts.json") + requests_mock.get(MOCK_URL + "/v1/sic/alerts", json=mock_response) + + args = {} + result = SekoiaXDR.list_alerts_command(client=client, args=args) + + assert result.outputs == mock_response["items"] + + +# Skipped if there's no SEKOIA.IO API_KEY +@pytest.mark.skipif("{'SEKOIAIO_APIKEY'}.issubset(os.environ.keys()) == False") +def test_list_alerts_with_credentials(client): + result = SekoiaXDR.list_alerts_command(client=client, args={}) + + assert result.outputs != [] + + +def test_get_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert.json") + requests_mock.get(MOCK_URL + "/v1/sic/alerts/ALL1A4SKUiU2", json=mock_response) + + args = {"id": "ALL1A4SKUiU2"} + result = SekoiaXDR.get_alert_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_get_workflow_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_workflow.json") + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json=mock_response + ) + + args = {"id": "ALWVYiP2Msz4"} + result = SekoiaXDR.get_workflow_alert_command(client=client, args=args) + + assert len(result.outputs) == len(mock_response["actions"]) + + +def test_get_cases_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_cases.json") + requests_mock.get( + MOCK_URL + + "/v1/sic/cases?match[alert_uuid]=4fb686e0-ab0c-479c-9afe-856beef9d592&match[short_id]=CAs3AT1XeGCp", + json=mock_response, + ) + + args = { + "alert_id": "4fb686e0-ab0c-479c-9afe-856beef9d592", + "case_id": "CAs3AT1XeGCp", + } + result = SekoiaXDR.get_cases_alert_command(client=client, args=args) + + assert len(result.outputs) > 0 + + +def test_update_status_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_workflow.json") + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json=mock_response + ) + requests_mock.patch(MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json={}) + + args = {"id": "ALWVYiP2Msz4", "status": "Acknowledged", "comment": "test cortex"} + result = SekoiaXDR.update_status_alert_command(client=client, args=args) + + assert result.outputs == {} + + +def test_comments_alert_command(client, requests_mock): + mock_response_alert_comments = util_load_json( + "test_data/SekoiaXDR_get_alert_comments.json" + ) + mock_response_user = util_load_json("test_data/SekoiaXDR_get_user.json") + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALL1A4SKUiU2/comments", + json=mock_response_alert_comments, + ) + requests_mock.get( + MOCK_URL + "/v1/users/7114c307-d86c-4c55", json=mock_response_user + ) + + args = {"id": "ALL1A4SKUiU2"} + result = SekoiaXDR.get_comments_alert_command(client=client, args=args) + + for item in result.outputs: + if item["author"].startswith("user"): + assert item["user"] == "Joe done" + if item["author"].startswith("apikey"): + assert item["user"] == "Commented via API" + if item["author"].startswith("application"): + assert item["user"] == "Sekoia.io" + + +def test_post_comment_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_alert_comment.json") + requests_mock.post( + MOCK_URL + "/v1/sic/alerts/ALU9FpFZoApW/comments", json=mock_response + ) + + args = { + "id": "ALU9FpFZoApW", + "comment": "This alert is always on ongoing status", + "author": "Joe", + } + result = SekoiaXDR.post_comment_alert_command(client=client, args=args) + assert result.outputs["author"] == args["author"] + assert result.outputs["content"] == args["comment"] + + +def kill_chain_command(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_killchain.json") + requests_mock.post( + MOCK_URL + "/v1/sic/kill-chains/73708d4f-419f-44aa", json=mock_response + ) + + args = {"kill_chain_uuid": "73708d4f-419f-44aa"} + result = SekoiaXDR.get_kill_chain_command(client=client, args=args) + assert result.outputs["uuid"] == args["73708d4f-419f-44aa"] + + +def test_query_events(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_query_events.json") + requests_mock.post(MOCK_URL + "/v1/sic/conf/events/search/jobs", json=mock_response) + + args = { + "query": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "earliest_time": "2024-04-25T10:00:23", + "lastest_time": "2024-04-25T15:00:23", + } + result = SekoiaXDR.query_events_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_query_events_status(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_query_events_status.json") + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f", + json=mock_response, + ) + + args = {"uuid": "df904d2e-2c57-488f"} + result = SekoiaXDR.query_events_status_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_retrieve_events(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f/events", + json=mock_response, + ) + + args = {"uuid": "df904d2e-2c57-488f"} + result = SekoiaXDR.retrieve_events_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_search_events(client, requests_mock, mocker): + mock_response_query_events = util_load_json("test_data/SekoiaXDR_query_events.json") + mock_response_query_events_status = util_load_json( + "test_data/SekoiaXDR_query_events_status.json" + ) + mock_response_retrieve_events = util_load_json( + "test_data/SekoiaXDR_retrieve_events.json" + ) + requests_mock.post( + MOCK_URL + "/v1/sic/conf/events/search/jobs", json=mock_response_query_events + ) + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f", + json=mock_response_query_events_status, + ) + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f/events", + json=mock_response_retrieve_events, + ) + + params = {"exclude_info_events": "False", "replace_dots_event": "_"} + mocker.patch.object(demisto, "params", return_value=params) + args = { + "earliest_time": "2024-04-25T10:00:23", + "lastest_time": "2024-04-25T15:00:23", + "query": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "max_last_events": "100", + "timeout_in_seconds": "5", + "exclude_info": "False", + } + result = SekoiaXDR.search_events_command(client=client, args=args) + + assert result.outputs[0]["action_id"] + assert result.outputs[0]["action_outcome"] + assert result.outputs[0]["action_name"] + + +def test_list_assets(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_list_assets.json") + requests_mock.get( + MOCK_URL + "/v1/asset-management/assets?limit=5&match[type_name]=computer", + json=mock_response, + ) + + args = {"limit": "5", "assets_type": "computer"} + result = SekoiaXDR.list_asset_command(client=client, args=args) + + assert len(result.outputs) == 2 + + +def test_get_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_asset.json") + requests_mock.get( + MOCK_URL + "/v1/asset-management/assets/015ea33b-a7a2-4e34", json=mock_response + ) + + args = {"asset_uuid": "015ea33b-a7a2-4e34"} + result = SekoiaXDR.get_asset_command(client=client, args=args) + + assert result.outputs["uuid"] == args["asset_uuid"] + + +def test_add_keys_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_asset_key.json") + requests_mock.post( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/keys?name=host&value=computer1", + json=mock_response, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "name": "host", + "value": "computer1", + } + result = SekoiaXDR.add_keys_asset_command(client=client, args=args) + + assert result.outputs["name"] == args["name"] + assert result.outputs["value"] == args["value"] + + +def test_remove_keys_asset(client, requests_mock): + requests_mock.delete( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/keys/8007222c-f135-4f5f", + json={}, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "key_uuid": "8007222c-f135-4f5f", + } + result = SekoiaXDR.remove_key_asset_command(client=client, args=args) + + assert not result.outputs + + +def test_add_attr_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_asset_attr.json") + requests_mock.post( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/attr?name=attr_test_4&value=value4", + json=mock_response, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "name": "attr_test_4", + "value": "value4", + } + result = SekoiaXDR.add_attributes_asset_command(client=client, args=args) + + assert result.outputs["name"] == args["name"] + assert result.outputs["value"] == args["value"] + + +def test_remove_attr_asset(client, requests_mock): + requests_mock.delete( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/attr/8007222c-f135-4f5f", + json={}, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "attribute_uuid": "8007222c-f135-4f5f", + } + result = SekoiaXDR.remove_attribute_asset_command(client=client, args=args) + + assert not result.outputs + + +def test_get_user(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_user.json") + requests_mock.get(MOCK_URL + "/v1/users/7114c307-d86c-4c55", json=mock_response) + + args = {"user_uuid": "7114c307-d86c-4c55"} + result = SekoiaXDR.get_user_command(client=client, args=args) + + assert result.outputs["firstname"] == "Joe" + assert result.outputs["lastname"] == "done" diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_examples b/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_examples new file mode 100644 index 000000000000..fa7244d5abc2 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_examples @@ -0,0 +1,19 @@ +!sekoia-list-assets limit=5 assets_type="computer" +!sekoia-get-asset asset_uuid="e553efc7-ab91-48f6-8c79-efd18ada9916" +!sekoia-add-attributes-asset asset_uuid="e553efc7-ab91-48f6-8c79-efd18ada9916" name="Test" value="Test2" +!sekoia-remove-attribute-asset asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 attribute_uuid=95733049-4ffb-434e-9036-742a01871fc4 +!sekoia-add-keys-asset asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 name="MyKey" value="MyValue" +!sekoia-remove-key-asset key_uuid=32dc9f1d-0e7b-4550-a042-eeb52c4a537e asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 +!sekoia-events-execute-query earliest_time=-1d lastest_time=+1d query=alert_short_ids:ALUnyZCYZ9Ga +!sekoia-events-status-query uuid=127@cd3435a4-5937-46ed-8163-ffdd5e7ab95b +!sekoia-events-results-query uuid=127@cd3435a4-5937-46ed-8163-ffdd5e7ab95b +!sekoia-search-events earliest_time=-1d lastest_time=+1d query=alert_short_ids:ALVDPAcN6MYo +!sekoia-list-alerts limit="5" sort_by="created_at" +!sekoia-get-alert id=AL3qRBWfoveP +!sekoia-get-workflow-alert id=AL3qRBWfoveP +!sekoia-update-status-alert id=50314bd2-5493-4518-a242-71d405877e22 +!sekoia-get-cases-alert +!sekoia-get-kill-chain kill_chain_uuid=KCYDJkEpzMot +!sekoia-get-comments id=d444aa87-1408-49d0-9946-86bbc8d740f3 +!sekoia-get-user user_uuid=b57d2513-7037-4fe3-b1f7-9126e52dcc32 +!sekoia-http-request method=GET url_sufix=/sic/alerts/ diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json new file mode 100644 index 000000000000..5736ce565d78 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json @@ -0,0 +1,356 @@ +{ + "uuid": "80ee2ccc-11e3-4416", + "title": "Feed Enriched", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958505, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALL1A4SKUiU2", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology test" + }, + "urgency": { + "current_value": 20, + "value": 20, + "severity": 40, + "criticity": 0, + "display": "Moderate" + }, + "alert_type": { + "value": "brute-force", + "category": "intrusion-attempts" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "ebcb5113-dcd1-4563", + "name": "Feed Enriched", + "description": "description test", + "severity": 40, + "type": null, + "pattern": "[ipv4-addr:value = '1.2.3.4']" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": null, + "similar": 11, + "details": "details description", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": "KCXKNfnJuUUU", + "number_of_unseen_comments": 0, + "first_seen_at": "2019-11-21T13:32:39.839600Z", + "last_seen_at": null, + "assets": [], + "time_to_detect": null, + "time_to_acknowledge": 113615345, + "time_to_respond": null, + "time_to_resolve": 111893849, + "comments": [ + { + "uuid": "40528f74-2523-428f", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c00", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + } + ], + "history": [ + { + "uuid": "be86c882-7ca2-4d23", + "created_at": 1713431780, + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "entry_type": "comment", + "comment": { + "uuid": "5661ca10-33cf-4b49", + "status": "created", + "display_name": "apikey:f870d496-a37b-4aec", + "content": "Alert has been closed automatically" + }, + "history_comments": [] + }, + { + "uuid": "bcf71278-6dd4-41b7", + "created_at": 1687958505, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "alert", + "alert": { + "status": "Acknowledged", + "previous_status": "Closed" + }, + "history_comments": [] + }, + { + "uuid": "792d6585-61b3-4da4", + "created_at": 1686237009, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "entry_type": "alert", + "alert": { + "status": "Closed", + "previous_status": "Pending" + }, + "history_comments": [ + { + "uuid": "40528f74-2523-428f-adb9-b1b3da5b3bcc", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c95-ab31-40f1e9aea5a4", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95-ab31-40f1e9aea5a4", + "created_by_type": "apikey" + } + ] + }, + { + "uuid": "400e4f8f-9473-41c0", + "created_at": 1574343164, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "alert", + "alert": { + "status": "Pending", + "previous_status": null + }, + "history_comments": [] + }, + { + "uuid": "94589f34-9c01-4592", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure_action_step", + "countermeasure": { + "uuid": "43caf7af-06ff-4821", + "status": "created" + }, + "history_comments": [], + "countermeasure_action_step": { + "status": "created", + "name": "1" + } + }, + { + "uuid": "f143ebf4-d3e1-4930", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure", + "countermeasure": { + "uuid": "9f2a40ae-add5-49f8", + "status": "created" + }, + "history_comments": [] + }, + { + "uuid": "b77f2a3e-fd30-43be", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure_action_step", + "countermeasure": { + "uuid": "9f2a40ae-add5-49f8", + "status": "created" + }, + "history_comments": [], + "countermeasure_action_step": { + "status": "created", + "name": "3" + } + }, + { + "uuid": "8c22657d-4d55-4842", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure", + "countermeasure": { + "uuid": "43caf7af-06ff-4821", + "status": "created" + }, + "history_comments": [] + } + ], + "countermeasures": [ + { + "uuid": "43caf7af-06ff-4821-9770-2023c16153f7", + "model_uuid": "55117974-f59e-46df", + "relevance": 50, + "dynamic_relevance": 0, + "duration": null, + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "course_of_action": { + "id": "course-of-action--43caf7af-06ff", + "type": "course-of-action", + "created_by_ref": "identity--59899459-d385", + "created": "2019-11-21T13:32:39.839600+00:00", + "name": "countermeasure--55117974-f59e", + "description": "Report the issue to security team", + "action-steps": [ + { + "name": "1", + "description": "Notify the security team", + "type": "openc2", + "object": { + "action": "investigate", + "target": { + "uri": "$ALERT_URI" + } + } + } + ], + "x_sic_countermeasure": { + "relevance": 50, + "dynamic_relevance": 0, + "uuid": "55117974-f59e-46df" + }, + "modified": "2019-11-21T13:32:39.839600+00:00" + }, + "action_steps": [ + { + "uuid": "1aacb24b-7ec6-41c5", + "name": "1", + "description": "Notify the security team", + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "action_order": 0, + "object": { + "action": "investigate", + "target": { + "uri": "$ALERT_URI" + } + }, + "comments": [], + "assignee": null, + "type": null + } + ], + "name": "countermeasure--55117974-f59e", + "description": "Report the issue to security team", + "comments": [], + "assignee": null, + "type": "openc2", + "external_ref": null, + "alert_uuid": "80ee2ccc-11e3-4416" + }, + { + "uuid": "9f2a40ae-add5-49f8", + "model_uuid": "7d2bb069-b3ff-40ca", + "relevance": 76, + "dynamic_relevance": 0, + "duration": null, + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "course_of_action": { + "id": "course-of-action--9f2a40ae-add5", + "type": "course-of-action", + "created_by_ref": "identity--59899459-d385a", + "created": "2019-11-21T13:32:39.839600+00:00", + "name": "countermeasure--7d2bb069-b3ff", + "description": "Temporarily block the concerned system", + "action-steps": [ + { + "name": "3", + "description": "Block the IP address temporarily", + "type": "openc2", + "object": { + "action": "deny", + "target": { + "ipv4_net": "1.2.3.4" + }, + "actuator": { + "slpf": {} + }, + "args": { + "duration": 7800000000 + } + } + } + ], + "x_sic_countermeasure": { + "relevance": 76, + "dynamic_relevance": 0, + "uuid": "7d2bb069-b3ff-40ca" + }, + "modified": "2019-11-21T13:32:39.839600+00:00" + }, + "action_steps": [ + { + "uuid": "905e5315-a3a9-4efd", + "name": "3", + "description": "Block the IP address temporarily", + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "action_order": 0, + "object": { + "action": "deny", + "target": { + "ipv4_net": "1.2.3.4" + }, + "actuator": { + "slpf": {} + }, + "args": { + "duration": 7800000000 + } + }, + "comments": [], + "assignee": null, + "type": null + } + ], + "name": "countermeasure--7d2bb069-b3ff", + "description": "Temporarily block the concerned system", + "comments": [], + "assignee": null, + "type": "openc2", + "external_ref": null, + "alert_uuid": "80ee2ccc-11e3-4416" + } + ], + "similarity_strategy": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json new file mode 100644 index 000000000000..9fcfd0287e4e --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json @@ -0,0 +1,27 @@ +{ + "items": [ + { + "uuid": "05f229e7-0196-45a3", + "short_id": "CAs3AT1XeGCp", + "created_at": "2022-12-15T10:08:21.434114+00:00", + "created_by": "2514dc77-47aa-42f4", + "created_by_type": "user", + "updated_at": "2023-12-18T14:55:33.061335+00:00", + "updated_by": "2514dc77-47aa-42f4", + "updated_by_type": "user", + "title": "Test Add events", + "description": "Test Add events", + "priority": "low", + "status": "opened", + "status_uuid": "6adc2d64-87ee-4394", + "community_uuid": "52bd045f-4199-4361", + "subscribers": [], + "tags": [], + "number_of_comments": 0, + "first_seen_at": "2022-06-17T04:30:24.976000Z", + "last_seen_at": "2023-12-18T13:56:08Z", + "manual": true + } + ], + "total": 1 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json new file mode 100644 index 000000000000..77bf6b120e8a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json @@ -0,0 +1,32 @@ +{ + "items": [ + { + "uuid": "40528f74-2523-428f", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c95", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + }, + { + "uuid": "29a36b54-8ad1-4211", + "content": "This alert is always on ongoing status", + "author": "user:7114c307-d86c-4c55", + "date": 1714653288, + "created_by": "7114c307-d86c-4c55", + "created_by_type": "user", + "unseen": false + }, + { + "uuid": "0fad9131-7596-45be", + "content": "Alert is currently ongoing and will be analyzed by our team of security analysts. Update to come.", + "author": "Sekoia's security analysts", + "date": 1712073666, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + } + ], + "total": 3 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json new file mode 100644 index 000000000000..9a58f85bcfbd --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json @@ -0,0 +1,24 @@ +{ + "actions": [ + { + "id": "937bdabf-6a08-434b", + "name": "Acknowledge", + "description": "Acknowledge the alert" + }, + { + "id": "c39a0a95-aa2c-4d0d", + "name": "Validate", + "description": "Validate the alert" + }, + { + "id": "ade85d7b-7507-4026", + "name": "Reject", + "description": "Reject the alert" + }, + { + "id": "1390be4e-ced8-4dd6", + "name": "Close", + "description": "Close the alert" + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json new file mode 100644 index 000000000000..86cba361a4c4 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json @@ -0,0 +1,120 @@ +{ + "items": [ + { + "uuid": "80ee2ccc-11e3-4416", + "title": "Feed Enriched", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958505, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALL1A4SKUUUU", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology TEST" + }, + "urgency": { + "current_value": 20, + "value": 20, + "severity": 40, + "criticity": 0, + "display": "Moderate" + }, + "alert_type": { + "value": "brute-force", + "category": "intrusion-attempts" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "ebcb5113-dcd1-4563", + "name": "Feed Enriched", + "description": "description test", + "severity": 40, + "type": null, + "pattern": "[ipv4-addr:value = '1.2.3.4']" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": null, + "similar": 11, + "details": "details test", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": "KCXKNfnJuuuu", + "number_of_total_comments": 1, + "first_seen_at": "2019-11-21T13:32:39.839600Z", + "last_seen_at": null, + "assets": [], + "time_to_detect": null, + "time_to_acknowledge": 113615345, + "time_to_respond": null, + "time_to_resolve": 111893849 + }, + { + "uuid": "07fe3fc0-ddb7-44f3", + "title": "Unauthorized IP access", + "created_at": 1574343161, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958712, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALN1JwGVLxxx", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology TEST" + }, + "urgency": { + "current_value": 35, + "value": 35, + "severity": 0, + "criticity": 70, + "display": "Moderate" + }, + "alert_type": { + "value": "unauthorised-information-access", + "category": "information-content-security" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "0c5f57f6-d063-4352", + "name": "Unauthorized IP access", + "description": "Unauthorized network access from one lan to an other one", + "severity": 0, + "type": null, + "pattern": "[network-traffic:src_ref.value NOT IN ('1.2.3.4','5.6.7.8') AND network-traffic:dst_ref.value IN ('7.3.4.4') AND network-traffic:dst_port=22]" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": "DMZ-01 (7.7.7.7)", + "similar": 2, + "details": "Unauthorized network access from one lan to an other one", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": null, + "number_of_total_comments": 1, + "first_seen_at": "2019-11-21T13:32:41.902000Z", + "last_seen_at": null, + "assets": [ + "c50cc586-f3d9-4198" + ], + "time_to_detect": null, + "time_to_acknowledge": 113615550, + "time_to_respond": null, + "time_to_resolve": 111893860 + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json new file mode 100644 index 000000000000..c3edbfd14ccb --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json @@ -0,0 +1,39 @@ +{ + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "keys": [], + "attributes": [ + { + "uuid": "50b7d40c-c052-4b66", + "name": "test_attr", + "value": "0" + }, + { + "uuid": "52bfc48e-567c-45b9", + "name": "test_attr1", + "value": "1" + }, + { + "uuid": "2237d15e-f9d4-463d", + "name": "test_attr2", + "value": "2" + } + ], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json new file mode 100644 index 000000000000..198ff6f73639 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json @@ -0,0 +1,88 @@ +{ + "items": [ + { + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null + }, + { + "uuid": "3deb62b1-aeee-4f08", + "name": "ydi test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": "ydi test fortisoar", + "criticity": { + "value": 28, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-12-01T14:35:37.482496Z", + "updated_at": null + }, + { + "uuid": "dc14148b-8476-4b48", + "name": "cortex debug", + "category": { + "uuid": "87da56fc-1e88-467a", + "name": "people" + }, + "description": "cortex debug", + "criticity": { + "value": 90, + "display": "high" + }, + "asset_type": { + "uuid": "e47dcc10-7c1d-4922", + "name": "person" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-04-06T07:40:45.908084Z", + "updated_at": "2022-04-06T07:41:07.477336Z" + }, + { + "uuid": "54d7afbc-f3e5-42df", + "name": "ADMIN", + "category": { + "uuid": "87da56fc-1e88-467a", + "name": "people" + }, + "description": "Test People Assets", + "criticity": { + "value": 90, + "display": "high" + }, + "asset_type": { + "uuid": "e47dcc10-7c1d-4922", + "name": "person" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-04-06T07:02:59.038731Z", + "updated_at": null + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json new file mode 100644 index 000000000000..7e43a7b038c0 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json @@ -0,0 +1,8 @@ +{ + "order_id": 1, + "uuid": "73708d4f-419f-44aa", + "short_id": "KCXKNfnJupq5", + "name": "Reconnaissance", + "description": "Intruder selects target, researches it, and attempts to identify vulnerabilities in the target network.", + "stix_name": "reconnaissance" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json new file mode 100644 index 000000000000..c82c183f00ae --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json @@ -0,0 +1,22 @@ +{ + "uuid": "7114c307-d86c-4c55", + "firstname": "Joe", + "lastname": "done", + "company_name": "sekoia.io", + "email": "joe.done@test.io", + "picture_mode": "initials", + "created_at": "2023-05-15 15:42:16.266135", + "updated_at": "2024-04-18 09:04:46.748669", + "invitation_v2": null, + "mfa_enabled": true, + "last_activity": "2024-05-02T12:32:27.196065+00:00", + "auth_provider": "local", + "communities": [ + { + "uuid": "52bd045f-4199-4361", + "name": "Sandbox", + "avatar_uuid": "d03d90b1-39f6-4da5", + "disabled": false + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json new file mode 100644 index 000000000000..ae3f98cf5746 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json @@ -0,0 +1,47 @@ +{ + "items": [ + { + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null + }, + { + "uuid": "3deb62b1-aeee-4f08", + "name": "ydi test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": "ydi test cortex", + "criticity": { + "value": 28, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-12-01T14:35:37.482496Z", + "updated_at": null + } + ], + "total": 2 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json new file mode 100644 index 000000000000..619cde5bf12a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json @@ -0,0 +1,9 @@ +{ + "uuid": "00a22dd5-b54d-4eb7", + "content": "This alert is always on ongoing status", + "author": "Joe", + "date": 1714655024, + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "unseen": false +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json new file mode 100644 index 000000000000..592a3753a385 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json @@ -0,0 +1,5 @@ +{ + "uuid": "eac84783-d8d3-4344", + "name": "attr_test_4", + "value": "value4" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json new file mode 100644 index 000000000000..6401b71a3175 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json @@ -0,0 +1,5 @@ +{ + "uuid": "8007222c-f135-4f5f", + "name": "host", + "value": "computer1" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json new file mode 100644 index 000000000000..d14948346921 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json @@ -0,0 +1,28 @@ +{ + "uuid": "df904d2e-2c57-488f", + "status": 0, + "total": 0, + "term": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "term_lang": "es-query-string", + "filters": [], + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "created_at": "2024-04-30T13:50:04.876962Z", + "started_at": null, + "canceled_by": null, + "canceled_by_type": null, + "canceled_at": null, + "ended_at": null, + "earliest_time": "2024-04-25T10:00:23", + "latest_time": "2024-04-25T15:00:23", + "results_ttl": 1800, + "expiration_date": null, + "expired": false, + "view_uuid": null, + "community_uuids": [ + "52bd045f-4199-4361" + ], + "only_eternal": false, + "max_last_events": null, + "date_field": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json new file mode 100644 index 000000000000..ad3ebde3eb4c --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json @@ -0,0 +1,28 @@ +{ + "uuid": "df904d2e-2c57-488f", + "status": 2, + "total": 203912, + "term": "sekoiaio.intake.uuid:834a2d7f-3623", + "term_lang": "es-query-string", + "filters": [], + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "created_at": "2024-04-30T13:56:32.338174Z", + "started_at": "2024-04-30T13:56:32.409996Z", + "canceled_by": null, + "canceled_by_type": null, + "canceled_at": null, + "ended_at": "2024-04-30T13:56:33.802894Z", + "earliest_time": "2024-04-25T10:00:23", + "latest_time": "2024-04-25T15:00:23", + "results_ttl": 1800, + "expiration_date": "2024-04-30T14:26:33.838485Z", + "expired": true, + "view_uuid": null, + "community_uuids": [ + "52bd045f-4199-4361" + ], + "only_eternal": false, + "max_last_events": null, + "date_field": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json new file mode 100644 index 000000000000..1afffda7852a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json @@ -0,0 +1,124 @@ +{ + "items": [ + { + "__event_id": "ZXZlbnRzLTUyYmQwNDVmLTQxOTktNDM2MS04MjY3LWNkZWJmYzc4NDM5Mi0", + "timestamp": "2024-04-25T14:11:10.652Z", + "agent.id": "6a779e00ed1642ab91a9afcb20b4b4de371a62d28", + "agent.version": "v1.5.0+909fc425bc21b", + "process.args": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.args": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.name": "SekoiaTest.exe", + "process.parent.pid": 1002, + "process.parent.command_line": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.executable": "C:\\Windows\\System32\\SekoiaTest.exe", + "process.name": "processNameTest.exe", + "process.pid": 623, + "process.command_line": "\"C:\\Windows\\system32\\processNameTest.exe\" -ServerName:testserver", + "process.executable": "C:\\Windows\\system32\\processNameTest.exe", + "message": "{}", + "related.hosts": "laptop-test", + "related.ip": "1.2.3.4", + "related.user": "joe.done", + "sekoiaio.any_tag": "rfc5555, rfc1111", + "sekoiaio.process.parent_guid": "52bff9b3-fa38-4724", + "sekoiaio.process.guid": "dd924315-2807-45de", + "sekoiaio.assets.host.hostname.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.host.ip.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.host.name.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.user.name.uuid": [ + "9d99b786-6eaf-46d7" + ], + "sekoiaio.any_asset.uuid": [ + [ + "85dbcf0f-cc30-421e" + ], + [ + "9d99b786-6eaf-46d7" + ] + ], + "sekoiaio.any_asset.criticality_value": [ + [ + 0 + ], + [ + 0 + ] + ], + "sekoiaio.any_asset.name": [ + [ + "laptop-test" + ], + [ + "joe.done" + ] + ], + "sekoiaio.intake.parsing_status": "success", + "sekoiaio.intake.dialect": "sekoia.io endpoint agent", + "sekoiaio.intake.name": "Sekoia Agent ARY", + "sekoiaio.intake.dialect_uuid": "250e4095-fa08-4101", + "sekoiaio.intake.uuid": "834a2d7f-3623-4b26", + "sekoiaio.intake.key": "WJ4KkMbT8wkiFVkWpv", + "sekoiaio.entity.name": "Sekoia Agent ARY", + "sekoiaio.entity.id": "1001", + "sekoiaio.entity.uuid": "7f7676e7-a254-43c3", + "sekoiaio.tags.related.ip": [ + "rfc5735", + "rfc1918" + ], + "sekoiaio.tags.host.ip": [ + "rfc5735", + "rfc1918" + ], + "sekoiaio.customer.community_name": "Sandbox", + "sekoiaio.customer.community_uuid": "52bd045f-4199-4361", + "sekoiaio.customer.id": "Sandbox", + "host.hostname": "laptop-test", + "host.os.type": "windows", + "host.ip": "1.2.3.4", + "host.name": "laptop-test", + "action.name": "process-created", + "action.id": 1, + "action.properties.ExitStatus": "259", + "action.properties.ProviderGuid": "{3D6FA8D0-FE05-11D0}", + "action.properties.Keywords": "0x0", + "action.properties.ImageFileName": "SekoiaTest.exe", + "action.properties.PackageFullName": "", + "action.properties.SourceName": "Kernel-Process", + "action.properties.Severity": "LOG_ALWAYS", + "action.properties.UniqueProcessKey": "0xFFFFB3811111111", + "action.properties.Flags": "0", + "action.properties.ApplicationId": "", + "action.properties.SessionId": "2", + "action.properties.DirectoryTableBase": "0x933E111", + "action.outcome": "success", + "event.code": "1", + "event.dialect": "sekoia.io endpoint agent", + "event.provider": "SEKOIA-IO", + "event.created": "2024-04-25T14:11:28.073386+00:00", + "event.action": "process-created", + "event.id": "0b83c211-6e79-4a28", + "event.dialect_uuid": "250e4095-fa08-4101", + "event.type": "creation", + "event.category": "process", + "event.outcome": "success", + "user.domain": "DomainTEST", + "user.name": "joe.done", + "entity.name": "IT test", + "entity.id": "1000", + "entity.uuid": "7f7676e7-a254-43c3", + "customer.intake_key": "WJ4KkMbT8wkiFVk", + "customer.community_name": "Sandbox", + "customer.intake_uuid": "834a2d7f-3623-4b26", + "customer.community_uuid": "52bd045f-4199-4361", + "customer.id": "Sandbox", + "customer.intake_name": "Sekoia Agent ARY" + } + ], + "total": 1 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/README.md b/Packs/SekoiaXDR/README.md new file mode 100644 index 000000000000..70990f1712b3 --- /dev/null +++ b/Packs/SekoiaXDR/README.md @@ -0,0 +1,10 @@ +# SEKOIA Operation Center + +Request assets, alerts and events from SEKOIA.IO Operation Center. + +## What does this pack do ? + +- Fetch assets and do some actions on it +- Fetch alerts and do some actions on it +- Query events +- Fetch user \ No newline at end of file diff --git a/Packs/SekoiaXDR/pack_metadata.json b/Packs/SekoiaXDR/pack_metadata.json new file mode 100644 index 000000000000..33ed58bcc4e1 --- /dev/null +++ b/Packs/SekoiaXDR/pack_metadata.json @@ -0,0 +1,23 @@ +{ + "name": "SekoiaXDR", + "description": "Request SEKOIA.IO Operation Center from Cortex XSOAR", + "support": "partner", + "currentVersion": "1.0.0", + "author": "SEKOIA.IO", + "url": "https://www.sekoia.io/en/contact/", + "email": "contact@sekoia.io", + "categories": [ + "Data Enrichment & Threat Intelligence" + ], + "tags": [], + "useCases": [], + "keywords": [], + "marketplaces": [ + "xsoar", + "marketplacev2" + ], + "devEmail": [ + "team-integration@sekoia.io" + ], + "githubUser": [] +} \ No newline at end of file