Azure Sentinel
Microsoft Sentinel is a scalable, cloud-native solution that provides: Security information and event management (SIEM) Security orchestration, automation, and response (SOAR).
Analytics & SIEM · Microsoft Sentinel
Details
| ID | Azure Sentinel |
|---|---|
| Provider | Microsoft |
| Category | Analytics & SIEM |
| From Version | 5.0.0 |
| Docker Image | demisto/crypto:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
Important Notice – Microsoft Sentinel Migration to Microsoft Defender Portal
Microsoft is migrating Microsoft Sentinel from the Azure portal to the Microsoft Defender portal:
- From July 2025 – New customers have automatically been onboarded and redirected to the Defender portal.
- Starting March 2027 – All customers using Microsoft Sentinel in the Azure portal will be redirected to the Defender portal.
This integration is not being deprecated at this time, as not all commands are supported in the Graph API. However, if you currently use Microsoft Sentinel in the Azure portal, Microsoft recommends planning your transition to the Defender portal now.
We strongly recommend transitioning to the following integrations for managing incidents and indicators:
Use the Azure Sentinel integration to get and manage incidents and get related entity information for incidents.
This integration was integrated and tested with version 2021-04-01 of Azure Sentinel.
Authorize Cortex XSOAR for Azure Sentinel
Follow these steps for a self-deployed configuration.
- To use a self-configured Azure application, you need to add a new Azure App Registration in the Azure Portal. To add the registration, refer to the Register an application section of the following Microsoft article. (Note: There is no need to create a redirect URI or complete subsequent steps of the article).
- In your registered app - create a new Client secret.
- Navigate in the Azure Portal to App registrations > your registered application > Certificates & secrets and click + New client secret.
- Copy and save the new secret value to use in the add credentials step.
- Assign a role to the registered app.
- In the Azure portal, go to the Subscriptions and select the subscription you are using -> Access control (IAM).
- Click Add > Add role assignment.
- Select the Azure Sentinel Contributor role > Select your registered app, and click Save.
- In Cortex XSOAR, go to Settings > Integrations > Credentials and create a new credentials set.
- In the Username parameter, enter your registered app Application (client) ID.
- In the Password parameter, enter the secret value you created.
- Copy your tenant ID for the integration configuration usage.
Configure the server URL
If you have a dedicated server URL, enter it in the Server Url parameter.
Get the additional instance parameters
To get the Subscription ID, Workspace Name and Resource Group parameters, in the Azure Portal navigate to Azure Sentinel > your workspace > Settings and click the Workspace Settings tab.
Configure Azure Sentinel on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for Azure Sentinel.
- Click Add instance to create and configure a new integration instance.
| Parameter | Description | Required |
|---|---|---|
| Azure Cloud | When selecting the Custom option, the Server URL parameter must be filled. More information about National clouds can be found here - https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations—authentication#using-national-cloud | False |
| Maximum number of incidents per fetch. | The maximum number of incidents to fetch each time. The default value is 20 and the maximum allowed value is 50. | False |
| Tenant ID | False | |
| Client ID | The Application (Client) ID of the Azure app registration. | False |
| Client Secret | False | |
| Certificate Thumbprint | Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. | False |
| Private Key | False | |
| Use Azure Managed Identities | Relevant only if the integration is running on Azure VM. If selected, authenticates based on the value provided for the Azure Managed Identities Client ID field. If no value is provided for the Azure Managed Identities Client ID field, authenticates based on the System Assigned Managed Identity. For additional information, see the Help tab. | False |
| Azure Managed Identities Client ID | The Managed Identities client id for authentication - relevant only if the integration is running on Azure VM. | False |
| Default Subscription ID | The parameter can be saved as 000-000 and added as an argument to each command, but Test button will fail. | True |
| Default Resource Group Name | The parameter can be saved as 000-000 and added as an argument to each command, but the Test button will fail. | True |
| Workspace Name | True | |
| Fetch incidents | False | |
| First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days) | False | |
| The minimum severity of incidents to fetch | False | |
| Incident type | False | |
| Server URL | Use this option when required to customize the URL to the Azure management endpoint. More information can be found here - https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations—authentication#using-national-cloud | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Additional info to fetch | Choose what additional info to fetch for each incident. Note that this will increase the number of API calls. |
False |
| Mirroring Direction | False | |
| Close Mirrored XSOAR Incident | When selected, closing the Microsoft Sentinel ticket is mirrored in Cortex XSOAR. | False |
| Close Mirrored Microsoft Sentinel Ticket | When selected, closing the Cortex XSOAR incident is mirrored in Microsoft Sentinel. | False |
| Incident Statuses to Fetch | The statuses of the incidents that will be fetched. If no status is provided then incidents of all the statuses will be fetched. | False |
| Incidents Fetch Interval | False | |
| Minutes to look back when fetching | The lookback time window for incidents/issues created before the last run time that did not initially match the query. Small values (for example, 1-5 minutes) are recommended to avoid performance issues. | False |
| Incident Titles to not Fetch | The case-sensitive titles of the incidents that will not be fetched. This will also match if the title provided is contained in the incident’s title. If no title is provided then all incidents will be fetched. | False |
| Alert Product Names to not Fetch | The alert product names of the incidents that will not be fetched. For example: Microsoft Entra ID Protection, Microsoft Sentinel. If no alert product name is provided then incidents will be fetched normally. | False |
-
Azure cloud options
Azure Cloud Description Worldwide The publicly accessible Azure Cloud US GCC Azure cloud for the USA Government Cloud Community (GCC) US GCC-High Azure cloud for the USA Government Cloud Community High (GCC-High) DoD Azure cloud for the USA Department of Defense (DoD) Germany Azure cloud for the German Government China Azure cloud for the Chinese Government Custom Custom endpoint configuration to the Azure cloud, please see note below. - Note: In most cases setting Azure cloud is preferred to setting Server URL. Only use it in cases where a custom proxy URL is required for accessing a national cloud.
-
Click Test to validate the URLs, token, and connection.
Incident Mirroring
You can enable incident mirroring between Cortex XSOAR incidents and Microsoft Sentinel incidents (available from Cortex XSOAR version 6.0.0).
To setup the mirroring follow these instructions:
- Navigate to Settings > Integrations > Servers & Services.
- Search for Microsoft Sentinel and select your integration instance.
- Enable Fetches incidents.
- In the Mirroring Direction integration parameter, select in which direction the incidents should be mirrored:
- Incoming - Any changes in Microsoft Sentinel incidents will be reflected in Cortex XSOAR incidents.
- Outgoing - Any changes in Cortex XSOAR incidents will be reflected in Microsoft Sentinel.
- Incoming And Outgoing - Changes in Cortex XSOAR incidents and Microsoft Sentinel incidents will be reflected in both directions.
- None - Turns off incident mirroring.
- Optional: Check the Close Mirrored XSOAR Incident integration parameter to close the Cortex XSOAR incident when the corresponding incident is closed in Microsoft Sentinel.
- Optional: Check the Close Mirrored Microsoft Sentinel Ticket integration parameter to close the Microsoft Sentinel incident when the corresponding Cortex XSOAR incident is closed.
Newly fetched incidents will be mirrored in the chosen direction. However, this selection does not affect existing incidents.
Important Notes:
- To ensure the mirroring works as expected, mappers are required, both for incoming and outgoing, to map the expected fields in Cortex XSOAR and Microsoft Sentinel.
- If the The minimum severity of incidents to fetch integration parameter is set to a value other than
None, incidents with a severity lower than the specified value will not be mirrored, even if their severity is changed in Microsoft Sentinel to a higher severity. - When closing an incident in Cortex XSOAR, the Closing Reason must be provided, otherwise the incident cannot be closed in Microsoft Sentinel.
Look-back Note:
- Increasing the look-back parameter value after the initial fetch may result in duplicate incidents during the first run following the change. To avoid duplicates, ensure the lookback value is not increased once the integration is active.
For more information, see fetch-incidents-lookback. - Using a large lookback value (greater than one hour) may increase memory usage and is not recommended.
For tracking issues or scenarios requiring a large lookback window, it is recommended to use the mirroring feature with relevant tag filtering instead of the lookback parameter. You can configure a custom mapper to track specific fields.
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.
azure-sentinel-get-incident-by-id
Gets a single incident from Azure Sentinel.
Base Command
azure-sentinel-get-incident-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Incident.ID | String | The incident ID. |
| AzureSentinel.Incident.Title | String | The incident title. |
| AzureSentinel.Incident.Description | String | Description of the incident. |
| AzureSentinel.Incident.Severity | String | The incident severity. |
| AzureSentinel.Incident.Status | String | The incident status. |
| AzureSentinel.Incident.AssigneeName | String | The name of the incident assignee. |
| AzureSentinel.Incident.AssigneeEmail | String | The email address of the incident assignee. |
| AzureSentinel.Incident.AssigneeObjectID | String | The object ID of the incident assignee. |
| AzureSentinel.Incident.AssigneeUPN | String | The user principal name of the incident assignee. |
| AzureSentinel.Incident.Label.Name | String | The name of the incident label. |
| AzureSentinel.Incident.Label.Type | String | The incident label type. |
| AzureSentinel.Incident.FirstActivityTimeUTC | Date | The date and time of the incident’s first activity. |
| AzureSentinel.Incident.LastActivityTimeUTC | Date | The date and time of the incident’s last activity. |
| AzureSentinel.Incident.LastModifiedTimeUTC | Date | The date and time the incident was last modified. |
| AzureSentinel.Incident.CreatedTimeUTC | Date | The date and time the incident was created. |
| AzureSentinel.Incident.IncidentNumber | Number | The incident number. |
| AzureSentinel.Incident.AlertsCount | Number | The number of the alerts in the incident. |
| AzureSentinel.Incident.BookmarkCount | Number | The number of bookmarks in the incident. |
| AzureSentinel.Incident.CommentCount | Number | The number of comments in the incident. |
| AzureSentinel.Incident.AlertProductNames | String | The alert product names of the incident. |
| AzureSentinel.Incident.Tactics | String | The incident’s tactics. |
| AzureSentinel.Incident.FirstActivityTimeGenerated | Date | The incident’s generated first activity time. |
| AzureSentinel.Incident.LastActivityTimeGenerated | Date | The incident’s generated last activity time. |
| AzureSentinel.Incident.Etag | String | The Etag of the incident. |
| AzureSentinel.Incident.IncidentUrl | String | The deep-link URL to the incident in the Azure portal. |
Command Example
!azure-sentinel-get-incident-by-id incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742
Context Example
{
"AzureSentinel": {
"Incident": {
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": "test@test.com",
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 3,
"CreatedTimeUTC": "2020-01-15T09:29:14Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"2700a244-0000-0100-0000-6123a2930000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": null,
"ID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"IncidentNumber": 2,
"Label": [
{
"Name": "label_a",
"Type": "User"
},
{
"Name": "label_b",
"Type": "User"
}
],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2021-08-23T13:28:51Z",
"Severity": "Informational",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
}
}
}
Human Readable Output
Incident 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 details
ID Incident Number Title Description Severity Status Assignee Email Label Last Modified Time UTC Created Time UTC Alerts Count Bookmarks Count Comments Count Alert Product Names Etag 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 2 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Informational New test@test.com {‘Name’: ‘label_a’, ‘Type’: ‘User’},
{‘Name’: ‘label_b’, ‘Type’: ‘User’}2021-08-23T13:28:51Z 2020-01-15T09:29:14Z 1 0 3 Azure Sentinel “2700a244-0000-0100-0000-6123a2930000”
azure-sentinel-list-incidents
Gets a list of incidents from Azure Sentinel.
Base Command
azure-sentinel-list-incidents
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of incidents to return. The maximum value is 200. Default is 50. | Optional |
| filter | Filter results using OData syntax. For example: properties/createdTimeUtc gt 2020-02-02T14:00:00Z`). For more information, see the Azure documentation: https://docs.microsoft.com/bs-latn-ba/azure/search/search-query-odata-filter. | Optional |
| next_link | A link that specifies a starting point to use for subsequent calls. This argument overrides all of the other command arguments. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Incident.ID | String | The incident ID. |
| AzureSentinel.Incident.Title | String | The incident title. |
| AzureSentinel.Incident.Description | String | Description of the incident. |
| AzureSentinel.Incident.Severity | String | The incident severity. |
| AzureSentinel.Incident.Status | String | The incident status. |
| AzureSentinel.Incident.AssigneeName | String | The name of the incident assignee. |
| AzureSentinel.Incident.AssigneeEmail | String | The email address of the incident assignee. |
| AzureSentinel.Incident.Label.Name | String | The name of the incident label. |
| AzureSentinel.Incident.Label.Type | String | The incident label type. |
| AzureSentinel.Incident.FirstActivityTimeUTC | Date | The date and time of the incident’s first activity. |
| AzureSentinel.Incident.LastActivityTimeUTC | Date | The date and time of the incident’s last activity. |
| AzureSentinel.Incident.LastModifiedTimeUTC | Date | The date and time the incident was last modified. |
| AzureSentinel.Incident.CreatedTimeUTC | Date | The date and time the incident was created. |
| AzureSentinel.Incident.IncidentNumber | Number | The incident number. |
| AzureSentinel.Incident.AlertsCount | Number | The number of the alerts in the incident. |
| AzureSentinel.Incident.BookmarkCount | Number | The number of bookmarks in the incident. |
| AzureSentinel.Incident.CommentCount | Number | The number of comments in the incident. |
| AzureSentinel.Incident.AlertProductNames | String | The alert product names of the incident. |
| AzureSentinel.Incident.Tactics | String | The incident’s tactics. |
| AzureSentinel.Incident.FirstActivityTimeGenerated | Date | The incident’s generated first activity time. |
| AzureSentinel.Incident.LastActivityTimeGenerated | Date | The incident’s generated last activity time. |
| AzureSentinel.NextLink.Description | String | Description of NextLink. |
| AzureSentinel.NextLink.URL | String | Used if an operation returns partial results. If a response contains a NextLink element, its value specifies a starting point to use for subsequent calls. |
| AzureSentinel.Incident.Etag | String | The Etag of the incident. |
Command Example
!azure-sentinel-list-incidents limit=5
Context Example
{
"AzureSentinel": {
"Incident": [
{
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": "test@test.com",
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 3,
"CreatedTimeUTC": "2020-01-15T09:29:14Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"2700a244-0000-0100-0000-6123a2930000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": null,
"ID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"IncidentNumber": 2,
"Label": [
{
"Name": "label_a",
"Type": "User"
},
{
"Name": "label_b",
"Type": "User"
}
],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2021-08-23T13:28:51Z",
"Severity": "Informational",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
},
{
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": "test@test.com",
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 0,
"CreatedTimeUTC": "2020-01-15T09:34:12Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"dc00cb1c-0000-0100-0000-60992bf20000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": null,
"ID": "e0b06d71-b5a3-43a9-997f-f25b45085cb7",
"IncidentNumber": 4,
"Label": [
{
"Name": "f",
"Type": "User"
},
{
"Name": "o",
"Type": "User"
},
{
"Name": "o",
"Type": "User"
},
{
"Name": "1",
"Type": "User"
}
],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2021-05-10T12:49:54Z",
"Severity": "Low",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
},
{
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": null,
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 0,
"CreatedTimeUTC": "2020-01-15T09:40:09Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"0100c30e-0000-0100-0000-5fb883be0000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": "2020-01-15T08:04:05Z",
"ID": "a7977be7-1008-419b-877b-6793b7402a80",
"IncidentNumber": 6,
"Label": [],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": "2020-01-15T09:04:05Z",
"LastModifiedTimeUTC": "2020-01-15T09:40:09Z",
"Severity": "Medium",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
},
{
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": null,
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 1,
"CreatedTimeUTC": "2020-01-15T09:44:12Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"0600a81f-0000-0100-0000-5fdb4e890000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": null,
"ID": "6440c129-c313-418c-a262-5df608aa9cd2",
"IncidentNumber": 7,
"Label": [],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2020-12-17T12:26:49Z",
"Severity": "Medium",
"Status": "Active",
"Tactics": null,
"Title": "test_title"
},
{
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": null,
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 0,
"CreatedTimeUTC": "2020-01-15T09:49:12Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"0100b70e-0000-0100-0000-5fb883bd0000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": "2020-01-15T08:44:06Z",
"ID": "413e9d64-c7b4-4e33-ae26-bb39710d2187",
"IncidentNumber": 9,
"Label": [],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": "2020-01-15T09:44:06Z",
"LastModifiedTimeUTC": "2020-01-15T09:49:12Z",
"Severity": "Medium",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
}
],
"NextLink": {
"Description": "NextLink for listing commands",
"URL": "https://test.com"
}
}
}
Human Readable Output
Incidents List (5 results)
ID Incident Number Title Description Severity Status Assignee Email Label First Activity Time UTC Last Activity Time UTC Last Modified Time UTC Created Time UTC Alerts Count Bookmarks Count Comments Count Alert Product Names Etag 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 2 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Informational New test@test.com {‘Name’: ‘label_a’, ‘Type’: ‘User’},
{‘Name’: ‘label_b’, ‘Type’: ‘User’}2021-08-23T13:28:51Z 2020-01-15T09:29:14Z 1 0 3 Azure Sentinel “2700a244-0000-0100-0000-6123a2930000” e0b06d71-b5a3-43a9-997f-f25b45085cb7 4 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Low New test@test.com {‘Name’: ‘f’, ‘Type’: ‘User’},
{‘Name’: ‘o’, ‘Type’: ‘User’},
{‘Name’: ‘o’, ‘Type’: ‘User’},
{‘Name’: ‘1’, ‘Type’: ‘User’}2021-05-10T12:49:54Z 2020-01-15T09:34:12Z 1 0 0 Azure Sentinel “dc00cb1c-0000-0100-0000-60992bf20000” a7977be7-1008-419b-877b-6793b7402a80 6 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Medium New 2020-01-15T08:04:05Z 2020-01-15T09:04:05Z 2020-01-15T09:40:09Z 2020-01-15T09:40:09Z 1 0 0 Azure Sentinel “0100c30e-0000-0100-0000-5fb883be0000” 6440c129-c313-418c-a262-5df608aa9cd2 7 test_title Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Medium Active 2020-12-17T12:26:49Z 2020-01-15T09:44:12Z 1 0 1 Azure Sentinel “0600a81f-0000-0100-0000-5fdb4e890000” 413e9d64-c7b4-4e33-ae26-bb39710d2187 9 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Medium New 2020-01-15T08:44:06Z 2020-01-15T09:44:06Z 2020-01-15T09:49:12Z 2020-01-15T09:49:12Z 1 0 0 Azure Sentinel “0100b70e-0000-0100-0000-5fb883bd0000”
azure-sentinel-list-watchlists
Gets a list of watchlists from Azure Sentinel.
Base Command
azure-sentinel-list-watchlists
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | Alias of specific watchlist to get. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Watchlist.ID | String | The watchlist ID. |
| AzureSentinel.Watchlist.Description | String | A description of the watchlist. |
| AzureSentinel.Watchlist.DisplayName | String | The display name of the watchlist. |
| AzureSentinel.Watchlist.Provider | String | The provider of the watchlist. |
| AzureSentinel.Watchlist.Source | String | The source of the watchlist. |
| AzureSentinel.Watchlist.Created | Date | The time the watchlist was created. |
| AzureSentinel.Watchlist.Updated | Date | The last time the watchlist was updated. |
| AzureSentinel.Watchlist.CreatedBy | String | The name of the user who created the watchlist. |
| AzureSentinel.Watchlist.UpdatedBy | String | The name of the user who updated the Watchlist. |
| AzureSentinel.Watchlist.Alias | String | The alias of the watchlist. |
| AzureSentinel.Watchlist.Label | unknown | Label that will be used to tag and filter on. |
| AzureSentinel.Watchlist.ItemsSearchKey | String | The search key is used to optimize query performance when using watchlists for joins with other data. For example, enable a column with IP addresses to be the designated SearchKey field, then use this field as the key field when joining to other event data by IP address. |
| AzureSentinel.NextLink.Description | String | Description of NextLink. |
| AzureSentinel.NextLink.URL | String | Used if an operation returns partial results. If a response contains a NextLink element, its value specifies a starting point to use for subsequent calls. |
Command Example
#### Context Example
```json
{
"AzureSentinel": {
"Watchlist": [
{
"Alias": "booboo",
"Created": "2021-07-11T08:20:35Z",
"CreatedBy": "test@test.com",
"Description": "just for fun",
"ID": "35bffe30-19f2-40a6-8855-4a858e161fad",
"ItemsSearchKey": "IP",
"Label": [
"IP"
],
"Name": "booboo",
"Provider": "xsoar",
"Source": "Local file",
"Updated": "2021-07-11T08:20:35Z",
"UpdatedBy": "test@test.com"
},
{
"Alias": "test_2",
"Created": "2021-08-16T10:26:56Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"Description": "test watchlist",
"ID": "ceae6089-10dd-4f02-89d5-ab32285688dc",
"ItemsSearchKey": "IP",
"Label": [],
"Name": "test_2",
"Provider": "XSOAR",
"Source": "Local file",
"Updated": "2021-08-16T10:26:56Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd"
},
{
"Alias": "test_1",
"Created": "2021-08-15T14:14:28Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"Description": "",
"ID": "92863c74-fee7-4ffe-8288-bc1529d12597",
"ItemsSearchKey": "IP",
"Label": [],
"Name": "test_1",
"Provider": "XSOAR",
"Source": "Local file",
"Updated": "2021-08-15T14:14:28Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd"
},
{
"Alias": "test_4",
"Created": "2021-08-23T13:30:53Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"Description": "test watchlist",
"ID": "84d1fedd-5945-4670-ae34-5e8c94af2660",
"ItemsSearchKey": "IP",
"Label": [],
"Name": "test_4",
"Provider": "XSOAR",
"Source": "Local file",
"Updated": "2021-08-23T13:30:53Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd"
}
]
}
}
Human Readable Output
Watchlists results
Name ID Description booboo 35bffe30-19f2-40a6-8855-4a858e161fad just for fun test_2 ceae6089-10dd-4f02-89d5-ab32285688dc test watchlist test_1 92863c74-fee7-4ffe-8288-bc1529d12597 test_4 84d1fedd-5945-4670-ae34-5e8c94af2660 test watchlist
azure-sentinel-delete-watchlist
Delete a watchlists from Azure Sentinel.
Base Command
azure-sentinel-delete-watchlist
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | Alias of the watchlist to be deleted. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
There is no context output for this command.
Command Example
!azure-sentinel-delete-watchlist watchlist_alias=test_4
Human Readable Output
Watchlist test_4 was deleted successfully.
azure-sentinel-watchlist-create-update
Create or update a watchlist in Azure Sentinel.
Base Command
azure-sentinel-watchlist-create-update
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | The alias of the new watchlist or the watchlist to update. | Required |
| watchlist_display_name | The display name of the watchlist. | Required |
| description | The description of the watchlist. | Optional |
| provider | The provider of the watchlist. Default is XSOAR. | Optional |
| source | The source of the watchlist. Possible values are: Local file, Remote storage. | Required |
| labels | The labels of the watchlist. | Optional |
| lines_to_skip | The number of lines in the CSV content to skip before the header. Default is 0. | Optional |
| file_entry_id | A file entry with raw content that represents the watchlist items to create. | Required |
| items_search_key | The search key is used to optimize query performance when using watchlists for joins with other data. For example, enable a column with IP addresses to be the designated SearchKey field, then use this field as the key field when joining to other event data by IP address. | Required |
| content_type | The content type of the raw content. For now, only text/csv is valid. Default is Text/Csv. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Watchlist.Name | String | The name of the watchlist. |
| AzureSentinel.Watchlist.ID | String | The ID (GUID) of the watchlist. |
| AzureSentinel.Watchlist.Description | String | A description of the watchlist. |
| AzureSentinel.Watchlist.Provider | String | The provider of the watchlist. |
| AzureSentinel.Watchlist.Source | String | The source of the watchlist. |
| AzureSentinel.Watchlist.Created | Date | The time the watchlist was created. |
| AzureSentinel.Watchlist.Updated | Date | The time the watchlist was updated. |
| AzureSentinel.Watchlist.CreatedBy | String | The user who created the watchlist. |
| AzureSentinel.Watchlist.UpdatedBy | String | The user who updated the watchlist. |
| AzureSentinel.Watchlist.Alias | String | The alias of the watchlist. |
| AzureSentinel.Watchlist.Label | Unknown | List of labels relevant to this watchlist. |
| AzureSentinel.Watchlist.ItemsSearchKey | String | The search key is used to optimize query performance when using watchlists for joins with other data. |
Command Example
!azure-sentinel-watchlist-create-update items_search_key=IP raw_content=1711@3c9bd2a0-9eac-465b-8799-459df4997b2d source="Local file" watchlist_alias=test_4 watchlist_display_name=test_4 description="test watchlist"
Context Example
{
"AzureSentinel": {
"Watchlist": {
"Alias": "test_4",
"Created": "2021-08-23T13:30:53Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"Description": "test watchlist",
"ID": "84d1fedd-5945-4670-ae34-5e8c94af2660",
"ItemsSearchKey": "IP",
"Label": [],
"Name": "test_4",
"Provider": "XSOAR",
"Source": "Local file",
"Updated": "2021-08-23T13:30:53Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd"
}
}
}
Human Readable Output
Create watchlist results
Name ID Description test_4 84d1fedd-5945-4670-ae34-5e8c94af2660 test watchlist
azure-sentinel-update-incident
Updates a single incident in Azure Sentinel.
Base Command
azure-sentinel-update-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| title | The incident’s title. | Optional |
| description | Description of the incident. | Optional |
| severity | The incident severity. Possible values are: High, Medium, Low, Informational. | Optional |
| status | The incident status. Possible values are: New, Active, Closed. | Optional |
| classification | The reason the incident was closed. Required when updating the status to Closed. Possible values are: BenignPositive, FalsePositive, TruePositive, Undetermined. | Optional |
| classification_comment | Describes the reason the incident was closed. | Optional |
| classification_reason | The classification reason the incident was closed with. Required when updating the status to Closed and the classification is determined. Possible values are: InaccurateData, IncorrectAlertLogic, SuspiciousActivity, SuspiciousButExpected. | Optional |
| assignee_email | The email address of the incident assignee. It is recommended to update user_principal_name instead of this field. Note that the updated API field is owner.email. |
Optional |
| user_principal_name | The user principal name of the client. Note that the updated API field is owner.userPrincipalName. |
Optional |
| labels | Incident labels. Note that all labels will be set as labelType=’User’. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Incident.ID | String | The incident ID. |
| AzureSentinel.Incident.Title | String | The incident’s title. |
| AzureSentinel.Incident.Description | String | Description of the incident. |
| AzureSentinel.Incident.Severity | String | The incident severity. |
| AzureSentinel.Incident.Status | String | The incident status. |
| AzureSentinel.Incident.AssigneeName | String | The name of the incident assignee. |
| AzureSentinel.Incident.AssigneeEmail | String | The email address of the incident assignee. |
| AzureSentinel.Incident.AssigneeObjectID | String | The object ID of the incident assignee. |
| AzureSentinel.Incident.AssigneeUPN | String | The user principal name of the incident assignee. |
| AzureSentinel.Incident.Label.Name | String | The name of the incident label. |
| AzureSentinel.Incident.Label.Type | String | The incident label type. |
| AzureSentinel.Incident.FirstActivityTimeUTC | Date | The date and time of the incident’s first activity. |
| AzureSentinel.Incident.LastActivityTimeUTC | Date | The date and time of the incident’s last activity. |
| AzureSentinel.Incident.LastModifiedTimeUTC | Date | The date and time the incident was last modified. |
| AzureSentinel.Incident.CreatedTimeUTC | Date | The date and time the incident was created. |
| AzureSentinel.Incident.IncidentNumber | Number | The incident number. |
| AzureSentinel.Incident.AlertsCount | Number | The number of the alerts in the incident. |
| AzureSentinel.Incident.BookmarkCount | Number | The number of bookmarks in the incident. |
| AzureSentinel.Incident.CommentCount | Number | The number of comments in the incident. |
| AzureSentinel.Incident.AlertProductNames | String | The alert product names of the incident. |
| AzureSentinel.Incident.Tactics | String | The incident’s tactics. |
| AzureSentinel.Incident.FirstActivityTimeGenerated | Date | The incident’s generated first activity time. |
| AzureSentinel.Incident.LastActivityTimeGenerated | Date | The incident’s generated last activity time. |
| AzureSentinel.Incident.Etag | String | The Etag of the incident. |
Command Example
!azure-sentinel-update-incident incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 labels=label_a,label_b
Context Example
{
"AzureSentinel": {
"Incident": {
"AlertProductNames": [
"Azure Sentinel"
],
"AlertsCount": 1,
"AssigneeEmail": "test@test.com",
"AssigneeName": null,
"BookmarksCount": 0,
"CommentsCount": 4,
"CreatedTimeUTC": "2020-01-15T09:29:14Z",
"Deleted": false,
"Description": "Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses\nexceeds a threshold (default is 100).",
"Etag": "\"27002845-0000-0100-0000-6123a3090000\"",
"FirstActivityTimeGenerated": null,
"FirstActivityTimeUTC": null,
"ID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"IncidentNumber": 2,
"Label": [
{
"Name": "label_a",
"Type": "User"
},
{
"Name": "label_b",
"Type": "User"
}
],
"LastActivityTimeGenerated": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2021-08-23T13:30:49Z",
"Severity": "Informational",
"Status": "New",
"Tactics": null,
"Title": "SharePointFileOperation via previously unseen IPs"
}
}
}
Human Readable Output
Updated incidents 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 details
ID Incident Number Title Description Severity Status Assignee Email Label Last Modified Time UTC Created Time UTC Alerts Count Bookmarks Count Comments Count Alert Product Names Etag 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 2 SharePointFileOperation via previously unseen IPs Identifies when the volume of documents uploaded to or downloaded from Sharepoint by new IP addresses
exceeds a threshold (default is 100).Informational New test@test.com {‘Name’: ‘label_a’, ‘Type’: ‘User’},
{‘Name’: ‘label_b’, ‘Type’: ‘User’}2021-08-23T13:30:49Z 2020-01-15T09:29:14Z 1 0 4 Azure Sentinel “27002845-0000-0100-0000-6123a3090000”
azure-sentinel-create-incident
Creates a single incident in Azure Sentinel.
Base Command
azure-sentinel-create-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| title | The incident’s title. | Required |
| severity | The incident severity. Possible values are: High, Medium, Low, Informational. | Required |
| status | The incident status. Possible values are: New, Active, Closed. | Required |
| description | Description of the incident. | Optional |
| labels | Incident labels. Note that all labels will be set as labelType=’User’. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.Incident.ID | String | The incident ID. |
| AzureSentinel.Incident.Title | String | The incident’s title. |
| AzureSentinel.Incident.Description | String | Description of the incident. |
| AzureSentinel.Incident.Severity | String | The incident severity. |
| AzureSentinel.Incident.Status | String | The incident status. |
| AzureSentinel.Incident.AssigneeName | String | The name of the incident assignee. |
| AzureSentinel.Incident.AssigneeEmail | String | The email address of the incident assignee. |
| AzureSentinel.Incident.AssigneeObjectID | String | The object ID of the incident assignee. |
| AzureSentinel.Incident.AssigneeUPN | String | The user principal name of the incident assignee. |
| AzureSentinel.Incident.Label.Name | String | The name of the incident label. |
| AzureSentinel.Incident.Label.Type | String | The incident label type. |
| AzureSentinel.Incident.FirstActivityTimeUTC | Date | The date and time of the incident’s first activity. |
| AzureSentinel.Incident.LastActivityTimeUTC | Date | The date and time of the incident’s last activity. |
| AzureSentinel.Incident.LastModifiedTimeUTC | Date | The date and time the incident was last modified. |
| AzureSentinel.Incident.CreatedTimeUTC | Date | The date and time the incident was created. |
| AzureSentinel.Incident.IncidentNumber | Number | The incident number. |
| AzureSentinel.Incident.AlertsCount | Number | The number of the alerts in the incident. |
| AzureSentinel.Incident.BookmarkCount | Number | The number of bookmarks in the incident. |
| AzureSentinel.Incident.CommentCount | Number | The number of comments in the incident. |
| AzureSentinel.Incident.AlertProductNames | String | The alert product names of the incident. |
| AzureSentinel.Incident.Tactics | String | The incident’s tactics. |
| AzureSentinel.Incident.FirstActivityTimeGenerated | Date | The incident’s generated first activity time. |
| AzureSentinel.Incident.LastActivityTimeGenerated | Date | The incident’s generated last activity time. |
| AzureSentinel.Incident.Etag | String | The Etag of the incident. |
Command Example
!azure-sentinel-create-incident severity=Low status=New title=test description=testing labels=[{\"labelName\":\"value\"}]
Context Example
{
"AzureSentinel": {
"Incident": {
"ID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"IncidentNumber": 2,
"IncidentUrl": "https://portal.azure.com/#asset/Microsoft_Azure_Security_Insights/Incident/subscriptions/xxxxxx/resourceGroups/xxxxxx/providers/Microsoft.OperationalInsights/workspaces/xxxxxx/providers/Microsoft.SecurityInsights/Incidents/8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Title": "test",
"Description": "testing",
"Severity": "Low",
"Status": "New",
"AssigneeName": null,
"AssigneeEmail": null,
"AssigneeObjectID": null,
"AssigneeUPN": null,
"Label": [
{
"Name": "value",
"Type": "User"
}
],
"FirstActivityTimeUTC": null,
"LastActivityTimeUTC": null,
"LastModifiedTimeUTC": "2021-08-23T13:30:49Z",
"CreatedTimeUTC": "2021-08-23T13:30:49Z",
"AlertsCount": 0,
"BookmarksCount": 0,
"CommentsCount": 0,
"AlertProductNames": [],
"ProviderIncidentUrl": null,
"Tactics": [],
"Techniques": [],
"FirstActivityTimeGenerated": null,
"LastActivityTimeGenerated": null,
"Etag": "\"3700fdde-0000-3d00-0000-67c6dadc0000\"",
"Deleted": false
}
}
}
Human Readable Output
Created incidents 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 details
ID Incident Number Title Description Severity Status Incident Url Label Last Modified Time UTC Created Time UTC Alerts Count Bookmarks Count Comments Count 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 2 test testing Low New https://portal.azure.com/#asset/Microsoft_Azure_Security_Insights/Incident/subscriptions/xxxxxx/resourceGroups/xxxxxx/providers/Microsoft.OperationalInsights/workspaces/xxxxxx/providers/Microsoft.SecurityInsights/Incidents/2b43defc-6c4b-434f-a152-6bdca46b6ef3 {‘Name’: ‘value’, ‘Type’: ‘User’} 2021-08-23T13:30:49Z 2021-08-23T13:30:49Z 0 0 0
azure-sentinel-delete-incident
Deletes a single incident in Azure Sentinel.
Base Command
azure-sentinel-delete-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
There is no context output for this command.
Command Example
!azure-sentinel-delete-incident incident_id=c90cc84d-a95e-47a0-9478-89ebc9ee22fd
Context Example
{
"AzureSentinel": {
"Incident": {
"Deleted": true,
"ID": "c90cc84d-a95e-47a0-9478-89ebc9ee22fd"
}
}
}
Human Readable Output
Incident c90cc84d-a95e-47a0-9478-89ebc9ee22fd was deleted successfully.
azure-sentinel-list-incident-comments
Gets the comments of an incident from Azure Sentinel.
Base Command
azure-sentinel-list-incident-comments
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| limit | The maximum number of incident comments to return. The maximum value is 50. Default is 50. | Optional |
| next_link | A link that specifies a starting point to use for subsequent calls. Using this argument overrides all of the other command arguments. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.IncidentComment.ID | String | The ID of the incident comment. |
| AzureSentinel.IncidentComment.IncidentID | String | The incident ID. |
| AzureSentinel.IncidentComment.Message | String | The incident’s comment. |
| AzureSentinel.IncidentComment.AuthorName | String | The name of the author of the incident’s comment. |
| AzureSentinel.IncidentComment.AuthorEmail | String | The email address of the author of the incident comment. |
| AzureSentinel.IncidentComment.CreatedTimeUTC | Date | The date and time that the incident comment was created. |
| AzureSentinel.NextLink.Description | String | Description of NextLink. |
| AzureSentinel.NextLink.URL | String | Used if an operation returns a partial result. If a response contains a NextLink element, its value specifies a starting point to use for subsequent calls. |
Command Example
!azure-sentinel-list-incident-comments incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742
Context Example
{
"AzureSentinel": {
"IncidentComment": [
{
"AuthorEmail": null,
"AuthorName": null,
"CreatedTimeUTC": "2021-08-23T13:30:42Z",
"ID": "231020399272240422047777436922721687523",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Message": "test messages"
},
{
"AuthorEmail": null,
"AuthorName": null,
"CreatedTimeUTC": "2021-08-23T13:26:26Z",
"ID": "251456744761940512356246980948458722890",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Message": "test messages"
},
{
"AuthorEmail": null,
"AuthorName": null,
"CreatedTimeUTC": "2021-08-12T10:57:44Z",
"ID": "152909182848719872520422267385960967748",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Message": "test messages"
},
{
"AuthorEmail": "test@test.com",
"AuthorName": null,
"CreatedTimeUTC": "2020-04-05T12:14:13Z",
"ID": "307866023137611282164566423986768628663",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Message": "hello world"
}
]
}
}
Human Readable Output
Incident 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 Comments (4 results)
ID Incident ID Message Author Email Created Time UTC 231020399272240422047777436922721687523 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 test messages 2021-08-23T13:30:42Z 251456744761940512356246980948458722890 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 test messages 2021-08-23T13:26:26Z 152909182848719872520422267385960967748 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 test messages 2021-08-12T10:57:44Z 307866023137611282164566423986768628663 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 hello world test@test.com 2020-04-05T12:14:13Z
azure-sentinel-incident-add-comment
Adds a comment to an incident in Azure Sentinel.
Base Command
azure-sentinel-incident-add-comment
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| message | The comment message. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.IncidentComment.ID | String | The ID of the incident comment. |
| AzureSentinel.IncidentComment.IncidentID | String | The incident ID. |
| AzureSentinel.IncidentComment.Message | String | The incident’s comment. |
| AzureSentinel.IncidentComment.AuthorName | String | The name of the author of the incident’s comment. |
| AzureSentinel.IncidentComment.AuthorEmail | String | The email address of the author of the incident comment. |
| AzureSentinel.IncidentComment.CreatedTimeUTC | Date | The date and time that the incident comment was created. |
Command Example
!azure-sentinel-incident-add-comment incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 message="test messages"
Context Example
{
"AzureSentinel": {
"IncidentComment": {
"AuthorEmail": null,
"AuthorName": null,
"CreatedTimeUTC": "2021-08-23T13:30:42Z",
"ID": "231020399272240422047777436922721687523",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Message": "test messages"
}
}
}
Human Readable Output
Incident 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 new comment details
ID Incident ID Message Created Time UTC 231020399272240422047777436922721687523 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 test messages 2021-08-23T13:30:42Z
azure-sentinel-incident-delete-comment
Deletes a comment from incident in Azure Sentinel.
Base Command
azure-sentinel-incident-delete-comment
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| comment_id | The comment ID. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
There is no context output for this command.
Command Example
!azure-sentinel-incident-delete-comment incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 comment_id="296745069631925005023508651351426"
Human Readable Output
Comment 296745069631925005023508651351426 was deleted successfully.
azure-sentinel-list-incident-relations
Gets a list of an incident’s related entities from Azure Sentinel.
Base Command
azure-sentinel-list-incident-relations
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| limit | The maximum number of related entities to return. Default is 50. | Optional |
| next_link | A link that specifies a starting point to use for subsequent calls. Using this argument overrides all of the other command arguments. | Optional |
| entity_kinds | A comma-separated list of entity kinds to filter by. By default, the results won’t be filtered by kind. The optional kinds are: Account, Host, File, AzureResource, CloudApplication, DnsResolution, FileHash, Ip, Malware, Process, RegistryKey, RegistryValue, SecurityGroup, Url, IoTDevice, SecurityAlert, Bookmark. |
Optional |
| filter | Filter results using OData syntax. For example: properties/createdTimeUtc gt 2020-02-02T14:00:00Z`). For more information see the Azure documentation: https://docs.microsoft.com/bs-latn-ba/azure/search/search-query-odata-filter. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.IncidentRelatedResource.ID | String | The ID of the incident’s related resource. |
| AzureSentinel.IncidentRelatedResource.Kind | String | The kind of the incident’s related resource. |
| AzureSentinel.NextLink.Description | String | The description about NextLink. |
| AzureSentinel.NextLink.URL | String | Used if an operation returns a partial result. If a response contains a NextLink element, its value specifies a starting point to use for subsequent calls. |
| AzureSentinel.IncidentRelatedResource.IncidentID | String | The incident ID. |
Command Example
!azure-sentinel-list-incident-relations incident_id=8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742
Context Example
{
"AzureSentinel": {
"IncidentRelatedResource": {
"ID": "bfb02efc-12b7-4147-a8e8-961338b1b834",
"IncidentID": "8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742",
"Kind": "SecurityAlert"
}
}
}
Human Readable Output
Incident 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 Relations (1 results)
ID Incident ID Kind bfb02efc-12b7-4147-a8e8-961338b1b834 8a44b7bb-c8ae-4941-9fa0-3aecc8ef1742 SecurityAlert
azure-sentinel-list-incident-entities
Gets a list of an incident’s entities from Azure Sentinel.
Base Command
azure-sentinel-list-incident-entities
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.IncidentEntity.ID | String | The ID of the entity. |
| AzureSentinel.IncidentEntity.IncidentId | String | The ID of the incident. |
| AzureSentinel.IncidentEntity.Kind | String | The kind of the entity. |
| AzureSentinel.IncidentEntity.Properties | Unknown | The properties of the entity. |
Command Example
!azure-sentinel-list-incident-entities incident_id=65d8cbc0-4e4d-4acb-ab7e-8aa19936002c
Context Example
{
"AzureSentinel": {
"IncidentEntity": {
"ID": "176567ab-1ccc-8a53-53bf-97958a78d3b5",
"IncidentId": "65d8cbc0-4e4d-4acb-ab7e-8aa19936002c",
"Kind": "Account",
"Properties": {
"aadTenantId": "176567ab-1ccc-8a53-53bf-97958a78d3b5",
"aadUserId": "176567ab-1ccc-8a53-53bf-97958a78d3b5",
"accountName": "test_user_1",
"additionalData": {
"AdditionalMailAddresses": "[\"test@test.com\"]",
"City": "SantaClara",
"Country": "United States",
"GivenName": "test_name",
"IsDeleted": "False",
"IsEnabled": "True",
"JobTitle": "test",
"MailAddress": "test@test.com",
"ManagerName": "test_manager",
"Sources": "[\"AzureActiveDirectory\"]",
"State": "California",
"StreetAddress": "test address",
"Surname": "test_name",
"SyncFromAad": "True",
"TransitiveDirectoryRoles": "[\"Global Administrator\"]",
"TransitiveGroupsMembership": "[\"kkk\"]",
"UpnName": "test",
"UserType": "Member"
},
"displayName": "Test Name",
"friendlyName": "Test Name",
"isDomainJoined": true,
"upnSuffix": "test.com"
}
}
}
}
Human Readable Output
Incident 65d8cbc0-4e4d-4acb-ab7e-8aa19936002c Entities (1 results)
ID Kind Incident Id 176567ab-1ccc-8a53-53bf-97958a78d3b5 Account 65d8cbc0-4e4d-4acb-ab7e-8aa19936002c
azure-sentinel-list-incident-alerts
Gets a list of an incident’s alerts from Azure Sentinel.
Base Command
azure-sentinel-list-incident-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.IncidentAlert.ID | String | The ID of the alert. |
| AzureSentinel.IncidentAlert.IncidentId | String | The ID of the incident. |
| AzureSentinel.IncidentAlert.Kind | String | The kind of the alert. |
| AzureSentinel.IncidentAlert.Tactic | Unknown | The tactics of the alert. |
| AzureSentinel.IncidentAlert.Techniques | Unknown | The Techniques of the alert. |
| AzureSentinel.IncidentAlert.DisplayName | String | The display name of the alert. |
| AzureSentinel.IncidentAlert.Description | String | The description of the alert. |
| AzureSentinel.IncidentAlert.ConfidenceLevel | String | The confidence level of this alert. |
| AzureSentinel.IncidentAlert.Severity | String | The severity of the alert. |
| AzureSentinel.IncidentAlert.VendorName | String | The name of the vendor that raised the alert. |
| AzureSentinel.IncidentAlert.ProductName | String | The name of the product that published this alert. |
| AzureSentinel.IncidentAlert.ProductComponentName | String | The name of a component inside the product which generated the alert. |
Command Example
!azure-sentinel-list-incident-alerts incident_id=25c9ddf4-d951-4b67-9381-172f953feb57
Context Example
{
"AzureSentinel": {
"IncidentAlert": {
"ConfidenceLevel": "Unknown",
"Description": "",
"DisplayName": "Test rule",
"ID": "f3319e38-3f5b-a1eb-9970-69679dcdf916",
"IncidentId": "25c9ddf4-d951-4b67-9381-172f953feb57",
"Kind": "SecurityAlert",
"ProductComponentName": "Scheduled Alerts",
"ProductName": "Azure Sentinel",
"Severity": "Medium",
"Tactic": [
"InitialAccess",
"Persistence",
"PrivilegeEscalation",
"DefenseEvasion",
"CredentialAccess",
"Discovery",
"LateralMovement",
"Execution",
"Collection",
"Exfiltration",
"CommandAndControl",
"Impact"
],
"VendorName": "Microsoft"
}
}
}
Human Readable Output
Incident 25c9ddf4-d951-4b67-9381-172f953feb57 Alerts (1 results)
ID Kind Incident Id f3319e38-3f5b-a1eb-9970-69679dcdf916 SecurityAlert 25c9ddf4-d951-4b67-9381-172f953feb57
azure-sentinel-list-watchlist-items
Get a single watchlist item or list of watchlist items.
Base Command
azure-sentinel-list-watchlist-items
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | The alias of the watchlist. | Required |
| watchlist_item_id | The ID of the single watchlist item. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.WatchlistItem.WatchlistAlias | String | The alias of the watchlist. |
| AzureSentinel.WatchlistItem.ID | String | The ID (GUID) of the watchlist item. |
| AzureSentinel.WatchlistItem.Created | Date | The time the watchlist item was created. |
| AzureSentinel.WatchlistItem.Updated | Date | The last time the watchlist item was updated. |
| AzureSentinel.WatchlistItem.CreatedBy | String | The name of the user. |
| AzureSentinel.WatchlistItem.UpdatedBy | String | The user who updated this item. |
| AzureSentinel.WatchlistItem.ItemsKeyValue | Unknown | Key-value pairs for a watchlist item. |
Command Example
!azure-sentinel-list-watchlist-items watchlist_alias=test_4
Context Example
{
"AzureSentinel": {
"WatchlistItem": [
{
"Created": "2021-08-23T13:30:53Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"ID": "28bd8f55-131b-42e6-bd5d-33d30f2d1291",
"ItemsKeyValue": {
"IP": "1.2.3.4",
"name": "test1"
},
"Name": "28bd8f55-131b-42e6-bd5d-33d30f2d1291",
"Updated": "2021-08-23T13:30:53Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"WatchlistAlias": "test_4"
},
{
"Created": "2021-08-23T13:30:53Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"ID": "510d8f80-99ad-441d-87f3-88341cc8b439",
"ItemsKeyValue": {
"IP": "1.2.3.5",
"name": "test2"
},
"Name": "510d8f80-99ad-441d-87f3-88341cc8b439",
"Updated": "2021-08-23T13:30:53Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"WatchlistAlias": "test_4"
}
]
}
}
Human Readable Output
Watchlist items results
ID Items Key Value 28bd8f55-131b-42e6-bd5d-33d30f2d1291 name: test1
IP: 1.2.3.4510d8f80-99ad-441d-87f3-88341cc8b439 name: test2
IP: 1.2.3.5
azure-sentinel-delete-watchlist-item
Delete a watchlist item.
Base Command
azure-sentinel-delete-watchlist-item
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | The watchlist alias. | Required |
| watchlist_item_id | The watchlist item ID to be deleted. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
There is no context output for this command.
Command Example
!azure-sentinel-delete-watchlist-item watchlist_alias=test_2 watchlist_item_id=96c326c6-2dea-403c-94bd-6a005921c3c1
Human Readable Output
Watchlist item 96c326c6-2dea-403c-94bd-6a005921c3c1 was deleted successfully.
azure-sentinel-create-update-watchlist-item
Create or update a watchlist item.
Base Command
azure-sentinel-create-update-watchlist-item
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist_alias | The watchlist alias. | Required |
| watchlist_item_id | The watchlist item ID (GUID) to update. | Optional |
| item_key_value | The JSON for the itemsKeyValue of the item (the key value is different from watchlist to watchlist). | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.WatchlistItem.WatchlistAlias | String | The alias of the watchlist. |
| AzureSentinel.WatchlistItem.ID | String | The ID (GUID) of the watchlist item. |
| AzureSentinel.WatchlistItem.Created | Date | The time the watchlist item was created. |
| AzureSentinel.WatchlistItem.Updated | Date | The last time the watchlist item was updated. |
| AzureSentinel.WatchlistItem.CreatedBy | String | The name of the user who created this watchlist item. |
| AzureSentinel.WatchlistItem.UpdatedBy | String | The user who updated this watchlist item. |
| AzureSentinel.WatchlistItem.ItemsKeyValue | Unknown | Key-value pairs for a watchlist item. |
Command Example
!azure-sentinel-create-update-watchlist-item watchlist_alias=test_4 item_key_value=`{"name": "test_4_item", "IP": "4.4.4.4"}`
Context Example
{
"AzureSentinel": {
"WatchlistItem": {
"Created": "2021-08-23T13:30:59Z",
"CreatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"ID": "6b21d1ef-18fa-420f-ae4a-a6f94588ebe8",
"ItemsKeyValue": {
"IP": "4.4.4.4",
"name": "test_4_item"
},
"Name": "6b21d1ef-18fa-420f-ae4a-a6f94588ebe8",
"Updated": "2021-08-23T13:30:59Z",
"UpdatedBy": "78e658fe-3ff0-4785-80e7-ef089a3d6bdd",
"WatchlistAlias": "test_4"
}
}
}
Human Readable Output
Create watchlist item results
ID Items Key Value 6b21d1ef-18fa-420f-ae4a-a6f94588ebe8 name: test_4_item
IP: 4.4.4.4
azure-sentinel-threat-indicator-list
Returns a list of threat indicators.
Base Command
azure-sentinel-threat-indicator-list
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_name | The name of the indicator. | Optional |
| limit | The maximum number of indicators to return. Default is 50. | Optional |
| next_link | A link that specifies a starting point to use for subsequent calls. This argument overrides all of the other command arguments. |
Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Whether the threat indicator was revoked. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | Unknown | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-list limit=2
Human Readable Output
Threat Indicators (2 results)
| Name | Display Name | Values | Types | Source | Tags |
|---|---|---|---|---|---|
| a31f2257-1af5-5eb9-bc82-acb8cc10becd | Name | test.value | malicious-activity | Azure Sentinel | Tag |
| 1286115b-3b65-5537-e831-969045792910 | DisplayName | domain.dot | benign | Azure Sentinel | No Tags |
azure-sentinel-threat-indicator-query
Returns a list of threat indicators with specific entities.
Base Command
azure-sentinel-threat-indicator-query
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of indicators to return. Default is 50. | Optional |
| next_link | A link that specifies a starting point to use for subsequent calls. This argument overrides all of the other command arguments. There may be no support for pagination. |
Optional |
| min_confidence | The minimum confidence number for a threat indicator. | Optional |
| max_confidence | The maximum confidence number for a threat indicator. | Optional |
| min_valid_until | Minimum valid until value of indicators to query. | Optional |
| max_valid_until | Maximum valid until value of indicators to query. | Optional |
| include_disabled | If true, the query also returns disabled indicators. Possible values are: true, false. Default is false. | Optional |
| sources | The sources of the threat indicator. | Optional |
| indicator_types | The indicator types of the threat indicator. Possible values are: ipv4, ipv6, file, url, domain. | Optional |
| threat_types | A comma-separated list of threat types of the threat indicator. Possible values are: anomalous-activity, attribution, anonymization, benign, malicious-activity, compromised, unknown. | Optional |
| keywords | A comma-separated list of keywords. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Whether the threat indicator was revoked. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | String | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-query max_confidence=70
Human Readable Output
Threat Indicators (2 results)
| Name | Display Name | Values | Types | Source | Confidence | Tags |
|---|---|---|---|---|---|---|
| a31f2257-1af5-5eb9-bc82-acb8cc10becd | DisplayName | domain.dot | compromised | Azure Sentinel | 50 | newTag |
| 1286115b-3b65-5537-e831-969045792910 | Name | test.dot | compromised | Azure Sentinel | 68 | No Tags |
azure-sentinel-threat-indicator-create
Creates a new threat indicator.
Base Command
azure-sentinel-threat-indicator-create
Input
| Argument Name | Description | Required |
|---|---|---|
| value | The value of the threat indicator. | Required |
| display_name | The display name of the new indicator. | Required |
| description | The description of the new indicator. | Optional |
| indicator_type | The type of the new indicator. Possible values are: ipv4, ipv6, file, url, domain. | Required |
| hash_type | The hash type of the new indicator. This argument is mandatory if the indicator type is file. Possible values are: MD5, SHA-1, SHA-256, SHA-512. | Optional |
| confidence | The confidence of the new threat indicator. Should be a number between 0-100. | Optional |
| threat_types | A comma-separated list of threat types of the threat indicator. Possible values are: anomalous-activity, attribution, anonymization, benign, malicious-activity, compromised, unknown. | Required |
| kill_chains | The kill chains phases of the indicator. | Optional |
| tags | A comma-separated list of tags of the new threat indicator. | Optional |
| valid_from | The date from which the indicator is valid. | Optional |
| valid_until | The date until which the indicator is valid. | Optional |
| created_by | The creator of the new indicator. | Optional |
| revoked | If true, the indicator is revoked. Possible values are: true, false. Default is false. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Whether the threat indicator was revoked. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | String | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-create display_name=name indicator_type=domain threat_types=benign value=good.test confidence=77
Human Readable Output
New threat Indicator was created
| Name | Display Name | Values | Types | Source | Confidence | Tags |
|---|---|---|---|---|---|---|
| a31f2257-1af5-5eb9-bc82-acb8cc10becd | name | good.test | benign | Azure Sentinel | 77 | No Tags |
azure-sentinel-threat-indicator-update
Updates an existing threat indicator.
Base Command
azure-sentinel-threat-indicator-update
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_name | The name of the indicator. | Required |
| value | The value of the indicator. | Required |
| description | The description of the threat indicator. | Optional |
| indicator_type | The type of the indicator. Possible values are: ipv4, ipv6, file, url, domain. | Required |
| hash_type | If indicator_type is a file, this entry is mandatory. | Optional |
| revoked | Whether the indicator is revoked. | Optional |
| confidence | The confidence of the threat indicator. This is a number between 0-100. | Optional |
| threat_types | A comma-separated list of threat types of the threat indicator. Possible values are: anomalous-activity, attribution, anonymization, benign, malicious-activity, compromised, unknown. | Optional |
| kill_chains | A comma-separated list of kill chains phases of the indicator. | Optional |
| tags | A comma-separated list of tags of the threat indicator. | Optional |
| valid_from | The date from which the indicator is valid. | Optional |
| valid_until | The date until which the indicator is valid. | Optional |
| created_by | The creator of the indicator. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Was the threat indicator revoked or not. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | String | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-update indicator_name=a31f2257-1af5-5eb9-bc82-acb8cc10becd display_name=WeChangedTheDisplayName indicator_type="domain-name" value=verynew.value
Human Readable Output
Threat Indicator a31f2257-1af5-5eb9-bc82-acb8cc10becd was updated
| Name | Display Name | Values | Types | Source | Tags |
|---|---|---|---|---|---|
| a31f2257-1af5-5eb9-bc82-acb8cc10becd | WeChangedTheDisplayName | verynew.value | malicious-activity | Azure Sentinel | ReplaceTheTag |
azure-sentinel-threat-indicator-delete
Deletes an existing threat indicator.
Base Command
azure-sentinel-threat-indicator-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_names | A comma-separated list of indicators to delete. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
There is no context output for this command.
Command Example
!azure-sentinel-threat-indicator-delete indicator_names=1286115b-3b65-5537-e831-969045792910
Human Readable Output
Threat Intelligence Indicators 1286115b-3b65-5537-e831-969045792910 were deleted successfully.
azure-sentinel-threat-indicator-tags-append
Appends new tags to an existing indicator.
Base Command
azure-sentinel-threat-indicator-tags-append
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_name | The name of the indicator. | Required |
| tags | A comma-separated list of tags to append. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Was the threat indicator revoked or not. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | String | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-tags-append indicator_name=1286115b-3b65-5537-e831-969045792910 tags=newtag
Human Readable Output
Tags were appended to 1286115b-3b65-5537-e831-969045792910 Threat Indicator.
azure-sentinel-threat-indicator-tags-replace
Replaces the tags of a given indicator.
Base Command
azure-sentinel-threat-indicator-tags-replace
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_name | The name of the indicator. | Required |
| tags | A comma-separated list of tags to replace. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ThreatIndicator.ID | String | The ID of the indicator. |
| AzureSentinel.ThreatIndicator.Name | String | The name of the indicator. |
| AzureSentinel.ThreatIndicator.ETag | String | The ETag of the indicator. |
| AzureSentinel.ThreatIndicator.Type | String | The type of the indicator. |
| AzureSentinel.ThreatIndicator.Kind | String | The kind of the indicator. |
| AzureSentinel.ThreatIndicators.Confidence | Number | The confidence of the threat indicator. This is a number between 0-100. |
| AzureSentinel.ThreatIndicator.Created | Date | When the threat indicator was created. |
| AzureSentinel.ThreatIndicator.CreatedByRef | String | The creator of the indicator. |
| AzureSentinel.ThreatIndicator.ExternalID | String | The external ID of the indicator. |
| AzureSentinel.ThreatIndicator.Revoked | Boolean | Whether the threat indicator was revoked. |
| AzureSentinel.ThreatIndicator.Source | String | The source of the indicator. |
| AzureSentinel.ThreatIndicator.ETags | String | The Etags of the indicator. |
| AzureSentinel.ThreatIndicator.DisplayName | String | The display name of the indicator. |
| AzureSentinel.ThreatIndicator.Description | String | The description of the indicator. |
| AzureSentinel.ThreatIndicator.ThreatTypes | Unknown | The threat types of the indicator. |
| AzureSentinel.ThreatIndicator.KillChainPhases.KillChainName | String | The kill chain’s name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeKey | Unknown | The pattern type key of the indicator. |
| AzureSentinel.ThreatIndicator.Pattern | String | The pattern of the indicator. |
| AzureSentinel.ThreatIndicator.PatternType | String | The pattern type of the indicator. |
| AzureSentinel.ThreatIndicator.ValidFrom | Date | The date from which the indicator is valid. |
| AzureSentinel.ThreatIndicator.ValidUntil | Date | The date until which the indicator is valid. |
| AzureSentinel.ThreatIndicator.KillChainPhases.PhaseName | String | The phase name of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.Value | String | The value of the indicator. |
| AzureSentinel.ThreatIndicator.ParsedPattern.PatternTypeValues.ValueType | String | The value type of the indicator. |
| AzureSentinel.ThreatIndicator.LastUpdatedTimeUtc | Date | The last updated time of the indicator. |
| AzureSentinel.ThreatIndicator.Tags | Unknown | The tags of the indicator. |
| AzureSentinel.ThreatIndicator.Types | Unknown | The threat types of the indicator. |
Command Example
!azure-sentinel-threat-indicator-tags-replace name=1286115b-3b65-5537-e831-969045792910 tags=newtag
Human Readable Output
Tags were replaced to 1286115b-3b65-5537-e831-969045792910 Threat Indicator.
azure-sentinel-list-alert-rule
Gets a list of all alert rules.
Base Command
azure-sentinel-list-alert-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | The rule ID. If not given, will return all rules. | Optional |
| limit | The maximum number of rules to return. Default is 50. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.AlertRule.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.AlertRule.name | String | The name of the resource. |
| AzureSentinel.AlertRule.type | String | The type of the resource. |
| AzureSentinel.AlertRule.kind | String | The alert rule kind. |
| AzureSentinel.AlertRule.etag | String | ETag of the Azure resource. |
| AzureSentinel.AlertRule.properties.alertRuleTemplateName | Unknown | The name of the alert rule template used to create this rule. |
| AzureSentinel.AlertRule.properties.displayName | String | The display name for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.description | String | The description of the alert rule. |
| AzureSentinel.AlertRule.properties.severity | String | The severity for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.enabled | Boolean | Determines whether this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.tactics | String | The tactics of the alert rule. |
| AzureSentinel.AlertRule.properties.query | String | The query that creates alerts for this rule. |
| AzureSentinel.AlertRule.properties.queryFrequency | String | The frequency (in ISO 8601 duration format) for this alert rule to run. |
| AzureSentinel.AlertRule.properties.queryPeriod | String | The period (in ISO 8601 duration format) that this alert rule looks at. |
| AzureSentinel.AlertRule.properties.triggerOperator | String | The operation against the threshold that triggers the alert rule. |
| AzureSentinel.AlertRule.properties.triggerThreshold | Number | The threshold that triggers this alert rule. |
| AzureSentinel.AlertRule.properties.suppressionDuration | String | The suppression (in ISO 8601 duration format) to wait since the last time this alert rule was triggered. |
| AzureSentinel.AlertRule.properties.suppressionEnabled | Boolean | Determines whether the suppression for this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.lastModifiedUtc | Date | The last time this alert rule was modified. |
| AzureSentinel.AlertRule.properties.eventGroupingSettings.aggregationKind | String | The event grouping aggregation kinds. |
| AzureSentinel.AlertRule.properties.entityMappings.entityType | String | The V3 type of the mapped entity. |
| AzureSentinel.AlertRule.properties.entityMappings.fieldMappings.identifier | String | The V3 identifier of the entity. |
| AzureSentinel.AlertRule.properties.entityMappings.fieldMappings.columnName | String | The column name to be mapped to the identifier. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride.alertDisplayNameFormat | String | The format containing the columns’ name(s) used to override the alert name. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride.alertDescriptionFormat | String | The format containing columns’ name(s) used to override the alert description. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride.alertTacticsColumnName | Unknown | The column name to take the alert tactics from. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride.alertSeverityColumnName | Unknown | The column name to take the alert severity from. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.createIncident | Boolean | Create incidents from alerts triggered by this analytics rule. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.enabled | Boolean | Whether grouping is enabled. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.reopenClosedIncident | Boolean | Re-open closed matching incidents. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.lookbackDuration | String | Limit the group to alerts created within the lookback duration (in ISO 8601 duration format). |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.matchingMethod | String | Grouping matching method. When method is Selected at least one of groupByEntities, groupByAlertDetails, groupByCustomDetails must be provided and not empty. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.groupByEntities | String | A list of entity types to group by (when matchingMethod is Selected). Only entities defined in the current alert rule may be used. |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.groupByAlertDetails | String | A list of alert details to group by (when matchingMethod is Selected). |
| AzureSentinel.AlertRule.properties.incidentConfiguration.groupingConfiguration.groupByCustomDetails | String | A list of custom details keys to group by (when matchingMethod is Selected). Only keys defined in the current alert rule may be used. |
| AzureSentinel.AlertRule.properties.productFilter | String | The alerts’ productName on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.severitiesFilter | Unknown | The alerts’ severities on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.displayNamesFilter | Unknown | The alerts’ displayNames on which the cases will be generated |
Command example
!azure-sentinel-list-alert-rule limit=1
Context Example
{
"AzureSentinel": {
"AlertRule": {
"etag": "\"0000-0100-0000\"",
"id": "/subscriptions/{subscription_id}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/test-rule-id",
"kind": "Scheduled",
"name": "test-rule-id",
"properties": {
"alertRuleTemplateName": null,
"description": null,
"displayName": "testing displayname",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "Account",
"identifier": "FullName"
}
]
},
{
"entityType": "Host",
"fieldMappings": [
{
"columnName": "Computer",
"identifier": "FullName"
}
]
}
],
"eventGroupingSettings": {
"aggregationKind": "AlertPerResult"
},
"incidentConfiguration": {
"createIncident": true,
"groupingConfiguration": {
"enabled": false,
"groupByAlertDetails": null,
"groupByCustomDetails": null,
"groupByEntities": [],
"lookbackDuration": "PT5H",
"matchingMethod": "AllEntities",
"reopenClosedIncident": false
}
},
"lastModifiedUtc": "2020-03-28T16:07:49.1905911Z",
"query": "Heartbeat",
"queryFrequency": "PT1M",
"queryPeriod": "P2DT1H30M",
"severity": "Low",
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Persistence"
],
"techniques": [
"T11"
],
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.SecurityInsights/alertRules"
}
}
}
Human Readable Output
Azure Sentinel Alert Rules
ID Kind Severity Display Name Description Enabled test-rule-id Scheduled Low testing displayname true
azure-sentinel-list-alert-rule-template
Gets a list of all alert rule templates.
Base Command
azure-sentinel-list-alert-rule-template
Input
| Argument Name | Description | Required |
|---|---|---|
| template_id | The alert rule template ID. If not given, will return all alert rule templates. | Optional |
| limit | The maximum number of templates to return. Default is 50. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.AlertRuleTemplate.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.AlertRuleTemplate.name | String | The name of the resource. |
| AzureSentinel.AlertRuleTemplate.type | String | The type of the resource. |
| AzureSentinel.AlertRuleTemplate.kind | String | The alert rule kind. |
| AzureSentinel.AlertRuleTemplate.properties.severity | String | The severity for alerts created by this alert rule. |
| AzureSentinel.AlertRuleTemplate.properties.query | String | The query that creates alerts for this rule. |
| AzureSentinel.AlertRuleTemplate.properties.queryFrequency | String | The frequency (in ISO 8601 duration format) for this alert rule to run. |
| AzureSentinel.AlertRuleTemplate.properties.queryPeriod | String | The period (in ISO 8601 duration format) that this alert rule looks at. |
| AzureSentinel.AlertRuleTemplate.properties.triggerOperator | String | The operation against the threshold that triggers alert rule. |
| AzureSentinel.AlertRuleTemplate.properties.triggerThreshold | Number | The threshold that triggers this alert rule. |
| AzureSentinel.AlertRuleTemplate.properties.displayName | String | The display name for the alert rule template. |
| AzureSentinel.AlertRuleTemplate.properties.description | String | The description of the alert rule template. |
| AzureSentinel.AlertRuleTemplate.properties.tactics | String | The tactics of the alert rule template. |
| AzureSentinel.AlertRuleTemplate.properties.lastUpdatedDateUTC | Date | The time this alert rule template was last updated. |
| AzureSentinel.AlertRuleTemplate.properties.createdDateUTC | Date | The time this alert rule template was added. |
| AzureSentinel.AlertRuleTemplate.properties.status | String | The alert rule template status. |
| AzureSentinel.AlertRuleTemplate.properties.version | String | The version of this template in the format <a.b.c>, where all are numbers. For example <1.0.2>. |
| AzureSentinel.AlertRuleTemplate.properties.requiredDataConnectors.connectorId | String | The connector ID that provides the following data types |
| AzureSentinel.AlertRuleTemplate.properties.requiredDataConnectors.dataTypes | String | The data types used by the alert rule template. |
| AzureSentinel.AlertRuleTemplate.properties.alertRulesCreatedByTemplateCount | Number | The number of alert rules that were created by this template. |
| AzureSentinel.AlertRuleTemplate.properties.productFilter | String | The alerts’ productName on which the cases will be generated. |
Command example
!azure-sentinel-list-alert-rule-template limit=1
Context Example
{
"AzureSentinel": {
"AlertRuleTemplate": {
"id": "/subscriptions/{subscription_id}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/AlertRuleTemplates/test-rule-template-id",
"kind": "Scheduled",
"name": "test-rule-template-id",
"properties": {
"severity": "Low",
"query": "let timeframe = 1d;\nAWSCloudTrail\n| where TimeGenerated >= ago(timeframe)\n| where EventName == \"CreateNetworkAclEntry\"\n or EventName == \"CreateRoute\"\n| project TimeGenerated, EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid, UserAgent, UserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress, AWSRegion, EventSource, AdditionalEventData, ResponseElements\n| extend AccountCustomEntity = UserIdentityUserName, IPCustomEntity = SourceIpAddress",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0,
"displayName": "Changes to Amazon VPC settings",
"description": "This alert monitors changes to Amazon VPC (Virtual Private Cloud) settings such as new ACL entries and routes in route tables.\nMore information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255 \nand https://aws.amazon.com/vpc/",
"tactics": [
"PrivilegeEscalation",
"LateralMovement"
],
"lastUpdatedDateUTC": "2021-02-27T10:00:00Z",
"createdDateUTC": "2019-02-27T00:00:00Z",
"status": "Available",
"version": "1.0.1",
"requiredDataConnectors": [
{
"connectorId": "AWS",
"dataTypes": [
"AWSCloudTrail"
]
}
],
"alertRulesCreatedByTemplateCount": 0
},
"type": "Microsoft.SecurityInsights/AlertRuleTemplates"
}
}
}
Human Readable Output
Azure Sentinel Alert Rule Template
ID Kind Severity Display Name Description Status Created Date UTC Last Updated Date UTC Alert Rules Created By Template Count test-rule-template-id Scheduled Low Changes to Amazon VPC settings This alert monitors changes to Amazon VPC (Virtual Private Cloud) settings such as new ACL entries and routes in route tables.
More information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255
and https://aws.amazon.com/vpc/Available 2019-02-27T00:00:00Z 2021-02-27T10:00:00Z 0
azure-sentinel-delete-alert-rule
Deletes the specified alert rule.
Base Command
azure-sentinel-delete-alert-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | The alert rule ID to delete. | Required |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.AlertRule.ID | String | The alert rule ID. |
| AzureSentinel.AlertRule.Deleted | Boolean | Whether the alert rule was deleted. |
Command example
!azure-sentinel-delete-alert-rule rule_id=1234-abcd-5678-efgh
Context Example
{
"AzureSentinel": {
"AlertRule": {
"Deleted": true,
"ID": "1234-abcd-5678-efgh"
}
}
}
Human Readable Output
Alert rule 1234-abcd-5678-efgh was deleted successfully.
azure-sentinel-create-alert-rule
Creates a new alert rule.
Base Command
azure-sentinel-create-alert-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_name | The alert rule name to create. | Required |
| kind | The alert rule kind to create. Possible values are: fusion, microsoft_security_incident_creation, scheduled. | Optional |
| template_name | The name of the alert rule template used to create this rule. Required for Fusion, optional for Scheduled rules |
Optional |
| enabled | Determines whether this alert rule is enabled or disabled. Possible values are: yes, no. | Optional |
| etag | ETag of the Azure resource. | Optional |
| displayName | The display name for alerts created by this alert rule. Required for MicrosoftSecurityIncidentCreation and scheduled rules |
Optional |
| product_filter | The alerts’ productName on which the cases will be generated. Required for MicrosoftSecurityIncidentCreation rules. Possible values are: azure_active_directory_identity_protection, azure_advanced_threat_protection, azure_security_center, azure_security_center_for_iot, microsoft_cloud_app_security. |
Optional |
| description | The description of the alert rule. Relevant for MicrosoftSecurityIncidentCreation and scheduled rules. |
Optional |
| name_exclude_filter | Alerts’ displayNames on which the cases will not be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| name_include_filter | Alerts’ displayNames on which the cases will be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| severity_filter | Alerts’ severities on which the cases will be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| query | The query that creates alerts for this rule. Required for scheduled rules. |
Optional |
| query_frequency | The frequency (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) for this alert rule to run. Required for scheduled rules. |
Optional |
| query_period | The period (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) that this alert rule looks at. Required for scheduled rules. |
Optional |
| severity | The severity for alerts created by this alert rule. Required for scheduled rules. Possible values are: informational, low, medium, high. |
Optional |
| suppression_duration | The suppression (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) to wait since the last time this alert rule was triggered. Required for scheduled rules. |
Optional |
| suppression_enabled | Determines whether the suppression for this alert rule is enabled or disabled. Required for scheduled rules. Possible values are: yes, no. |
Optional |
| trigger_operator | The operation against the threshold that triggers the alert rule. Required for scheduled rules. Possible values are: equal, greater_than, less_than, not_equal. |
Optional |
| trigger_threshold | The threshold that triggers this alert rule. Required for scheduled rules. |
Optional |
| tactics | The tactics of the alert rule. Relevant for scheduled rules. |
Optional |
| techniques | The techniques of the alert rule. Relevant for scheduled rules. |
Optional |
| rule_json | Option to insert a configured rule JSON instead of using the arguments. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.AlertRule.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.AlertRule.name | String | The name of the resource. |
| AzureSentinel.AlertRule.etag | String | ETag of the Azure resource. |
| AzureSentinel.AlertRule.type | String | The type of the resource, e.g., “Microsoft.Compute/virtualMachines” or “Microsoft.Storage/storageAccounts” |
| AzureSentinel.AlertRule.kind | String | The alert rule kind. |
| AzureSentinel.AlertRule.properties.displayName | String | The display name for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.description | String | The description of the alert rule. |
| AzureSentinel.AlertRule.properties.alertRuleTemplateName | Unknown | The name of the alert rule template used to create this rule. |
| AzureSentinel.AlertRule.properties.tactics | String | The tactics of the alert rule. |
| AzureSentinel.AlertRule.properties.severity | String | The severity for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.enabled | Boolean | Determines whether this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.lastModifiedUtc | Date | The last time that this alert was modified. |
| AzureSentinel.AlertRule.properties.productFilter | String | The alerts’ productName on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.severitiesFilter | Unknown | The alerts’ severities on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.displayNamesFilter | Unknown | The alerts’ displayNames on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.query | String | The query that creates alerts for this rule. |
| AzureSentinel.AlertRule.properties.queryFrequency | String | The frequency (in ISO 8601 duration format) for this alert rule to run. |
| AzureSentinel.AlertRule.properties.queryPeriod | String | The period (in ISO 8601 duration format) that this alert rule looks at. |
| AzureSentinel.AlertRule.properties.triggerOperator | String | The operation against the threshold that triggers the alert rule. |
| AzureSentinel.AlertRule.properties.triggerThreshold | Number | The threshold that triggers this alert rule. |
| AzureSentinel.AlertRule.properties.suppressionDuration | String | The suppression (in ISO 8601 duration format) to wait since the last time this alert rule was triggered. |
| AzureSentinel.AlertRule.properties.suppressionEnabled | Boolean | Determines whether the suppression for this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.eventGroupingSettings | Unknown | The event grouping settings. |
| AzureSentinel.AlertRule.properties.customDetails | Unknown | Dictionary of string key-value pairs of columns to be attached to the alert. |
| AzureSentinel.AlertRule.properties.entityMappings | Unknown | Array of the entity mappings of the alert rule. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride | String | The alert details override settings. |
| AzureSentinel.AlertRule.properties.incidentConfiguration | Unknown | The settings of the incidents that created from alerts triggered by this analytics rule. |
Command example
!azure-sentinel-create-alert-rule enabled=true kind=microsoft_security_incident_creation rule_name=test_name displayName="Testing Display Name" product_filter=microsoft_cloud_app_security
Context Example
{
"AzureSentinel": {
"AlertRule": {
"etag": "\"09009060-0000-5e60000\"",
"id": "/subscriptions/{subscription_id}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/test_name",
"kind": "MicrosoftSecurityIncidentCreation",
"name": "test_name",
"properties": {
"alertRuleTemplateName": null,
"description": null,
"displayName": "Testing Display Name",
"displayNamesExcludeFilter": null,
"displayNamesFilter": null,
"enabled": true,
"lastModifiedUtc": "2023-02-20T10:05:26.5066026Z",
"productFilter": "Microsoft Cloud App Security",
"severitiesFilter": null
},
"type": "Microsoft.SecurityInsights/alertRules"
}
}
}
Human Readable Output
Azure Sentinel Alert Rule successfully created/updated
ID Name Kind Display Name Enabled Etag test_name test_name MicrosoftSecurityIncidentCreation Testing Display Name true “09009060-0000-5e60000”
azure-sentinel-update-alert-rule
Updates an alert rule.
Base Command
azure-sentinel-update-alert-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_name | The alert rule name to update. | Required |
| kind | The alert rule kind to update. Possible values are: fusion, microsoft_security_incident_creation, scheduled. | Optional |
| template_name | The name of the alert rule template used to update this rule. Required for Fusion, optional for Scheduled rules. |
Optional |
| enabled | Determines whether this alert rule is enabled or disabled. Possible values are: yes, no. | Optional |
| etag | ETag of the Azure resource. | Optional |
| displayName | The display name for alerts created by this alert rule. Required for MicrosoftSecurityIncidentCreation and scheduled rules. |
Optional |
| product_filter | The alerts’ productName on which the cases will be generated. Required for MicrosoftSecurityIncidentCreation rules. Possible values are: azure_active_directory_identity_protection, azure_advanced_threat_protection, azure_security_center, azure_security_center_for_iot, microsoft_cloud_app_security. |
Optional |
| description | The description of the alert rule. Relevant for MicrosoftSecurityIncidentCreation and scheduled rules. |
Optional |
| name_exclude_filter | Alerts’ displayNames on which the cases will not be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| name_include_filter | Alerts’ displayNames on which the cases will be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| severity_filter | Alerts’ severities on which the cases will be generated. Relevant for MicrosoftSecurityIncidentCreation rules. |
Optional |
| query | The query that creates alerts for this rule. Required for scheduled rules. |
Optional |
| query_frequency | The frequency (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) for this alert rule to run. Required for scheduled rules. |
Optional |
| query_period | The period (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) that this alert rule looks at. Required for scheduled rules. |
Optional |
| severity | The severity for alerts created by this alert rule. Required for scheduled rules. Possible values are: informational, low, medium, high. |
Optional |
| suppression_duration | The suppression (in ISO 8601 duration format: PnYnMnDTnHnMnS or PnW) to wait since the last time this alert rule was triggered. Required for scheduled rules. |
Optional |
| suppression_enabled | Determines whether the suppression for this alert rule is enabled or disabled. Required for scheduled rules. Possible values are: yes, no. |
Optional |
| trigger_operator | The operation against the threshold that triggers the alert rule. Required for scheduled rules. Possible values are: equal, greater_than, less_than, not_equal. |
Optional |
| trigger_threshold | The threshold that triggers this alert rule. Required for scheduled rules. |
Optional |
| tactics | The tactics of the alert rule. Relevant for scheduled rules. |
Optional |
| techniques | The techniques of the alert rule. Relevant for scheduled rules. |
Optional |
| rule_json | Option to insert a configured rule JSON instead of using the arguments. | Optional |
| subscription_id | The subscription ID. | Optional |
| resource_group_name | The resource group name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.AlertRule.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.AlertRule.name | String | The name of the resource. |
| AzureSentinel.AlertRule.etag | String | ETag of the Azure resource. |
| AzureSentinel.AlertRule.type | String | The type of the resource, e.g., “Microsoft.Compute/virtualMachines” or “Microsoft.Storage/storageAccounts” |
| AzureSentinel.AlertRule.kind | String | The alert rule kind. |
| AzureSentinel.AlertRule.properties.displayName | String | The display name for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.description | String | The description of the alert rule. |
| AzureSentinel.AlertRule.properties.alertRuleTemplateName | Unknown | The name of the alert rule template used to update this rule. |
| AzureSentinel.AlertRule.properties.tactics | String | The tactics of the alert rule. |
| AzureSentinel.AlertRule.properties.severity | String | The severity for alerts created by this alert rule. |
| AzureSentinel.AlertRule.properties.enabled | Boolean | Determines whether this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.lastModifiedUtc | Date | The last time this alert was modified. |
| AzureSentinel.AlertRule.properties.productFilter | String | The alerts’ productName on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.severitiesFilter | Unknown | The alerts’ severities on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.displayNamesFilter | Unknown | The alerts’ displayNames on which the cases will be generated. |
| AzureSentinel.AlertRule.properties.query | String | The query that creates alerts for this rule. |
| AzureSentinel.AlertRule.properties.queryFrequency | String | The frequency (in ISO 8601 duration format) for this alert rule to run. |
| AzureSentinel.AlertRule.properties.queryPeriod | String | The period (in ISO 8601 duration format) that this alert rule looks at. |
| AzureSentinel.AlertRule.properties.triggerOperator | String | The operation against the threshold that triggers alert rule. |
| AzureSentinel.AlertRule.properties.triggerThreshold | Number | The threshold triggers this alert rule. |
| AzureSentinel.AlertRule.properties.suppressionDuration | String | The suppression (in ISO 8601 duration format) to wait since the last time this alert rule been triggered. |
| AzureSentinel.AlertRule.properties.suppressionEnabled | Boolean | Determines whether the suppression for this alert rule is enabled or disabled. |
| AzureSentinel.AlertRule.properties.eventGroupingSettings | Unknown | The event grouping settings. |
| AzureSentinel.AlertRule.properties.customDetails | Unknown | Dictionary of string key-value pairs of columns to be attached to the alert |
| AzureSentinel.AlertRule.properties.entityMappings | Unknown | Array of the entity mappings of the alert rule. |
| AzureSentinel.AlertRule.properties.alertDetailsOverride | String | The alert details override settings. |
| AzureSentinel.AlertRule.properties.incidentConfiguration | Unknown | The settings of the incidents that created from alerts triggered by this analytics rule. |
Command example
!azure-sentinel-update-alert-rule enabled=true kind=microsoft_security_incident_creation rule_name=test_name displayName="Testing updating Display Name" product_filter=microsoft_cloud_app_security
Context Example
{
"AzureSentinel": {
"AlertRule": {
"etag": "\"097809060-0000-6hd400\"",
"id": "/subscriptions/{subscription_id}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/test_name",
"kind": "MicrosoftSecurityIncidentCreation",
"name": "test_name",
"properties": {
"alertRuleTemplateName": null,
"description": null,
"displayName": "Testing updating Display Name",
"displayNamesExcludeFilter": null,
"displayNamesFilter": null,
"enabled": true,
"lastModifiedUtc": "2023-02-20T11:59:42.2920381Z",
"productFilter": "Microsoft Cloud App Security",
"severitiesFilter": null
},
"type": "Microsoft.SecurityInsights/alertRules"
}
}
}
Human Readable Output
Azure Sentinel Alert Rule successfully created/updated
ID Name Kind Display Name Enabled Etag test_name test_name MicrosoftSecurityIncidentCreation Testing updating Display Name true “097809060-0000-6hd400”
azure-sentinel-subscriptions-list
Lists all subscriptions.
Base Command
azure-sentinel-subscriptions-list
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.SubscriptionId | String | Fully qualified resource ID for the resource. |
| AzureSentinel.Subscription.displayName | String | The name of the resource. |
| AzureSentinel.Subscription.authorizationSource | String | The authorization source of the resource. |
| AzureSentinel.Subscription.managedByTenants | String | The subscriptions that are managed by tenants of the resource. |
| AzureSentinel.Subscription.tenetId | String | The tenet ID of the resource. |
| AzureSentinel.Subscription.state | String | The state of the resource. |
| AzureSentinel.Subscription.subscriptionPolicies | String | The subscription policies of the resource. |
Command example
#### Context Example
```json
{
"AzureSentinel": {
"Subscription": {
"authorizationSource": "RoleBased",
"displayName": "Pay-As-You-Go",
"id": "/subscriptions/0000000000000",
"managedByTenants": [],
"state": "Enabled",
"subscriptionId": "0000000000000",
"subscriptionPolicies": {
"locationPlacementId": "Public_2014-09-01",
"quotaId": "PayAsYouGo_2014-09-01",
"spendingLimit": "Off"
},
"tenantId": "000000000000000"
}
}
}
Human Readable Output
Azure Sentinel Subscriptions
Subscriptionid Tenantid Displayname State 0000000000000 000000000000000 Pay-As-You-Go Enabled
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ResourceGroup.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.ResourceGroup.name | String | The name of the resource. |
| AzureSentinel.ResourceGroup.type | String | The type of the resource. E.g., “Microsoft.Compute/virtualMachines” or “Microsoft.Storage/storageAccounts” |
| AzureSentinel.ResourceGroup.location | String | The location of the resource group. |
| AzureSentinel.ResourceGroup.tags | Dictionary | The tags of the resource group. |
| AzureSentinel.ResourceGroup.properties | dictionary | The properties of the resource group. |
azure-sentinel-resource-group-list
Lists all resource groups.
Base Command
azure-sentinel-resource-group-list
Input
| Argument Name | Description | Required |
|---|---|---|
| subscription_id | The subscription ID. Note: The integration default Subscription ID will be used unless this argument is provided. | Optional |
| tag | The tag name. Input should be {“Tag Name:Tag Value”}`. Operator is “equals”. |
Optional |
| limit | The maximum number of items to return. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureSentinel.ResourceGroup.id | String | Fully qualified resource ID for the resource. |
| AzureSentinel.ResourceGroup.name | String | The name of the resource. |
| AzureSentinel.ResourceGroup.type | String | The type of the resource. E.g., “Microsoft.Compute/virtualMachines” or “Microsoft.Storage/storageAccounts” |
| AzureSentinel.ResourceGroup.location | String | The location of the resource group. |
| AzureSentinel.ResourceGroup.tags | Dictionary | The tags of the resource group. |
| AzureSentinel.ResourceGroup.properties | dictionary | The properties of the resource group. |
Command example
#### Context Example
```json
{
"AzureSentinel": {
"ResourceGroup": [
{
"id": "/subscriptions/0f907ea4-bc8b-/resourceGroups/cloud-shell",
"location": "eastus",
"name": "cloud-shell-storage-eastus",
"properties": {
"provisioningState": "Succeeded"
},
"type": "Microsoft.Resources/resourceGroups"
},
{
"id": "/subscriptions/0f907ea4/resourceGroups/demi",
"location": "centralus",
"name": "demi",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"Owner": "Demi"
},
"type": "Microsoft.Resources/resourceGroups"
},
]}
}
Human Readable Output
Azure Sentinel Resource Groups
Name Location Tags cloud-shell eastus demi centralus Owner: Demi
azure-sentinel-auth-reset
Run this command if for some reason you need to rerun the authentication process.
Base Command
azure-sentinel-auth-reset
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Configuration parameters
azure_cloud— Azure Cloudlimit— Maximum number of incidents per fetch.creds_tenant_id—tenant_id— Tenant IDcreds_client_id—credentials—creds_certificate— Certificate Thumbprintcertificate_thumbprint— Certificate Thumbprintprivate_key— Private Keyuse_managed_identities— Use Azure Managed Identitiesmanaged_identities_client_id—subscriptionID— Default Subscription ID (required)resourceGroupName— Default Resource Group Name (required)workspaceName— Workspace Name (required)isFetch— Fetch incidentsfetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)min_severity— The minimum severity of incidents to fetchincidentType— Incident typeserver_url— Server URLinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsfetch_additional_info— Additional info to fetchmirror_direction— Mirroring Directionclose_incident— Close Mirrored XSOAR Incidentclose_ticket— Close Mirrored Microsoft Sentinel Ticketstatuses_to_fetch— Incident Statuses to FetchincidentFetchInterval— Incidents Fetch Intervallook_back— Minutes to look back when fetchingtitles_to_not_fetch— Incident Titles to Not Fetchalert_product_names_to_not_fetch— Alert Product Names to Not Fetch
Commands (36)
-
azure-sentinel-auth-resetRun this command if for some reason you need to rerun the authentication process.
-
azure-sentinel-create-alert-ruleCreates a new alert rule.
-
azure-sentinel-create-incidentCreate a sentinel incident.
-
azure-sentinel-create-update-watchlist-itemCreate or update a watchlist item.
-
azure-sentinel-delete-alert-ruleDeletes the specified alert rule.
-
azure-sentinel-delete-incidentDeletes a single incident in Azure Sentinel.
-
azure-sentinel-delete-watchlistDelete a watchlist from Azure Sentinel.
-
azure-sentinel-delete-watchlist-itemDelete a watchlist item.
-
azure-sentinel-get-incident-by-idGets a single incident from Azure Sentinel.
-
azure-sentinel-incident-add-commentAdds a comment to an incident in Azure Sentinel.
-
azure-sentinel-incident-delete-commentDeletes a comment from incident in Azure Sentinel.
-
azure-sentinel-list-alert-ruleGets a list of all alert rules.
-
azure-sentinel-list-alert-rule-templateGets a list of all alert rule templates.
-
azure-sentinel-list-incident-alertsGets a list of an incident's alerts from Azure Sentinel.
-
azure-sentinel-list-incident-commentsGets the comments of an incident from Azure Sentinel.
-
azure-sentinel-list-incident-entitiesGets a list of an incident's entities from Azure Sentinel.
-
azure-sentinel-list-incident-relationsGets a list of an incident's related entities from Azure Sentinel.
-
azure-sentinel-list-incidentsGets a list of incidents from Azure Sentinel.
-
azure-sentinel-list-watchlist-itemsGet a single watchlist item or list of watchlist items.
-
azure-sentinel-list-watchlistsGets a list of watchlists from Azure Sentinel.
-
azure-sentinel-resource-group-listList all resource groups for a subscription.
-
azure-sentinel-subscriptions-listLists all subscriptions.
-
azure-sentinel-threat-indicator-createCreates a new threat indicator.
-
azure-sentinel-threat-indicator-deleteDeletes an existing threat indicator.
-
azure-sentinel-threat-indicator-listReturns a list of threat indicators.
-
azure-sentinel-threat-indicator-queryReturns a list of threat indicators with specific entities.
-
azure-sentinel-threat-indicator-tags-appendAppends new tags to an existing indicator.
-
azure-sentinel-threat-indicator-tags-replaceReplaces the tags of a given indicator.
-
azure-sentinel-threat-indicator-updateUpdates an existing threat indicator.
-
azure-sentinel-update-alert-ruleUpdates an alert rule.
-
azure-sentinel-update-incidentUpdates a single incident in Azure Sentinel.
-
azure-sentinel-watchlist-create-updateCreate or update a watchlist in Azure Sentinel.
-
get-mapping-fieldsReturns the list of fields to map in outgoing mirroring. This command is only used for debugging purposes.
-
get-modified-remote-dataGets the list of incidents and detections that were modified since the last update time. This method is used for debugging purposes.
-
get-remote-dataGets data from a remote incident. This method does not update the current incident, and should be used for debugging purposes only.
-
update-remote-systemUpdates the remote incident with local incident changes. This method is only used for debugging purposes and will not update the current incident.
import json import dateparser import demistomock as demisto import freezegun import pytest import requests from AzureSentinel import ( COMMENT_HEADERS, DEFAULT_SOURCE, NEXT_LINK_DESCRIPTION, XSOAR_USER_AGENT, Action, AzureSentinelClient, append_tags_threat_indicator_command, build_threat_indicator_data, create_and_update_alert_rule_command, create_data_for_alert_rule, create_incident_command, create_threat_indicator_command, create_update_watchlist_command, create_update_watchlist_item_command, delete_alert_rule_command, delete_incident_command, delete_threat_indicator_command, delete_watchlist_command, delete_watchlist_item_command, extract_classification_reason, fetch_incidents, fetch_incidents_command, fetch_incidents_additional_info, get_mapping_fields_command, get_modified_remote_data_command, get_remote_data_command, get_remote_incident_data, get_update_incident_request_data, incident_add_comment_command, incident_delete_comment_command, list_alert_rule_command, list_alert_rule_template_command, list_incident_alerts_command, list_incident_comments_command, list_incident_entities_command, list_incident_relations_command, list_incidents_command, list_threat_indicator_command, list_watchlist_items_command, list_watchlists_command, process_incidents, query_threat_indicators_command, replace_tags_threat_indicator_command, set_xsoar_incident_entries, update_incident_command, update_incident_request, update_remote_incident, update_remote_system_command, update_threat_indicator_command, validate_required_arguments_for_alert_rule, ) from CommonServerPython import CommandResults, IncidentStatus, pascalToSpace, tableToMarkdown TEST_ITEM_ID = "test_watchlist_item_id_1" NEXT_LINK_CONTEXT_KEY = 'AzureSentinel.NextLink(val.Description == "NextLink for listing commands")' API_VERSION = "2022-11-01" def test_valid_error_is_raised_when_empty_api_response_is_returned(mocker): """ Given - Empty api response and invalid status code returned from the api response. When - running 'test-module'. Then - ValueError is raised. """ from AzureSentinel import test_module client = mock_client() api_response = requests.Response() api_response.status_code = 403 api_response._content = None mocker.patch.object(client._client, "get_access_token") mocker.patch.object(client._client._session, "request", return_value=api_response) with pytest.raises(ValueError, match="[Forbidden 403]"): test_module(client, {}) def mock_client(): client = AzureSentinelClient( tenant_id="tenant_id", client_id="client_id", client_secret="client_secret", subscription_id="subscriptionID", resource_group_name="resourceGroupName", workspace_name="workspaceName", verify=False, proxy=False, certificate_thumbprint=None, private_key=None, ) return client def mock_404_response(resource_id: str): res = requests.Response() res.status_code = 404 res._content = json.dumps({"error": {"code": "NotFound", "message": f"Resource '{resource_id}' does not exist"}}).encode() return res def mock_204_response(): res = requests.Response() res.status_code = 204 return res TEST_INCIDENT_ID = "test_incident_id" TEST_WATCHLIST_ALIAS = "test_watchlist_id_1" INCIDENT_ELEMENTS_CONTEXT_KEY = "{context_prefix}(val.ID === obj.ID && val.IncidentId == obj.IncidentId)" ALERTS_CONTEXT_KEY = INCIDENT_ELEMENTS_CONTEXT_KEY.format(context_prefix="AzureSentinel.IncidentAlert") ENTITIES_CONTEXT_KEY = INCIDENT_ELEMENTS_CONTEXT_KEY.format(context_prefix="AzureSentinel.IncidentEntity") MOCKED_INCIDENTS_OUTPUT = { "value": [ { "name": "inc_name", "properties": { "incidentNumber": 1, "title": "title", "description": "desc", "severity": "High", "status": "New", "owner": { "assignedTo": "bla", "email": "bla", }, "labels": [{"name": "label_name", "type": "label_type"}], "firstActivityTimeUtc": "2020-02-02T14:05:01.5348545Z", "lastActivityTimeUtc": "2020-02-02T14:05:01.5348545Z", "lastModifiedTimeUtc": "2020-02-02T14:05:01.5348545Z", "createdTimeUtc": "2020-02-02T14:05:01.5348545Z", "additionalData": { "alertsCount": 1, "bookmarksCount": 2, "commentsCount": 3, "alertProductNames": ["name1", "name2"], "tactics": ["tactic"], }, "firstActivityTimeGenerated": "2020-02-02T14:05:01.5348545Z", "lastActivityTimeGenerated": "2020-02-02T14:05:01.5348545Z", }, } ] } MOCKED_RELATIONS_OUTPUT = { "value": [ { "name": "inc_id_resource_name", "properties": {"relatedResourceName": "resource_name", "relatedResourceKind": "SecurityAlert"}, } ], "nextLink": "https://test.com", } LIST_RELATIONS_NEXT_LINK = None MOCKED_ADD_COMMENT_OUTPUT = { "name": "1234", "properties": { "author": { "email": "test@demisto.com", "name": "test_name", }, "message": "test_message", }, } MOCKED_INCIDENT_ENTITIES = { "entities": [ { "id": "test_id_1", "name": "test_entity_name_1", "kind": "Account", "properties": {"accountName": "test_1", "displayName": "Test User 1", "friendlyName": "Test User 1"}, }, { "id": "test_id_2", "name": "test_entity_name_2", "kind": "Account", "properties": {"accountName": "test_2", "displayName": "Test User 2", "friendlyName": "Test User 2"}, }, ] } MOCKED_INCIDENT_ALERTS = { "value": [ { "id": "test_alert_id_1", "name": "test_alert_id_1", "kind": "SecurityAlert", "properties": { "systemAlertId": "test_alert_id_1", "tactics": [ "InitialAccess", "Persistence", "PrivilegeEscalation", "DefenseEvasion", "CredentialAccess", "Discovery", "LateralMovement", "Execution", "Collection", "Exfiltration", "CommandAndControl", "Impact", ], "alertDisplayName": "Test alert 1", "description": "Test description", "severity": "Medium", "confidenceLevel": "Unknown", "vendorName": "Microsoft", "productName": "Azure Sentinel", "productComponentName": "Scheduled Alerts", "status": "New", "endTimeUtc": "2021-08-12T01:48:03.4349774Z", "startTimeUtc": "2021-08-11T01:48:03.4349774Z", "timeGenerated": "2021-08-12T01:53:07.3071703Z", "additionalData": { "MitreTechniques": "Unknown", }, "friendlyName": "Test alert 1", }, }, { "id": "test_alert_id_2", "name": "test_alert_id_2", "kind": "SecurityAlert", "properties": { "systemAlertId": "test_alert_id_2", "tactics": [ "InitialAccess", "Persistence", "PrivilegeEscalation", "DefenseEvasion", "CredentialAccess", "Discovery", "LateralMovement", "Execution", "Collection", "Exfiltration", "CommandAndControl", "Impact", ], "alertDisplayName": "Test alert 2", "description": "Test description", "confidenceLevel": "Unknown", "severity": "Medium", "vendorName": "Microsoft", "productName": "Azure Sentinel", "productComponentName": "Scheduled Alerts", "status": "New", "endTimeUtc": "2021-08-12T01:48:03.4349774Z", "startTimeUtc": "2021-08-11T01:48:03.4349774Z", "timeGenerated": "2021-08-12T01:53:07.3071703Z", "additionalData": { "MitreTechniques": "Unknown", }, "friendlyName": "Test alert 2", }, }, ] } MOCKED_WATCHLISTS = { "value": [ { "id": "test_watchlist_id_1", "name": "test_watchlist_name_1", "properties": { "watchlistId": "test_watchlist_id_1", "displayName": "test_watchlist_name_1", "provider": "test_provider", "source": "Local file", "itemsSearchKey": "IP", "created": "2021-07-11T08:20:35.8964775+00:00", "updated": "2021-07-11T08:20:35.8964775+00:00", "createdBy": {"email": "test@demisto.com", "name": "test_user"}, "updatedBy": {"email": "test@demisto.com", "name": "test_user"}, "description": "test_description", "watchlistType": "watchlist", "watchlistAlias": "test_watchlist_id_1", "labels": ["IP"], "numberOfLinesToSkip": 0, "uploadStatus": "Complete", }, }, { "id": "test_watchlist_id_2", "name": "test_watchlist_name_2", "properties": { "watchlistId": "test_watchlist_id_2", "displayName": "test_watchlist_name_2", "provider": "test_provider", "source": "Local file", "itemsSearchKey": "IP", "created": "2021-07-11T08:20:35.8964775+00:00", "updated": "2021-07-11T08:20:35.8964775+00:00", "createdBy": {"email": "test@demisto.com", "name": "test_user"}, "updatedBy": {"email": "test@demisto.com", "name": "test_user"}, "description": "test_description", "watchlistType": "watchlist", "watchlistAlias": "test_watchlist_id_2", "labels": ["IP"], "numberOfLinesToSkip": 0, "uploadStatus": "Complete", }, }, ] } MOCKED_WATCHLIST_ITEMS = { "value": [ { "id": "test_watchlist_item_id_1", "name": "test_watchlist_item_name_1", "properties": { "watchlistItemId": "test_watchlist_item_id_1", "created": "2021-08-15T14:14:28.7803449+00:00", "updated": "2021-08-15T14:14:28.7803449+00:00", "createdBy": {"name": "User 1"}, "updatedBy": {"name": "User 2"}, "itemsKeyValue": {"name": "test1", "IP": "1.1.1.1"}, }, }, { "id": "test_watchlist_item_id_2", "name": "test_watchlist_item_name_2", "properties": { "watchlistItemId": "test_watchlist_item_id_2", "created": "2021-08-15T14:14:28.7803449+00:00", "updated": "2021-08-15T14:14:28.7803449+00:00", "createdBy": {"name": "User 3"}, "updatedBy": {"name": "User 4"}, "itemsKeyValue": {"name": "test2", "IP": "2.2.2.2"}, }, }, ] } MOCKED_UPDATE_INCIDENT = { "id": "1", "name": "8a44b7bb-c8ae-0000-0000-000000000", "etag": '"0000000-0000-0000-0000-00000000"', "type": "Microsoft.SecurityInsights/Incidents", "properties": { "title": "dummy title", "description": "i am a sample description", "severity": "Informational", "status": "New", "owner": {"objectId": None, "email": "alice@example.com", "assignedTo": None, "userPrincipalName": None}, "labels": [{"labelName": "label_start", "labelType": "User"}], "lastModifiedTimeUtc": "2021-05-24T14:57:40.4174809Z", "createdTimeUtc": "2020-01-15T09:29:00.0000000Z", "incidentNumber": 2, "additionalData": { "alertsCount": 1, "bookmarksCount": 0, "commentsCount": 1, "alertProductNames": ["Azure Sentinel"], "tactics": [], }, "relatedAnalyticRuleIds": [], "incidentUrl": "https://example.com", "providerName": "Azure Sentinel", "providerIncidentId": "2", }, } MOCKED_THREAT_INDICATOR_OUTPUT = { "value": [ { "id": "ind_id", "name": "ind_name", "etag": '"1200b4fe-0000-0800-0000-6194cfae0000"', "type": "Microsoft.SecurityInsights/threatIntelligence", "kind": "indicator", "properties": { "confidence": 100, "created": "2021-11-17T09:43:15.9576155Z", "externalId": "indicator--0a1a583a-d801-4b64-9c5b-f595f77aa53d", "lastUpdatedTimeUtc": "2021-11-17T09:43:15.9579245Z", "source": "Azure Sentinel", "threatIntelligenceTags": ["wereplacedthetag"], "displayName": "displayfortestmay", "threatTypes": ["malicious-activity"], "parsedPattern": [ { "patternTypeKey": "url", "patternTypeValues": [ { "valueType": "url", "value": "‘twitter.com’", # noqa: RUF001 } ], } ], "pattern": "[url:value = ‘twitter.com’]", # noqa: RUF001 "patternType": "twitter.com", "validFrom": "2021-11-17T08:20:15.111Z", }, } ] } MOCKED_CREATE_THREAT_INDICATOR_OUTPUT = { "id": "ind_id", "name": "ind_name", "etag": '"1f002899-0000-0800-0000-619a3dd40000"', "type": "Microsoft.SecurityInsights/threatIntelligence", "kind": "indicator", "properties": { "confidence": 80, "created": "2021-11-21T12:38:43.9928873Z", "createdByRef": "", "externalId": "indicator--9f973088-3ac8-4391-9eb3-97fa90d3e1b5", "lastUpdatedTimeUtc": "2021-11-21T12:38:43.9976961Z", "revoked": True, "source": "Azure Sentinel", "threatIntelligenceTags": ["wereplacedthetag"], "displayName": "displayfortestmay", "description": "blabla", "threatTypes": ["compromised"], "killChainPhases": [{"killChainName": "rrr", "phaseName": "rrr"}], "parsedPattern": [ { "patternTypeKey": "file", "patternTypeValues": [{"valueType": "hashes.'SHA-1'", "value": "935DA64F08574E820565497C6918C8A17D4567FE"}], } ], "pattern": "[file:hashes.'SHA-1' = '935DA64F08574E820565497C6918C8A17D4567FE']", "patternType": "935DA64F08574E820565497C6918C8A17D4567FE", "validFrom": "2020-04-15T17:44:00.114052Z", }, } MOCKED_UPDATE_THREAT_INDICATOR = { "id": "ind_id", "name": "ind_name", "etag": '"1f002899-0000-0800-0000-619a3dd40000"', "type": "Microsoft.SecurityInsights/threatIntelligence", "kind": "indicator", "properties": { "confidence": 80, "created": "2021-11-21T12:38:43.9928873Z", "createdByRef": "", "externalId": "indicator--9f973088-3ac8-4391-9eb3-97fa90d3e1b5", "lastUpdatedTimeUtc": "2021-11-21T12:38:43.9976961Z", "revoked": True, "source": "Azure Sentinel", "threatIntelligenceTags": ["newTag"], "displayName": "newDisplayName", "description": "blabla", "threatTypes": ["compromised"], "killChainPhases": [{"killChainName": "rrr", "phaseName": "rrr"}], "parsedPattern": [ {"patternTypeKey": "file", "patternTypeValues": [{"valueType": "hashes.'SHA-1'", "value": "newValue"}]} ], "pattern": "[domain-name:value = newValue]", "patternType": "newValue", "validFrom": "2020-04-15T17:44:00.114052Z", }, } MOCKED_ORIGINAL_THREAT_INDICATOR_OUTPUT = { "id": "ind_id", "name": "ind_name", "etag": '"1200b4fe-0000-0800-0000-6194cfae0000"', "type": "Microsoft.SecurityInsights/threatIntelligence", "kind": "indicator", "properties": { "confidence": 100, "created": "2021-11-17T09:43:15.9576155Z", "externalId": "indicator--0a1a583a-d801-4b64-9c5b-f595f77aa53d", "lastUpdatedTimeUtc": "2021-11-17T09:43:15.9579245Z", "source": "Azure Sentinel", "threatIntelligenceTags": ["wereplacedthetag"], "displayName": "displayfortestmay", "threatTypes": ["malicious-activity"], "parsedPattern": [ { "patternTypeKey": "url", "patternTypeValues": [ { "valueType": "url", "value": "‘twitter.com’", # noqa: RUF001 } ], } ], "pattern": "[url:value = ‘twitter.com’]", # noqa: RUF001 "patternType": "twitter.com", "validFrom": "0001-01-01T00:00:00", }, } ARGS_TO_UPDATE = {"indicator_name": "ind_name", "displayName": "newDisplayName", "value": "newValue", "indicator_type": "domain"} MOCKED_RAW_INCIDENT_OUTPUT = { "value": [ { "ID": "inc_ID", "Name": "inc_name", "IncidentNumber": 2, "Title": "title", "Severity": "High", "CreatedTimeUTC": "2020-02-02T14:05:01.5348545Z", }, { "ID": "inc_ID_3", "Name": "inc_name_3", "IncidentNumber": 3, "Title": "title", "Severity": "Low", "CreatedTimeUTC": "2020-02-02T14:05:01.5348545Z", }, ] } class TestHappyPath: """ Group the Happy path tests """ @pytest.mark.parametrize( "args, expected_next_link, client", [ # disable-secrets-detection ({"limit": "1"}, "https://test.com", mock_client()), ({"limit": "50"}, None, mock_client()), ], ) def test_get_limited_list_incidents(self, args, expected_next_link, client, mocker): """ Given: - Args with and various limit parameter for the tested command - Expected value for next link if exist - An app client object When: - Calling function list_incidents_command Then: - Ensure the results holds the expected incidents list data - Ensure next link returned as expected """ # prepare mocked_incidents = MOCKED_INCIDENTS_OUTPUT.copy() mocker.patch.object(client, "http_request", return_value=mocked_incidents) if expected_next_link: mocked_incidents["nextLink"] = expected_next_link # execute command_res = list_incidents_command(client, args=args) readable_output, outputs, raw_response = command_res.readable_output, command_res.outputs, command_res.raw_response context = outputs["AzureSentinel.Incident(val.ID === obj.ID)"][0] # validate assert "Incidents List (1 results)" in readable_output assert context["ID"] == "inc_name", "Incident name in Azure Sentinel API is Incident ID in Cortex XSOAR" assert context["FirstActivityTimeUTC"] == "2020-02-02T14:05:01Z", "Dates are formatted to %Y-%m-%dT%H:%M:%SZ" assert context["AlertsCount"] == 1 assert len(raw_response["value"]) == 1 next_link = outputs.get(NEXT_LINK_CONTEXT_KEY, {}).get("URL") assert next_link == expected_next_link def test_get_next_page_list_incidents(self, mocker): """ Given: - Next link parameter to get the next page of incidents - An app client object When: - Calling function list_incidents_command Then: - Ensure the the request sent to the next link url """ # prepare next_link_uri = "https://test.com" args = {"limit": "1", "next_link": next_link_uri} client = mock_client() mocker.patch.object(client, "http_request") # execute list_incidents_command(client, args=args) # validate assert client.http_request.call_args[1]["full_url"] == next_link_uri def test_incident_add_comment(self, mocker): """ Given: - Incident Id and comment as argument for the command When: - Calling function incident_add_comment_command Then: - Validate the comment was sent as expected """ # prepare import random client = mock_client() mocker.patch.object(random, "getrandbits", return_value=1234) mocker.patch.object(client, "http_request", return_value=MOCKED_ADD_COMMENT_OUTPUT) # run args = {"incident_id": "inc_id", "message": "test_message"} command_result = incident_add_comment_command(client, args=args) readable_output, outputs = command_result.readable_output, command_result.outputs # validate assert "Incident inc_id new comment details" in readable_output assert outputs["ID"] == "1234", "Comment IDs are generated by random.getrandbits()" assert outputs["Message"] == "test_message" assert outputs["AuthorEmail"] == "test@demisto.com" assert outputs["IncidentID"] == "inc_id" @pytest.mark.parametrize( argnames="mocked_status_code, expected_result", argvalues=[ (200, "Comment comment_id was deleted successfully."), (204, "Comment comment_id does not exist."), ], ) def test_incident_delete_comment(self, mocker, mocked_status_code, expected_result): """ Given: - Incident Id and comment Id as argument for the command When: - Calling function incident_delete_comment_command Then: - Validate the comment was sent as expected """ # prepare client = mock_client() res = requests.Response() res.status_code = mocked_status_code mocker.patch.object(client, "http_request", return_value=res) # run args = {"incident_id": "inc_id", "comment_id": "comment_id"} readable_output = incident_delete_comment_command(client, args=args).readable_output # validate assert readable_output == expected_result def test_update_incident(self, mocker): """ Given: - Labels for update an incident When: - Calling function get_update_incident_request_data Then: - Validate the labels was sent as expected with the label name and label type """ # prepare client = mock_client() args = { "labels": ["label_after_1", "label_after_2"], "assignee_email": "bob@example.com", "user_principal_name": "booUserPrincipalName", } mocker.patch.object(client, "http_request", return_value=MOCKED_UPDATE_INCIDENT) # run incident_data = get_update_incident_request_data(client, args) # validate properties = incident_data["properties"] assert properties["labels"] == [ {"labelName": "label_after_1", "labelType": "User"}, {"labelName": "label_after_2", "labelType": "User"}, ] assert properties["owner"]["email"] == "bob@example.com" assert properties["owner"]["userPrincipalName"] == "booUserPrincipalName" def test_list_incident_entities(self, mocker): """ Given: - Args with incident id to get entities for When: - Calling function list_incident_entities_command Then: - Validate the expected entities was returned as expected """ # prepare client = mock_client() args = {"incident_id": TEST_INCIDENT_ID} mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENT_ENTITIES) with open("test_data/expected_entities.json") as file: expected_entities = json.load(file) # run command_result = list_incident_entities_command(client=client, args=args) # validate assert client.http_request.call_args[0][1] == f"incidents/{TEST_INCIDENT_ID}/entities" assert command_result.raw_response == MOCKED_INCIDENT_ENTITIES assert f"Incident {TEST_INCIDENT_ID} Entities (2 results)" in command_result.readable_output assert expected_entities == command_result.outputs def test_list_incident_alerts(self, mocker): """ Given: - Existing incident Id When: - Calling function list_incident_alerts_command Then: - Validate the result was returned as expected """ # prepare client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENT_ALERTS) with open("test_data/expected_alerts.json") as file: expected_alerts = json.load(file) # run command_result = list_incident_alerts_command(client, {"incident_id": TEST_INCIDENT_ID}) # validate assert client.http_request.call_args[0][1] == f"incidents/{TEST_INCIDENT_ID}/alerts" assert command_result.raw_response == MOCKED_INCIDENT_ALERTS assert command_result.outputs == expected_alerts def test_list_watchlist(self, mocker): """ Given: - When: - Calling function list_watchlists_command Then: - Validate watchlist was returned as expected """ # prepare client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_WATCHLISTS) with open("test_data/expected_watchlists.json") as file: expected_watchlists = json.load(file) # run command_result = list_watchlists_command(client=client, args={}) # validate assert "### Watchlists results\n|Name|ID|Description|" in command_result.readable_output assert "| test_watchlist_name_1 | test_watchlist_id_1 | test_description |" in command_result.readable_output assert command_result.raw_response == MOCKED_WATCHLISTS assert expected_watchlists == command_result.outputs def test_get_specific_watchlist(self, mocker): """ Given: - When: - Calling function list_watchlists_command with alias for specific watchlist Then: - Validate watchlist was returned as expected """ # prepare client = mock_client() args = {"watchlist_alias": TEST_WATCHLIST_ALIAS} mocker.patch.object(client, "http_request", return_value=MOCKED_WATCHLISTS["value"][0]) with open("test_data/expected_watchlists.json") as file: expected_watchlist = json.load(file)[0] # run command_result = list_watchlists_command(client=client, args=args) # validate assert "### Watchlists results\n|Name|ID|Description|" in command_result.readable_output assert "| test_watchlist_name_1 | test_watchlist_id_1 | test_description |" in command_result.readable_output assert command_result.raw_response == MOCKED_WATCHLISTS["value"][0] assert expected_watchlist == command_result.outputs[0] @pytest.mark.parametrize( argnames="deletion_command, args, item_id", argvalues=[ (delete_incident_command, {"incident_id": TEST_INCIDENT_ID}, TEST_INCIDENT_ID), (delete_watchlist_command, {"watchlist_alias": TEST_WATCHLIST_ALIAS}, TEST_WATCHLIST_ALIAS), ( delete_watchlist_item_command, {"watchlist_item_id": TEST_ITEM_ID, "watchlist_alias": TEST_WATCHLIST_ALIAS}, TEST_ITEM_ID, ), ], ) def test_generic_delete_items(self, deletion_command, args, mocker, item_id): """ Given: - Item for deletion is exist When: - Calling varius commands for deletion items with the required args Then: - Validate result was as expected """ # prepare client = mock_client() mocker.patch.object(client, "http_request") # run command_result = deletion_command(client=client, args=args) readable_output = command_result.readable_output # validate assert f"{item_id} was deleted successfully." in readable_output def test_list_watchlist_items(self, mocker): """ Given: - Watchlist with items When: - Calling to function list_watchlist_items_command Then: - Validate the expected result was returned """ # prepare client = mock_client() args = {"watchlist_alias": TEST_WATCHLIST_ALIAS} mocker.patch.object(client, "http_request", return_value=MOCKED_WATCHLIST_ITEMS) with open("test_data/expected_watchlist_items.json") as file: expected_items = json.load(file) # run command_result = list_watchlist_items_command(client=client, args=args) # validate assert f"| {TEST_ITEM_ID} | name: test1<br>IP: 1.1.1.1 |" in command_result.readable_output assert command_result.raw_response == MOCKED_WATCHLIST_ITEMS assert command_result.outputs == expected_items def test_single_watchlist_item(self, mocker): """ Given: - Watchlist with at least one item When: - Calling to function list_watchlist_items_command with argument for specific item Then: - Validate the expected result was returned """ # prepare client = mock_client() args = {"watchlist_alias": TEST_WATCHLIST_ALIAS, "watchlist_item_id": TEST_ITEM_ID} mocked_item = MOCKED_WATCHLIST_ITEMS["value"][0] mocker.patch.object(client, "http_request", return_value=mocked_item) with open("test_data/expected_watchlist_items.json") as file: expected_item = json.load(file)[0] # run command_result = list_watchlist_items_command(client=client, args=args) # validate assert client.http_request.call_args[0][1] == f"watchlists/{TEST_WATCHLIST_ALIAS}/watchlistItems/test_watchlist_item_id_1" assert f"| {TEST_ITEM_ID} | name: test1<br>IP: 1.1.1.1 |" in command_result.readable_output assert command_result.raw_response == mocked_item assert command_result.outputs[0] == expected_item def test_create_update_watchlist(self, mocker): """ Given: - Not existing watchlist alias or existing and we want to update When: - Calling function create_update_watchlist_command Then: - Validate result returned as expected """ # prepare client = mock_client() mocked_watchlist = MOCKED_WATCHLISTS["value"][0] args = { "watchlist_alias": demisto.get(mocked_watchlist, "properties.watchlistAlias"), "raw_content": None, "watchlist_display_name": demisto.get(mocked_watchlist, "properties.displayName"), "description": demisto.get(mocked_watchlist, "properties.description"), "provider": demisto.get(mocked_watchlist, "properties.provider"), "source": demisto.get(mocked_watchlist, "properties.source"), "labels": "IP", "lines_to_skip": demisto.get(mocked_watchlist, "properties.numberOfLinesToSkip"), "items_search_key": demisto.get(mocked_watchlist, "properties.itemsSearchKey"), "content_type": demisto.get(mocked_watchlist, "properties.contentType"), } mocker.patch.object(client, "http_request", return_value=mocked_watchlist) with open("test_data/expected_watchlists.json") as file: expected_watchlist = json.load(file)[0] # run command_result = create_update_watchlist_command(client, args) # validate assert expected_watchlist == command_result.outputs assert "|Name|ID|Description|" in command_result.readable_output assert "| test_watchlist_name_1 | test_watchlist_id_1 | test_description |" in command_result.readable_output def test_create_update_watchlist_item(self, mocker): """ Given: - Not existing watchlist item or existing and we want to update When: - Calling function create_update_watchlist_item_command Then: - Validate result returned as expected """ # prepare client = mock_client() mocked_item = MOCKED_WATCHLIST_ITEMS["value"][0] args = { "watchlist_alias": TEST_WATCHLIST_ALIAS, "item_key_value": json.dumps(demisto.get(mocked_item, "properties.itemsKeyValue")), } mocker.patch.object(client, "http_request", return_value=mocked_item) with open("test_data/expected_watchlist_items.json") as file: expected_item = json.load(file)[0] # run command_result = create_update_watchlist_item_command(client, args) # validate assert expected_item == command_result.outputs assert mocked_item["id"] in command_result.readable_output def test_user_agent_in_request(self, mocker): """ Given: - Request go to send to Azure When: - Run any command Then: - Validate the required header exist in request """ # prepare client = mock_client() mocker.patch.object(client._client, "get_access_token") mocker.patch.object(requests.Session, "request") # run list_watchlists_command(client, args={}) # validate user_agent = requests.Session.request.call_args[1]["headers"]["User-Agent"] assert user_agent == XSOAR_USER_AGENT @pytest.mark.parametrize( "args, expected_next_link, client", [ # disable-secrets-detection ({"limit": "50"}, "https://test.com", mock_client()), ({"next_link": "https://test.com"}, None, mock_client()), ], ) def test_threat_indicator_list_command(self, args, expected_next_link, client, requests_mock): """ Given: - Args with and various limit parameter for the tested command - Expected value for next link if exist - An app client object When: - Calling function list_threat_indicators_command Then: - Ensure the results holds the expected incidents list data - Ensure next link returned as expected """ # prepare mocked_indicators = MOCKED_THREAT_INDICATOR_OUTPUT.copy() if expected_next_link: mocked_indicators["nextLink"] = expected_next_link requests_mock.get( "https://management.azure.com/subscriptions/subscriptionID/resourceGroups/resourceGroupName/providers/Microsoft" ".OperationalInsights/workspaces/workspaceName/providers/Microsoft.SecurityInsights/threatIntelligence" "/main/indicators", json=mocked_indicators, ) else: requests_mock.get("https://test.com", json=mocked_indicators) requests_mock.post("https://login.microsoftonline.com/tenant_id/oauth2/v2.0/token", json={}) # execute command_res = list_threat_indicator_command(client, args=args) readable_output, outputs, raw_response = command_res.readable_output, command_res.outputs, command_res.raw_response context = outputs["AzureSentinel.ThreatIndicator"][0] # validate assert "Threat Indicators (1 results)" in readable_output assert context["Name"] == "ind_name", "Incident name in Azure Sentinel API is Incident ID in Cortex XSOAR" assert context["DisplayName"] == "displayfortestmay" assert len(raw_response["value"]) == 1 next_link = outputs.get(f'AzureSentinel.NextLink(val.Description == "{NEXT_LINK_DESCRIPTION}")', {}).get("URL") assert next_link == expected_next_link @pytest.mark.parametrize( "args, expected_next_link, client", [ # disable-secrets-detection ({"limit": "1", "min_confidence": 0, "indicator_types": ["url", "domain"]}, "https://test.com", mock_client()), ({"next_link": "https://test.com"}, None, mock_client()), ], ) def test_query_threat_indicators_command(self, args, expected_next_link, client, requests_mock): """ Given: - Args with and various limit parameter for the tested command - Expected value for next link if exist - An app client object When: - Calling function query_threat_indicators_command Then: - Ensure the results holds the expected incidents list data - Ensure next link returned as expected """ # prepare mocked_indicators = MOCKED_THREAT_INDICATOR_OUTPUT.copy() if expected_next_link: mocked_indicators["nextLink"] = expected_next_link requests_mock.post( "https://management.azure.com/subscriptions/subscriptionID/resourceGroups/resourceGroupName/providers/Microsoft" ".OperationalInsights/workspaces/workspaceName/providers/Microsoft.SecurityInsights/threatIntelligence" "/main/queryIndicators", json=mocked_indicators, ) else: requests_mock.post("https://test.com", json=mocked_indicators) requests_mock.post("https://login.microsoftonline.com/tenant_id/oauth2/v2.0/token", json={}) # execute command_res = query_threat_indicators_command(client, args=args) readable_output, outputs, raw_response = command_res.readable_output, command_res.outputs, command_res.raw_response context = outputs["AzureSentinel.ThreatIndicator"][0] assert "Threat Indicators (1 results)" in readable_output assert context["Name"] == "ind_name", "Incident name in Azure Sentinel API is Incident ID in Cortex XSOAR" assert context["DisplayName"] == "displayfortestmay" assert len(raw_response["value"]) == 1 next_link = outputs.get(f'AzureSentinel.NextLink(val.Description == "{NEXT_LINK_DESCRIPTION}")', {}).get("URL") assert next_link == expected_next_link @pytest.mark.parametrize( "args, client", [ # disable-secrets-detection ( { "value": "twitter.com", "display_name": "displaytestformay", "indicator_types": "url", "threat_types": ["malicious-activity"], }, mock_client(), ) ], ) def test_create_threat_indicator_command(self, args, client, mocker): """ Given: - Args with and various limit parameter for the tested command - An app client object When: - Calling function create_threat_indicator_command Then: - Ensure the results holds the expected incidents list data """ # prepare mocked_indicators = MOCKED_CREATE_THREAT_INDICATOR_OUTPUT mocker.patch.object(client, "http_request", return_value=mocked_indicators) # execute command_res = create_threat_indicator_command(client, args=args) readable_output, outputs = command_res.readable_output, command_res.outputs context = outputs[0] # validate assert "New threat Indicator was created" in readable_output assert context["Name"] == "ind_name", "Incident name in Azure Sentinel API is Incident ID in Cortex XSOAR" assert context["DisplayName"] == "displayfortestmay" assert context["Tags"][0] == "wereplacedthetag" @pytest.mark.parametrize( "args, client", [ # disable-secrets-detection ({"indicator_names": ["ind_name", "ind2_name"]}, mock_client()) ], ) def test_delete_threat_indicator_command(self, args, client, mocker): """ Given: - Args with and various limit parameter for the tested command - An app client object When: - Calling function delete_threat_indicator_command Then: - Ensure the results holds the expected readable output """ # prepare mocker.patch.object(client, "http_request", return_value={}) # execute command_res = delete_threat_indicator_command(client, args=args) readable_output = command_res.readable_output # validate assert "Threat Intelligence Indicators ind_name, ind2_name were deleted successfully" in readable_output @pytest.mark.parametrize( "args, client", [ # disable-secrets-detection ({"indicator_name": "ind_name", "tags": "wereplacedthetag"}, mock_client()) ], ) def test_append_tags_threat_indicator_command(self, args, client, mocker): """ Given: - Args with and various limit parameter for the tested command - An app client object When: - Calling function pend_tags_threat_indicator_command Then: - Ensure the results holds the expected incidents list data """ # prepare mocked_indicators = MOCKED_CREATE_THREAT_INDICATOR_OUTPUT mocker.patch.object(client, "http_request", return_value=mocked_indicators) # execute command_res = append_tags_threat_indicator_command(client, args=args) readable_output, outputs = command_res.readable_output, command_res.outputs context = outputs[0] # validate assert "Tags were appended to ind_name Threat Indicator" in readable_output assert context["Name"] == "ind_name" assert context["DisplayName"] == "displayfortestmay" assert context["Tags"][0] == "wereplacedthetag" @pytest.mark.parametrize( "args, client", [ # disable-secrets-detection ({"indicator_name": "ind_name", "tags": "wereplacedthetag"}, mock_client()) ], ) def test_replace_tags_threat_indicator_command(self, args, client, mocker): """ Given: - Args with and various limit parameter for the tested command - An app client object When: - Calling function replace_tags_threat_indicator_command Then: - Ensure the results holds the expected incidents list data """ # prepare mocked_indicators = MOCKED_CREATE_THREAT_INDICATOR_OUTPUT mocker.patch.object(client, "http_request", return_value=mocked_indicators) # execute command_res = replace_tags_threat_indicator_command(client, args=args) readable_output, outputs = command_res.readable_output, command_res.outputs context = outputs[0] # validate assert "Tags were replaced to ind_name Threat Indicator." in readable_output assert context["Name"] == "ind_name" assert context["DisplayName"] == "displayfortestmay" assert context["Tags"][0] == "wereplacedthetag" @pytest.mark.parametrize( "args, client", [ # disable-secrets-detection (ARGS_TO_UPDATE, mock_client()) ], ) def test_update_threat_indicator_command(self, args, client, requests_mock): """ Given: - Args with and various limit parameter for the tested command - An app client object When: - Calling function update_incident_command Then: - Ensure the results holds the expected threat indicator data """ # prepare mocked_indicators = MOCKED_ORIGINAL_THREAT_INDICATOR_OUTPUT mocked_updated_indicators = MOCKED_UPDATE_THREAT_INDICATOR requests_mock.get( "https://management.azure.com/subscriptions/subscriptionID/resourceGroups/resourceGroupName/providers/Microsoft" ".OperationalInsights/workspaces/workspaceName/providers/Microsoft.SecurityInsights/threatIntelligence" "/main/indicators/ind_name", json=mocked_indicators, ) requests_mock.put( "https://management.azure.com/subscriptions/subscriptionID/resourceGroups/resourceGroupName/providers/Microsoft" ".OperationalInsights/workspaces/workspaceName/providers/Microsoft.SecurityInsights/threatIntelligence" "/main/indicators/ind_name", json=mocked_updated_indicators, ) requests_mock.post("https://login.microsoftonline.com/tenant_id/oauth2/v2.0/token", json={}) # execute command_res = update_threat_indicator_command(client, args=args) readable_output, outputs = command_res.readable_output, command_res.outputs context = outputs[0] # validate assert "Threat Indicator ind_name was updated" in readable_output assert context["Name"] == "ind_name", "Incident name in Azure Sentinel API is Incident ID in Cortex XSOAR" assert context["DisplayName"] == "newDisplayName" @pytest.mark.parametrize( "args, client, expected_result", [ # disable-secrets-detection ( {"last_fetch_ids": [], "min_severity": 3, "last_incident_number": 1}, mock_client(), {"last_fetch_ids": ["inc_ID"], "last_incident_number": 2}, ), # case 1 ], ) def test_process_incidents(self, args, client, expected_result): """ Given: - Raw_incidents, AzureSentinel client, last_fetched_ids array, last_incident_number, latest_created_time, and a minimum severity. When: - Calling the process_incidents command. Then: - Validate the return values based on the scenario: case 1: We expect to process the incident, so its ID exists in the expected result. case 2: The incident id is in the "last_fetch_ids" array, so we expect to not process the incident. """ # prepare raw_incidents = [MOCKED_RAW_INCIDENT_OUTPUT.get("value")[0]] last_incident_number = args.get("last_incident_number") latest_created_time = dateparser.parse("2020-02-02T14:05:01.5348545Z") # run next_run, _ = process_incidents(raw_incidents, latest_created_time, last_incident_number, {}) # validate assert next_run.get("last_fetch_ids") == expected_result.get("last_fetch_ids") assert next_run.get("last_incident_number") == expected_result.get("last_incident_number") def test_last_run_in_fetch_incidents(self, mocker): """ Scenario: First time fetching incidents after updating the integration. Given: - AzureSentinel client, last_run dictionary, first_fetch_time, and a minimum severity. The last_run dictionary mimics a last_run dict from a previous version of the integration, containing an empty 'last_fetch_ids' array and a valid 'last_fetch_time' string, but does not contain 'last_incident_number' that was added in the new version. When: - Calling the fetch_incidents command. Then: - Validate the call_args had the correct filter and orderby, to check that the fetch was handled by created time and not by incident number. """ # prepare client = mock_client() last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} first_fetch_time = "3 days" minimum_severity = "Informational" mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) # run fetch_incidents(client, last_run, first_fetch_time, minimum_severity) call_args = client.http_request.call_args[1] # validate assert "properties/createdTimeUtc ge" in call_args.get("params").get("$filter") assert call_args.get("params").get("$orderby") == "properties/createdTimeUtc asc" def test_last_run_in_fetch_incidents_duplicates(self, mocker): """ Scenario: Update the last run when duplicates are found. Given: - AzureSentinel client, last_run dictionary, first_fetch_time, and a minimum severity. The last_run dictionary mimics a last_run dict from a previous version of the integration, containing an empty 'last_fetch_ids' array with the previous detected incident, and has the same incident ID from the API. When: - Calling the fetch_incidents command. Then: - Validate that the incidents was deduped and not processed. """ # prepare client = mock_client() last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": ["inc_name"]} first_fetch_time = "3 days" minimum_severity = "Informational" process_mock = mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) # run fetch_incidents(client, last_run, first_fetch_time, minimum_severity) # validate assert not process_mock.call_args[0][0] @pytest.mark.parametrize("min_severity, expected_incident_num", [(1, 2), (3, 2)]) def test_last_fetched_incident_for_various_severity_levels(self, mocker, min_severity, expected_incident_num): """ Given: - Fetched incidents are with severity behind and over the lowest level defined in the integration instanse. When: - Calling the process_incidents function. Then: - Validate the last fetched incident contain also the low severity incidents. - Validate only incidents with the expected severity level is returned. """ # prepare raw_incidents = MOCKED_RAW_INCIDENT_OUTPUT["value"] latest_created_time = dateparser.parse("2020-02-02T14:05:01.5348545Z") # run next_run, incidents = process_incidents( raw_incidents=raw_incidents, latest_created_time=latest_created_time, last_incident_number=1, lookback_fetch_ids={}, ) # validate assert next_run.get("last_fetch_ids") == ["inc_ID", "inc_ID_3"] assert next_run.get("last_incident_number") == 3 assert len(incidents) == expected_incident_num def test_build_threat_indicator_data(self): """ Given: - Args with values. When: - Calling function build_threat_indicator_data. Then: - Ensure the results holds the expected outcomes. """ # prepare args = { "display_name": "displayname", "indicator_type": "ipv4", "revoked": "false", "threat_types": "compromised", "value": "1.1.1.1", } # run output = build_threat_indicator_data(args, source=DEFAULT_SOURCE) # validate assert " '1.1.1.1'" in output.get("pattern") assert output.get("patternType") == "ipv4-addr" assert output.get("source") == DEFAULT_SOURCE @pytest.mark.parametrize(argnames="client_id", argvalues=["test_client_id", None]) def test_test_module_command_with_managed_identities(self, mocker, requests_mock, client_id): """ Given: - Managed Identities client id for authentication. When: - Calling test_module. Then: - Ensure the output are as expected. """ import re import AzureSentinel from AzureSentinel import MANAGED_IDENTITIES_TOKEN_URL, Resources, main mock_token = {"access_token": "test_token", "expires_in": "86400"} get_mock = requests_mock.get(MANAGED_IDENTITIES_TOKEN_URL, json=mock_token) requests_mock.get(re.compile(f"^{Resources.management_azure}.*")) params = { "managed_identities_client_id": {"password": client_id}, "use_managed_identities": "True", "subscriptionID": "test_subscription_id", "resourceGroupName": "test_resource_group", "tenant_id": "test_tenant_id", "azure_cloud": "Worldwide", } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(AzureSentinel, "return_results") mocker.patch("MicrosoftApiModule.get_integration_context", return_value={}) main() assert "ok" in AzureSentinel.return_results.call_args[0][0] qs = get_mock.last_request.qs assert qs["resource"] == [Resources.management_azure] assert (client_id and qs["client_id"] == [client_id]) or "client_id" not in qs class TestEdgeCases: """ Group for the Edge cases tests """ @pytest.mark.parametrize( argnames="command, resource_id", argvalues=[ (list_incident_entities_command, TEST_INCIDENT_ID), (list_incident_comments_command, TEST_INCIDENT_ID), (list_incident_relations_command, TEST_INCIDENT_ID), (list_incident_alerts_command, TEST_INCIDENT_ID), (list_watchlists_command, TEST_WATCHLIST_ALIAS), (list_watchlist_items_command, TEST_WATCHLIST_ALIAS), ], ) def test_not_exist_elements(self, command, resource_id, mocker): """ Given: - Not existing resource id (incident, watchlist alias) When: - Calling various list incident elements commands Then: - Validate the expected error message was returned """ # prepare client = mock_client() args = {"incident_id": TEST_INCIDENT_ID, "limit": "50"} not_exist_response = mock_404_response(resource_id=resource_id) mocker.patch.object(requests.Session, "request", return_value=not_exist_response) mocker.patch.object(client._client, "get_access_token") # run with pytest.raises(ValueError) as error: command(client=client, args=args) # validate assert error.value.args[0] == f"[NotFound 404] Resource '{resource_id}' does not exist" @pytest.mark.parametrize( "incidents", [ ([{"ID": "incident-1"}]), ([{"ID": "incident-1"}, {"ID": "incident-2"}]), ({"ID": "incident-1"}), ([]), ], ) def test_fetch_incidents_additional_info(mocker, incidents): """ Given: - A list of incidents When: - Calling fetch_incidents_additional_info Then: - Ensure the client's http_request method was called the expected number of times, and the incidents were updated with the additional info """ args = {"fetch_additional_info": ["Alerts", "Entities"]} mocker.patch("demistomock.params", return_value=args) client = mock_client() mocker.patch.object( client, "http_request", side_effect=[ {"value": [{"id": "alert-1"}]}, {"entities": [{"id": "entities-1"}]}, {"value": [{"id": "alert-2"}]}, {"entities": [{"id": "entities-2"}]}, ], ) fetch_incidents_additional_info(client, incidents) if isinstance(incidents, dict): incidents = [incidents] assert client.http_request.call_count == len(args["fetch_additional_info"]) * len(incidents) if incidents: assert client.http_request.call_args_list[0][0][1] == "incidents/incident-1/alerts" for i, incident in enumerate(incidents): assert "alerts" in incident assert incident["alerts"] == [{"id": f"alert-{i + 1}"}] assert "entities" in incident assert incident["entities"] == [{"id": f"entities-{i + 1}"}] @pytest.mark.parametrize( "last_update, expected_last_update", [ ("2023-01-06T08:17:09.001016488+02:00", "2023-01-06T06:17:09.001016Z"), ("2023-01-06T08:17:09.001016488Z", "2023-01-06T08:17:09.001016Z"), ], ) def test_get_modified_remote_data_command(mocker, last_update, expected_last_update): """ Given - client - args with lastUpdate When - running get_modified_remote_data_command Then - Ensure the client's http_request method was called with the expected filter, and the modified_incident_ids were returned the expected list of ids. """ client = mock_client() mock_response = {"value": [{"name": "incident-1"}, {"name": "incident-2"}]} mocker.patch.object(client, "http_request", return_value=mock_response) result = get_modified_remote_data_command(client, {"lastUpdate": last_update}) excepted_filter = f"properties/lastModifiedTimeUtc ge {expected_last_update}" assert client.http_request.call_args[1]["params"]["$filter"] == excepted_filter assert result.modified_incident_ids == [incident["name"] for incident in mock_response["value"]] def test_get_remote_data_command(mocker): """ Given - client - args with id and lastUpdate When - running get_remote_data_command Then - Ensure the mirrored object was returned the expected object """ mocker.patch("AzureSentinel.get_remote_incident_data", return_value=({"name": "incident-1"}, {"ID": "incident-1"})) mocker.patch.object(demisto, "params", return_value={"close_incident": True}) result = get_remote_data_command(mock_client(), {"id": "incident-1", "lastUpdate": "2023-01-06T08:17:09Z"}) assert result.mirrored_object == {"ID": "incident-1"} assert result.entries == [] def test_get_remote_incident_data(mocker): """ Given - client - incident id When - running get_remote_incident_data Then Verify the function returns the expected mirrored data and updated object """ client = mock_client() mock_response = {"name": "id-incident-1", "properties": {"title": "title-incident-1", "additionalData": {"alertsCount": 0}}} mocker.patch.object(client, "http_request", return_value=mock_response) result = get_remote_incident_data(client, "id-incident-1") assert result == ( mock_response, {"ID": "id-incident-1", "Title": "title-incident-1", "AlertsCount": 0, "tags": [], "relatedAnalyticRuleIds": []}, ) @pytest.mark.parametrize( "incident, expected_contents", [ ( {"ID": "id-incident-1", "Status": "Closed", "classification": "BenignPositive"}, {"dbotIncidentClose": True, "closeReason": "Resolved", "closeNotes": "Closed on Microsoft Sentinel"}, ), ({"ID": "id-incident-1", "Status": "Active"}, {"dbotIncidentReopen": True}), ], ) def test_set_xsoar_incident_entries(mocker, incident, expected_contents): """ Given - incident - entries When - running set_xsoar_incident_entries Then - Ensure the entries were updated with the expected contents """ mocker.patch.object(demisto, "params", return_value={"close_incident": True}) entries: list = [] set_xsoar_incident_entries(incident, entries, "id-incident-1") assert entries[0].get("Contents") == expected_contents def test_get_mapping_fields_command(): """ Given - nothing When - running get_mapping_fields_command Then - the result fits the expected mapping scheme """ result = get_mapping_fields_command() assert result.scheme_types_mappings[0].type_name == "Microsoft Sentinel Incident" assert result.scheme_types_mappings[0].fields.keys() == { "description", "status", "lastActivityTimeUtc", "classificationReason", "tags", "classificationComment", "severity", "firstActivityTimeUtc", "classification", "title", "etag", } def test_update_remote_system_command(mocker): """ Given - client - args with remoteId, status, data and delta When - running update_remote_system_command Then - Ensure the function returns the expected incident id """ mocker.patch("AzureSentinel.update_remote_incident", return_value={}) args = { "remoteId": "incident-1", "status": 1, "data": {"title": "Title", "severity": 2, "status": 1}, "delta": {"title": "New Title", "severity": 3}, } result = update_remote_system_command(mock_client(), args) assert result == "incident-1" @pytest.mark.parametrize( "incident_status, required_action, delta, expected_update_call", [ (IncidentStatus.DONE, Action.CLOSE, {}, True), (IncidentStatus.DONE, Action.UNCHANGED, {}, False), # delta is empty (IncidentStatus.DONE, Action.UNCHANGED, {"classification": "FalsePositive"}, False), # delta have only closing fields (IncidentStatus.DONE, Action.UNCHANGED, {"title": "Title"}, True), # delta have fields except closing fields (IncidentStatus.ACTIVE, Action.UNCHANGED, {}, False), # delta is empty and required action is Action.UNCHANGED (IncidentStatus.ACTIVE, Action.UNCHANGED, {"title": "Title"}, True), (IncidentStatus.PENDING, Action.CLOSE, {}, False), ], ) def test_update_remote_incident(mocker, incident_status, required_action, delta, expected_update_call): """ Given - incident status When - running update_remote_incident Then - ensure the function call only when the incident status is DONE and should_close_incident_in_remote is True or when the incident status is ACTIVE """ mocker.patch("AzureSentinel.check_required_action_on_incident", return_value=required_action) mock_update_status = mocker.patch("AzureSentinel.update_incident_request") update_remote_incident(mock_client(), {}, delta, incident_status, "incident-1") assert mock_update_status.called == expected_update_call @pytest.mark.parametrize( "delta, data, close_ticket_param, incident_status, action", [ ({"classification": "FalsePositive"}, {}, True, IncidentStatus.DONE, Action.CLOSE), ({"classification": "FalsePositive"}, {}, False, IncidentStatus.DONE, Action.UNCHANGED), ({}, {}, True, IncidentStatus.DONE, Action.UNCHANGED), ({}, {}, False, IncidentStatus.DONE, Action.UNCHANGED), # Closing after classification is already present in the data. ({}, {"classification": "FalsePositive"}, True, IncidentStatus.DONE, Action.CLOSE), # Closing after reopened, before data update ({}, {"classification": "FalsePositive", "status": "Closed"}, True, IncidentStatus.DONE, Action.CLOSE), # Closing after reopened, after data update ({}, {"classification": "FalsePositive", "status": "Active"}, True, IncidentStatus.DONE, Action.CLOSE), ({"classification": "FalsePositive"}, {}, True, IncidentStatus.ACTIVE, Action.UNCHANGED), ({"classification": ""}, {}, True, IncidentStatus.ACTIVE, Action.REOPEN), ({"classification": ""}, {}, True, IncidentStatus.DONE, Action.UNCHANGED), ({}, {}, False, IncidentStatus.ACTIVE, Action.UNCHANGED), ( {"classification": "FalsePositive"}, {}, False, IncidentStatus.DONE, Action.UNCHANGED, ), ], ids=[ "1#-close_incident_close_ticket_param_is_true", "2#-close_incident_close_ticket_param_is_false", "3#-close_incident_without_classification_close_ticket_param_is_true", "4#-close_incident_without_classification_close_ticket_param_is_false", "5#-close_incident_classification_already_in_data", "6#-close_incident_after_reopen_before_data_update", "7#-close_incident_after_reopen_after_data_update", "8#-the_incident_is_open_classification_changed", "9#-the_incident_is_reopened", "10#-the_incident_is_close_classification_removed", "11#-the_incident_is_open", "12#-the_incident_is_close_classification_changed", ], ) def test_check_required_action_on_incident(mocker, delta, data, close_ticket_param, incident_status, action): """ Given - delta, data, close_ticket_param, incident_status When - outgoing mirroring triggered by a change in the incident Then - returns one of Action.CLOSE,Action.REOPEN,Action.UNCHANGED """ from AzureSentinel import check_required_action_on_incident mocker.patch.object(demisto, "params", return_value={"close_ticket": close_ticket_param}) assert check_required_action_on_incident(delta, data, incident_status) == action @pytest.mark.parametrize( "data, delta, mocked_fetch_data, expected_response, required_action", [ ( # Update description of active incident. {"title": "Title", "description": "old desc", "severity": 2, "status": "Active"}, {"title": "Title", "description": "new desc"}, {"title": "Title", "description": "old desc", "severity": "Medium", "status": "Active"}, {"title": "Title", "description": "new desc", "severity": "Medium", "status": "Active"}, Action.UNCHANGED, ), ( # Update runStatus (not mirror field) of active incident - shouldn't run the update, # and will return {} {"title": "Title", "description": "old desc", "severity": 2, "status": "New"}, {"runStatus": "running"}, {"title": "Title", "description": "old desc", "severity": "Medium", "status": "New"}, {}, Action.UNCHANGED, ), ( # Update runStatus (not mirror field) of Closed incident - should close the ticket, {"title": "Title", "description": "old desc", "severity": 1, "status": "New"}, {"runStatus": "running", "classification": "Undetermined"}, {"title": "Title", "severity": "Low", "status": "Active"}, {"title": "Title", "severity": "Low", "status": "Closed", "classification": "Undetermined"}, Action.CLOSE, ), ( # Update description and classification and close incident. {"title": "Title", "description": "old desc", "severity": 1, "status": "Active"}, {"title": "Title", "description": "new desc", "classification": "Undetermined"}, {"title": "Title", "description": "old desc", "severity": "Low", "status": "Active"}, { "title": "Title", "description": "new desc", "severity": "Low", "status": "Closed", "classification": "Undetermined", }, Action.CLOSE, ), ( # Update description and classification of active incident without closing. Result in description update only. {"title": "Title", "description": "old desc", "severity": 1, "status": "Active"}, {"title": "Title", "description": "new desc", "classification": "Undetermined"}, {"title": "Title", "description": "old desc", "severity": "Low", "status": "Active"}, {"title": "Title", "description": "new desc", "severity": "Low", "status": "Active"}, Action.UNCHANGED, ), ( # Update title and close incident with classification already in data. Result in closing with classification. {"title": "Title", "severity": 1, "status": "Active", "classification": "Undetermined"}, {"title": "Title"}, {"title": "Title", "severity": "Low", "status": "Active", "classification": "Undetermined"}, {"title": "Title", "severity": "Low", "status": "Closed", "classification": "Undetermined"}, Action.CLOSE, ), ( # Update labels of active incident when no labels exist. {"title": "Title", "description": "desc", "severity": 2, "status": "Active", "tags": []}, {"title": "Title", "tags": ["Test"]}, {"title": "Title", "description": "desc", "severity": "Medium", "status": "Active"}, {"title": "Title", "severity": "Medium", "status": "Active", "labels": [{"labelName": "Test", "type": "User"}]}, Action.UNCHANGED, ), ( # Update labels of active incident when a label already exist. {"title": "Title", "description": "desc", "severity": 2, "status": "Active", "tags": ["Test"]}, {"title": "Title", "tags": ["Test2"]}, { "title": "Title", "description": "desc", "severity": "Medium", "status": "Active", "properties": {"labels": [{"labelName": "Test", "type": "User"}]}, }, { "title": "Title", "severity": "Medium", "status": "Active", "labels": [{"labelName": "Test", "type": "User"}, {"labelName": "Test2", "type": "User"}], }, Action.UNCHANGED, ), ], ) def test_update_incident_request(mocker, data, delta, mocked_fetch_data, expected_response, required_action): """ Given - data: The incident data before the update in xsoar. - delta: The changes in the incident made in xsoar. - mocked fetched current data: The incident data before the update in sentinel. When - running update_incident_request Then - Ensure the client.http_request was called with the expected data """ client = mock_client() mocker.patch.object(client, "http_request", return_value=mocked_fetch_data) update_incident_request(client, "id-incident-1", data, delta, required_action) assert not expected_response or client.http_request.call_args[1]["data"].get("properties") == expected_response @pytest.mark.parametrize("args", [({}), ({"limit": 1}), ({"limit": 2}), ({"rule_id": "rule1"})]) def test_list_alert_rule_command(mocker, args): """ Given - client - args with limit or rule_id When - running list_alert_rule_command Then - Ensure the function returns the expected alert rule """ prefix_file = "get" if args.get("rule_id") else "list" with open(f"test_data/{prefix_file}_alert_rule-mock_response.json") as file: mock_response = json.load(file) client = mock_client() mocker.patch.object(client, "http_request", return_value=mock_response) command_results = list_alert_rule_command(client, args) if limit := args.get("limit"): assert len(command_results.outputs) == limit assert command_results.outputs == mock_response.get("value", [])[:limit] elif rule_id := args.get("rule_id"): assert command_results.outputs == [mock_response] assert command_results.outputs[0].get("name") == rule_id else: assert command_results.outputs == mock_response.get("value", []) assert len(command_results.outputs) == len(mock_response.get("value", [])) @pytest.mark.parametrize("args", [({}), ({"limit": 1}), ({"limit": 2}), ({"template_id": "template1"})]) def test_list_alert_rule_template_command(mocker, args): """ Given - client - args with limit or rule_id When - running list_alert_rule_template_command Then - Ensure the function returns the expected alert rule template """ prefix_file = "get" if args.get("template_id") else "list" with open(f"test_data/{prefix_file}_alert_rule_template-mock_response.json") as file: mock_response = json.load(file) client = mock_client() mocker.patch.object(client, "http_request", return_value=mock_response) command_results = list_alert_rule_template_command(client, args) if limit := args.get("limit"): assert len(command_results.outputs) == limit assert command_results.outputs == mock_response.get("value", [])[:limit] elif rule_id := args.get("template_id"): assert command_results.outputs == [mock_response] assert command_results.outputs[0].get("name") == rule_id else: assert command_results.outputs == mock_response.get("value", []) assert len(command_results.outputs) == len(mock_response.get("value", [])) @pytest.mark.parametrize( "mock_response, expected_readable_output, expected_outputs", [ ({}, "Alert rule rule1 was deleted successfully.", {"ID": "rule1", "Deleted": True}), # 200 response (mock_204_response(), "Alert rule rule1 does not exist.", None), # 204 response ], ) def test_delete_alert_rule_command(mocker, mock_response, expected_readable_output, expected_outputs): """ Given - args with rule_id When - running delete_alert_rule_command Then - Ensure the function returns the expected command results """ client = mock_client() mocker.patch.object(client, "http_request", return_value=mock_response) command_results = delete_alert_rule_command(client, {"rule_id": "rule1"}) assert command_results.readable_output == expected_readable_output def test_validate_required_arguments_for_alert_rule(): """ Given - args with all required arguments - args with missing required arguments When - running validate_required_arguments_for_alert_rule Then - if all required arguments are provided, ensure the function returns nothing - if a required argument is missing, ensure the function raises a ValueError """ # Test with a fusion alert rule with all required arguments args = {"kind": "fusion", "rule_name": "test_fusion_rule", "template_name": "test_template", "enabled": True} validate_required_arguments_for_alert_rule(args) # Test with a scheduled alert rule with all required arguments args = { "kind": "scheduled", "rule_name": "test_scheduled_rule", "displayName": "test_display_name", "enabled": True, "query": "test_query", "query_frequency": "test_frequency", "query_period": "test_period", "severity": "test_severity", "suppression_duration": "test_duration", "suppression_enabled": True, "trigger_operator": "test_operator", "trigger_threshold": 10, } validate_required_arguments_for_alert_rule(args) # Test with a fusion alert rule with a missing required argument args = {"kind": "fusion", "rule_name": "test_fusion_rule", "enabled": True} with pytest.raises(Exception) as e: validate_required_arguments_for_alert_rule(args) assert str(e.value) == '"template_name" is required for "fusion" alert rule.' # Test without a kind argument args = {"rule_name": "test_unknown_rule"} with pytest.raises(Exception) as e: validate_required_arguments_for_alert_rule(args) assert str(e.value) == 'The "kind" argument is required for alert rule.' def test_create_data_for_alert_rule(): """ Given - args When - running create_data_for_alert_rule Then - Ensure the function returns the expected data """ args = { "kind": "fusion", "rule_name": "test_fusion_rule", "template_name": "test_template", "enabled": True, "description": None, } expected_data = {"kind": "Fusion", "etag": None, "properties": {"alertRuleTemplateName": "test_template", "enabled": True}} data = create_data_for_alert_rule(args) assert data == expected_data def test_create_and_update_alert_rule_command(mocker): """ Given - client - args with all required arguments When - running create_alert_rule_command Then - Ensure the function returns the expected command results """ with open("test_data/create_alert_rule-mock_response.json") as file: mock_response = json.load(file) client = mock_client() mocker.patch.object(client, "http_request", return_value=mock_response) args = { "kind": "Fusion", "etag": "3d00c3ca-0000-0100-0000-5d42d5010000", "properties": {"enabled": True, "alertRuleTemplateName": "f71aba3d-28fb-450b-b192-4e76a83015c8"}, } mocker.patch("AzureSentinel.create_data_for_alert_rule", return_value=args) command_results = create_and_update_alert_rule_command(client, args) assert command_results.outputs == mock_response assert command_results.outputs_prefix == "AzureSentinel.AlertRule" assert command_results.outputs_key_field == "name" assert "|ID|Name|Kind|Severity|Display Name|Description|Enabled|Etag|" in command_results.readable_output def test_list_incident_comments_command_happy_path(mocker): """ Given: - Valid incident ID, limit, and next link. When: - Calling the list_incident_comments_command function. Then: - Ensure the function successfully retrieves comments for the given incident ID with and without a specified limit and next link. - Ensure the function returns the expected CommandResults object. """ client = mocker.Mock() args = {"incident_id": "123", "limit": "50", "next_link": ""} result = { "value": [ { "name": "comment1", "properties": { "message": "test comment 1", "author": {"assignedTo": "test user", "email": "test@test.com"}, "createdTimeUtc": "2022-01-01T00:00:00Z", }, }, { "name": "comment2", "properties": { "message": "test comment 2", "author": {"assignedTo": "test user 2", "email": "test2@test.com"}, "createdTimeUtc": "2022-01-02T00:00:00Z", }, }, ], "nextLink": "", } client.http_request.return_value = result expected_comments = [ { "ID": "comment1", "IncidentID": "123", "Message": "test comment 1", "AuthorName": "test user", "AuthorEmail": "test@test.com", "CreatedTimeUTC": "2022-01-01T00:00:00Z", }, { "ID": "comment2", "IncidentID": "123", "Message": "test comment 2", "AuthorName": "test user 2", "AuthorEmail": "test2@test.com", "CreatedTimeUTC": "2022-01-02T00:00:00Z", }, ] expected_outputs = {"AzureSentinel.IncidentComment(val.ID === obj.ID && val.IncidentID === 123)": expected_comments} expected_readable_output = tableToMarkdown( "Incident 123 Comments (2 results)", expected_comments, headers=COMMENT_HEADERS, headerTransform=pascalToSpace, removeNull=True, ) # Execute the test assert ( list_incident_comments_command(client, args).readable_output == CommandResults(readable_output=expected_readable_output, outputs=expected_outputs, raw_response=result).readable_output ) def test_update_incident_command_table_to_markdown(mocker): """ Given: - A valid incident_id and incident data. When: - Calling update_incident_command function. Then: - Ensure that the function formats the output table correctly. """ client = mock_client() mocker.patch.object(client, "http_request", return_value={"id": "123", "title": "test", "severity": "High"}) args = {"incident_id": "123", "title": "new title", "description": "new description", "severity": "High"} result = update_incident_command(client, args) expected_output = "### Updated incidents 123 details\n**No entries.**" assert result.readable_output.strip() == expected_output def test_create_incident_command(mocker): """ Given: - Valid incident data. When: - Calling create_incident_command function. Then: - The command function returns the expected raw response from the API. """ test_data = { "id": "123", "title": "test", "severity": "High", "description": "test description", "labels": [{"LabelName": "value"}], } client = mock_client() mocker.patch.object(client, "http_request", return_value=test_data) result = create_incident_command(client, test_data) assert result.raw_response == test_data def test_update_incident_with_client_changed_etag(mocker): """ Given: - An old incident to update with a delta from xsoar. - A newer version is returned from the client. When: - Updating the incident. Then: - Ensure the most updated etag is sent on update to avoid conflicts. """ client = mock_client() old_incident_data_in_xsoar = { "etag": "tag-version1", "title": "Title version 1", "severity": 1, "status": 2, "classification": "Undetermined", } delta_incident_changes = {"severity": 2} # Changed etag and title. newer_incident_from_azure = { "etag": "tag-version2", "properties": {"title": "Title version 2", "severity": 1, "status": 2, "classification": "Undetermined"}, } # return newer version when requesting incident http_request_mock = mocker.patch.object(client, "http_request", side_effect=[newer_incident_from_azure, True]) update_incident_request(client, "id-incident-1", old_incident_data_in_xsoar, delta_incident_changes, False) assert http_request_mock.call_count == 2 assert http_request_mock.call_args[1].get("data", {}).get("etag") == newer_incident_from_azure.get("etag") @pytest.mark.parametrize( "delta, data, expected", [ ( { "classification": "FalsePositive", "classificationReason": "InaccurateData", }, {}, "InaccurateData", ), ( {"classification": "FalsePositive"}, {"classificationReason": "SystemError"}, "SystemError", ), ({"classification": "FalsePositive"}, {}, "InaccurateData"), ( { "classification": "TruePositive", "classificationReason": "InaccurateData", }, {}, "SuspiciousActivity", ), ({}, {"classification": "BenignPositive"}, "SuspiciousButExpected"), ({}, {}, ""), ], ids=[ "FalsePositive classification with specific reason in delta", "FalsePositive classification with reason in data", "FalsePositive classification without specific reason", "TruePositive classification with default reason", "No classification in delta, but classification in data", "No classification in delta or data", ], ) def test_extract_classification_reason(delta, data, expected): result = extract_classification_reason(delta, data) assert result == expected def test_max_limit_argument_in_fetch_and_list_incident_commands(mocker): """ Given: - A max limit argument to the azure-sentinel-list-incidents command. When: - Execute the fetch-incident and the azure-sentinel-list-incidents commands. Then: - Ensure the the limit argument and the limit parameter were set correctly. """ # prepare args = {"limit": "201"} mocker.patch("AzureSentinel.demisto.params", return_value={"limit": "201"}) last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) # execute list_incidents_command(client, args=args) fetch_incidents(client, last_run, "3 days", "Informational") assert client.http_request.call_args_list[0][1] == {"params": {"$top": 200, "$orderby": "properties/createdTimeUtc asc"}} assert client.http_request.call_args_list[1][1] == { "params": { "$top": 50, "$filter": "properties/createdTimeUtc ge 2022-03-16T13:01:08Z", "$orderby": "properties/createdTimeUtc asc", } } def test_default_limit_argument_in_fetch_and_list_incident_commands(mocker): """ Given: - A default limit argument to the azure-sentinel-list-incidents command. When: - Execute the fetch-incident and the azure-sentinel-list-incidents commands. Then: - Ensure the the limit argument and the limit parameter were set correctly. """ # prepare args = {"limit": "50"} last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) # execute list_incidents_command(client, args=args) fetch_incidents(client, last_run, "3 days", "Informational") assert client.http_request.call_args_list[0][1] == {"params": {"$top": 50, "$orderby": "properties/createdTimeUtc asc"}} assert client.http_request.call_args_list[1][1] == { "params": { "$top": 20, "$filter": "properties/createdTimeUtc ge 2022-03-16T13:01:08Z", "$orderby": "properties/createdTimeUtc asc", } } def test_lower_then_default_limit_argument_in_fetch_and_list_incident_commands(mocker): """ Given: - A lower then default limit argument to the azure-sentinel-list-incidents command. When: - Execute the fetch-incident and the azure-sentinel-list-incidents commands. Then: - Ensure the the limit argument and the limit parameter were set correctly. """ # prepare args = {"limit": "20"} last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) # execute list_incidents_command(client, args=args) fetch_incidents(client, last_run, "3 days", "Informational") assert client.http_request.call_args_list[0][1] == {"params": {"$top": 20, "$orderby": "properties/createdTimeUtc asc"}} assert client.http_request.call_args_list[1][1] == { "params": { "$top": 20, "$filter": "properties/createdTimeUtc ge 2022-03-16T13:01:08Z", "$orderby": "properties/createdTimeUtc asc", } } def test_fetch_limit_above_default_within_max(mocker): """ Given: - A fetch limit parameter set to a value above the default (20) but within the max (50). When: - Executing the fetch-incidents command. Then: - Ensure the configured value is honored (not clamped down to the old hard-coded 20). """ # prepare mocker.patch("AzureSentinel.demisto.params", return_value={"limit": "50"}) last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) # execute fetch_incidents(client, last_run, "3 days", "Informational") # validate assert client.http_request.call_args_list[0][1] == { "params": { "$top": 50, "$filter": "properties/createdTimeUtc ge 2022-03-16T13:01:08Z", "$orderby": "properties/createdTimeUtc asc", } } def test_statuses_to_fetch_parameter_not_used(mocker): """ Given: - No statuses_to_fetch parameter configured (empty list). When: - Execute the fetch-incidents command. Then: - Ensure the filter query does not contain any status check. """ # prepare last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(demisto, "getLastRun", return_value=last_run) params = {} # execute fetch_incidents_command(client, params) # validate expected_filter = "properties/createdTimeUtc ge 2022-03-16T13:01:08Z" assert client.http_request.call_args_list[0][1] == { "params": { "$top": 20, "$filter": expected_filter, "$orderby": "properties/createdTimeUtc asc", } } def test_statuses_to_fetch_parameter_single_status(mocker): """ Given: - A single status in statuses_to_fetch parameter. When: - Execute the fetch-incidents command. Then: - Ensure the filter query contains a status equality check. """ # prepare last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(demisto, "getLastRun", return_value=last_run) params = {"statuses_to_fetch": ["New"]} # execute fetch_incidents_command(client, params) # validate expected_filter = "properties/createdTimeUtc ge 2022-03-16T13:01:08Z and (properties/status eq 'New')" assert client.http_request.call_args_list[0][1] == { "params": { "$top": 20, "$filter": expected_filter, "$orderby": "properties/createdTimeUtc asc", } } def test_statuses_to_fetch_parameter_multiple_statuses(mocker): """ Given: - Multiple statuses in statuses_to_fetch parameter. When: - Execute the fetch-incidents command. Then: - Ensure the filter query contains a status 'in' check for multiple values. """ # prepare last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(demisto, "getLastRun", return_value=last_run) params = {"statuses_to_fetch": ["New", "Active", "Closed"]} # execute fetch_incidents_command(client, params) # validate expected_filter = ( "properties/createdTimeUtc ge 2022-03-16T13:01:08Z and " "(properties/status eq 'New' or properties/status eq 'Active' or properties/status eq 'Closed')" ) assert client.http_request.call_args_list[0][1] == { "params": { "$top": 20, "$filter": expected_filter, "$orderby": "properties/createdTimeUtc asc", } } def test_odata_filter_parameters(mocker): """ Given: - Multiple filter parameters. When: - Execute the fetch-incidents command. Then: - Ensure the filter query contains all the provided filter parameters. """ # prepare last_run = {"last_fetch_time": "2022-03-16T13:01:08Z", "last_fetch_ids": []} client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) mocker.patch("AzureSentinel.process_incidents", return_value=({}, [])) mocker.patch.object(demisto, "getLastRun", return_value=last_run) params = { "titles_to_not_fetch": ["test_title"], "alert_product_names_to_not_fetch": ["test_alert_product_name"], } # execute fetch_incidents_command(client, params) # validate expected_filter = ( "properties/createdTimeUtc ge 2022-03-16T13:01:08Z and " "(not properties/additionalData/alertProductNames/any(x:x eq 'test_alert_product_name')) and " "((contains(properties/title, 'test_title') ne true))" ) assert client.http_request.call_args_list[0][1] == { "params": { "$top": 20, "$filter": expected_filter, "$orderby": "properties/createdTimeUtc asc", } } def test_main_uses_new_separate_client_id(mocker): """ Given - The new 'creds_client_id' param is provided with a Client ID value. - The legacy 'credentials' param is NOT provided. When - main() is called. Then - AzureSentinelClient is instantiated with client_id taken from 'creds_client_id'. """ import AzureSentinel from AzureSentinel import main params = { "creds_client_id": {"password": "new-client-id"}, "credentials": {"password": "client-secret"}, "creds_tenant_id": {"password": "tenant-id"}, "subscriptionID": "sub-id", "resourceGroupName": "rg-name", "workspaceName": "ws-name", "azure_cloud": "Worldwide", } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="test-module") mock_client_cls = mocker.patch("AzureSentinel.AzureSentinelClient", autospec=True) mocker.patch.object(AzureSentinel, "return_results") mocker.patch("AzureSentinel.test_module", return_value="ok") main() call_kwargs = mock_client_cls.call_args[1] assert call_kwargs["client_id"] == "new-client-id" def test_main_falls_back_to_legacy_client_id_when_new_param_absent(mocker): """ Given - The new 'creds_client_id' param is NOT provided. - The legacy 'credentials' param IS provided with both identifier (client_id) and password (client_secret). When - main() is called. Then - AzureSentinelClient is instantiated with client_id taken from 'credentials.identifier' (legacy fallback). """ import AzureSentinel from AzureSentinel import main params = { "credentials": {"identifier": "legacy-client-id", "password": "legacy-client-secret"}, "creds_tenant_id": {"password": "tenant-id"}, "subscriptionID": "sub-id", "resourceGroupName": "rg-name", "workspaceName": "ws-name", "azure_cloud": "Worldwide", } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="test-module") mock_client_cls = mocker.patch("AzureSentinel.AzureSentinelClient", autospec=True) mocker.patch.object(AzureSentinel, "return_results") mocker.patch("AzureSentinel.test_module", return_value="ok") main() call_kwargs = mock_client_cls.call_args[1] assert call_kwargs["client_id"] == "legacy-client-id" @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_dedup_lookback_incident_in_both_fetch_and_lookback(): """ Given: - An incident that appears in both the regular fetch and the lookback query. When: - Calling dedup_lookback_incidents. Then: - The incident is not returned in deduped_incidents (already fetched by regular fetch). - The incident ID is added to the updated lookback dict (to prevent re-ingestion in future cycles). """ from AzureSentinel import dedup_lookback_incidents lookback_incidents = [{"ID": "inc-1", "LastModifiedTimeUTC": "2026-05-11T12:00:00Z"}] previous_lookback_ids = {} incidents_ids_from_fetch = ["inc-1"] look_back = 60 deduped, updated_ids = dedup_lookback_incidents( lookback_incidents=lookback_incidents, previous_lookback_ids=previous_lookback_ids, incidents_ids_from_fetch=incidents_ids_from_fetch, look_back=look_back, ) assert deduped == [], "Incident should not be in deduped list since it was already in regular fetch" assert "inc-1" in updated_ids, "Incident should be tracked in lookback dict for future dedup" assert updated_ids["inc-1"] == "2026-05-11T12:00:00Z" @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_dedup_lookback_incident_already_in_previous_lookback(): """ Given: - An incident that was already ingested in a previous lookback cycle and still appears in the current lookback query. When: - Calling dedup_lookback_incidents. Then: - The incident is not returned in deduped_incidents (already ingested). - The incident ID remains in the updated lookback dict. """ from AzureSentinel import dedup_lookback_incidents lookback_incidents = [{"ID": "inc-1", "LastModifiedTimeUTC": "2026-05-11T12:00:00Z"}] previous_lookback_ids = {"inc-1": "2026-05-11T11:50:00Z"} incidents_ids_from_fetch = [] look_back = 60 deduped, updated_ids = dedup_lookback_incidents( lookback_incidents=lookback_incidents, previous_lookback_ids=previous_lookback_ids, incidents_ids_from_fetch=incidents_ids_from_fetch, look_back=look_back, ) assert deduped == [], "Incident should not be re-ingested since it was already in previous lookback" assert "inc-1" in updated_ids, "Incident should remain in the lookback dict" @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_dedup_lookback_new_incident_fetched_and_added_to_dict(): """ Given: - A new incident found by the lookback query that was not in previous lookback cycles and not in the regular fetch. When: - Calling dedup_lookback_incidents. Then: - The incident is returned in deduped_incidents. - The incident ID is added to the updated lookback dict. """ from AzureSentinel import dedup_lookback_incidents lookback_incidents = [{"ID": "inc-new", "LastModifiedTimeUTC": "2026-05-11T12:30:00Z"}] previous_lookback_ids = {"inc-old": "2026-05-11T11:00:00Z"} incidents_ids_from_fetch = [] look_back = 60 deduped, updated_ids = dedup_lookback_incidents( lookback_incidents=lookback_incidents, previous_lookback_ids=previous_lookback_ids, incidents_ids_from_fetch=incidents_ids_from_fetch, look_back=look_back, ) assert len(deduped) == 1, "New incident should be returned" assert deduped[0]["ID"] == "inc-new" assert "inc-new" in updated_ids, "New incident should be added to the lookback dict" assert updated_ids["inc-new"] == "2026-05-11T12:30:00Z" assert "inc-old" in updated_ids, "Previous active IDs should be preserved" @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_dedup_lookback_expired_ids_removed_from_dict(): """ Given: - Previous lookback dict contains an incident with a lastModifiedTimeUtc that is older than 2x the lookback window (expired). When: - Calling dedup_lookback_incidents. Then: - The expired incident ID is removed from the updated lookback dict. - Active (non-expired) IDs are preserved. """ from AzureSentinel import dedup_lookback_incidents lookback_incidents = [] previous_lookback_ids = { "inc-expired": "2020-01-01T00:00:00Z", "inc-active": "2026-05-11T12:00:00Z", } incidents_ids_from_fetch = [] look_back = 60 deduped, updated_ids = dedup_lookback_incidents( lookback_incidents=lookback_incidents, previous_lookback_ids=previous_lookback_ids, incidents_ids_from_fetch=incidents_ids_from_fetch, look_back=look_back, ) assert deduped == [] assert "inc-expired" not in updated_ids, "Expired ID should be removed from the dict" assert "inc-active" in updated_ids, "Active ID should be preserved in the dict" @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_fetch_incidents_lookback_builds_correct_filter(mocker): """ Given: - A client and lookback parameters with min_severity=High and statuses_to_fetch=["New"]. When: - Calling fetch_incidents_lookback. Then: - The filter query uses lastModifiedTimeUtc and includes severity and status filters. - The orderby uses lastModifiedTimeUtc asc. """ from AzureSentinel import fetch_incidents_lookback client = mock_client() mocker.patch.object(client, "http_request", return_value=MOCKED_INCIDENTS_OUTPUT) result = fetch_incidents_lookback( client=client, lookback_start_time="2026-05-11T12:00:00Z", min_severity="High", statuses_to_fetch=["New"], ) call_args = client.http_request.call_args[1] filter_expr = call_args["params"]["$filter"] assert "properties/lastModifiedTimeUtc ge 2026-05-11T12:00:00Z" in filter_expr assert "properties/severity eq 'High'" in filter_expr assert "properties/status eq 'New'" in filter_expr assert call_args["params"]["$orderby"] == "properties/lastModifiedTimeUtc asc" assert len(result) == 1 @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_fetch_incidents_lookback_returns_empty_on_no_results(mocker): """ Given: - A client where the API returns no incidents in the lookback window. When: - Calling fetch_incidents_lookback. Then: - An empty list is returned without errors. """ from AzureSentinel import fetch_incidents_lookback client = mock_client() mocker.patch.object(client, "http_request", return_value={"value": []}) result = fetch_incidents_lookback( client=client, lookback_start_time="2026-05-11T12:00:00Z", min_severity="Informational", statuses_to_fetch=[], ) assert result == [] @freezegun.freeze_time("2026-05-11T12:30:00Z") def test_fetch_incidents_e2e_with_lookback(mocker): """ Given: - A client with regular fetch returning one incident (inc_name) and lookback returning a different incident (inc_lookback) that was modified in the lookback window. - look_back=60 minutes, no previous lookback IDs. When: - Calling fetch_incidents with look_back=60. Then: - next_run contains both regular fetch IDs and lookback IDs. - incidents list contains both the regular and lookback incidents. - The lookback incident is appended after the regular incidents. """ client = mock_client() # Regular fetch API response (inc_name) regular_api_response = { "value": [ { "name": "inc_name", "properties": { "incidentNumber": 1, "title": "Regular Incident", "description": "desc", "severity": "High", "status": "New", "owner": {"assignedTo": "user", "email": "user@test.com"}, "labels": [], "firstActivityTimeUtc": "2026-05-11T12:00:00Z", "lastActivityTimeUtc": "2026-05-11T12:00:00Z", "lastModifiedTimeUtc": "2026-05-11T12:00:00Z", "createdTimeUtc": "2026-05-11T12:00:00Z", "additionalData": { "alertsCount": 0, "bookmarksCount": 0, "commentsCount": 0, "alertProductNames": [], "tactics": [], }, "firstActivityTimeGenerated": "2026-05-11T12:00:00Z", "lastActivityTimeGenerated": "2026-05-11T12:00:00Z", }, } ] } # Lookback API response (inc_lookback - different incident modified in lookback window) lookback_api_response = { "value": [ { "name": "inc_lookback", "properties": { "incidentNumber": 5, "title": "Lookback Incident", "description": "escalated severity", "severity": "High", "status": "New", "owner": {"assignedTo": "user", "email": "user@test.com"}, "labels": [], "firstActivityTimeUtc": "2026-05-11T11:00:00Z", "lastActivityTimeUtc": "2026-05-11T12:20:00Z", "lastModifiedTimeUtc": "2026-05-11T12:20:00Z", "createdTimeUtc": "2026-05-11T11:00:00Z", "additionalData": { "alertsCount": 0, "bookmarksCount": 0, "commentsCount": 0, "alertProductNames": [], "tactics": [], }, "firstActivityTimeGenerated": "2026-05-11T11:00:00Z", "lastActivityTimeGenerated": "2026-05-11T12:20:00Z", }, } ] } # First call = regular fetch, second call = lookback fetch mocker.patch.object(client, "http_request", side_effect=[regular_api_response, lookback_api_response]) mocker.patch("AzureSentinel.demisto.params", return_value={"fetch_additional_info": []}) last_run = { "last_fetch_time": "2026-05-11T12:00:00Z", "last_fetch_ids": [], "last_incident_number": 0, } next_run, incidents = fetch_incidents( client=client, last_run=last_run, first_fetch_time="3 days", min_severity="Informational", statuses_to_fetch=[], look_back=60, ) # Validate next_run has regular fetch IDs assert "inc_name" in next_run["last_fetch_ids"] assert next_run["last_incident_number"] == 1 # Validate next_run has lookback IDs tracked assert "inc_lookback" in next_run["lookback_fetch_ids"] # Validate incidents list contains both regular and lookback incidents assert len(incidents) == 2 assert incidents[0]["name"] == "[Azure Sentinel] Regular Incident" assert incidents[1]["name"] == "[Azure Sentinel] Lookback Incident"