diff --git a/src/securityinsight/HISTORY.rst b/src/securityinsight/HISTORY.rst
new file mode 100644
index 00000000000..1c139576ba0
--- /dev/null
+++ b/src/securityinsight/HISTORY.rst
@@ -0,0 +1,8 @@
+.. :changelog:
+
+Release History
+===============
+
+0.1.0
+++++++
+* Initial release.
diff --git a/src/securityinsight/README.md b/src/securityinsight/README.md
new file mode 100644
index 00000000000..90913a91f07
--- /dev/null
+++ b/src/securityinsight/README.md
@@ -0,0 +1,184 @@
+# Azure CLI sentinel Extension #
+This is the extension for sentinel
+
+### How to use ###
+Install this extension using the below CLI command
+```
+az extension add --name sentinel
+```
+
+### Included Features ###
+#### sentinel alert-rule ####
+##### Create #####
+```
+az sentinel alert-rule create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+ --logic-app-resource-id "/subscriptions/d0cfe6b2-9ac0-4464-9919-dccaee2e48c0/resourceGroups/myRg/providers/Microsoft.Logic/workflows/MyAlerts" \
+ --trigger-uri "https://prod-31.northcentralus.logic.azure.com:443/workflows/cd3765391efd48549fd7681ded1d48d7/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=signature" \
+ --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" \
+ --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "myFirstFusionRule" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "microsoftSecurityIncidentCreationRuleExample" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+ --workspace-name "myWorkspace"
+```
+##### List #####
+```
+az sentinel alert-rule list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Get-action #####
+```
+az sentinel alert-rule get-action --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" \
+ --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+```
+##### Delete #####
+```
+az sentinel alert-rule delete --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" \
+ --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+```
+#### sentinel action ####
+##### List #####
+```
+az sentinel action list --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+ --workspace-name "myWorkspace"
+```
+#### sentinel alert-rule-template ####
+##### List #####
+```
+az sentinel alert-rule-template list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel alert-rule-template show --alert-rule-template-id "65360bb0-8986-4ade-a89d-af3cf44d28aa" \
+ --resource-group "myRg" --workspace-name "myWorkspace"
+```
+#### sentinel bookmark ####
+##### Create #####
+```
+az sentinel bookmark create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --created "2019-01-01T13:15:30Z" \
+ --display-name "My bookmark" --labels "Tag1" --labels "Tag2" --notes "Found a suspicious activity" \
+ --query "SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)" \
+ --query-result "Security Event query result" --updated "2019-01-01T13:15:30Z" \
+ --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel bookmark show --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### List #####
+```
+az sentinel bookmark list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Delete #####
+```
+az sentinel bookmark delete --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+#### sentinel data-connector ####
+##### Create #####
+```
+az sentinel data-connector create \
+ --office-data-connector etag="\\"0300bf09-0000-0000-0000-5c37296e0000\\"" tenant-id="2070ecc9-b4d5-4ae4-adaa-936fa1954fa8" \
+ --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "763f9fa1-c2d3-4fa2-93e9-bccd4899aa12" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "b96d014d-b5c2-4a01-9aba-a8058f629d42" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "06b3ccb8-1384-4bcc-aec7-852f6d57161b" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "f0cd27d2-5f03-4c06-ba31-d2dc82dcb51d" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "07e42cb3-e658-4e90-801c-efa0f29d3d44" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel data-connector show --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### List #####
+```
+az sentinel data-connector list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Delete #####
+```
+az sentinel data-connector delete --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+#### sentinel incident ####
+##### Create #####
+```
+az sentinel incident create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+ --description "This is a demo incident" --classification "FalsePositive" \
+ --classification-comment "Not a malicious activity" --classification-reason "IncorrectAlertLogic" \
+ --first-activity-time-utc "2019-01-01T13:00:30Z" --last-activity-time-utc "2019-01-01T13:05:30Z" \
+ --owner object-id="2046feea-040d-4a46-9e2b-91c2941bfa70" --severity "High" --status "Closed" --title "My incident" \
+ --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel incident show --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### List #####
+```
+az sentinel incident list --orderby "properties/createdTimeUtc desc" --top 1 --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+##### Delete #####
+```
+az sentinel incident delete --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
+#### sentinel incident-comment ####
+##### Create #####
+```
+az sentinel incident-comment create --message "Some message" \
+ --incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+ --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Show #####
+```
+az sentinel incident-comment show --incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" \
+ --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### List #####
+```
+az sentinel incident-comment list --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+ --workspace-name "myWorkspace"
+```
\ No newline at end of file
diff --git a/src/securityinsight/azext_sentinel/__init__.py b/src/securityinsight/azext_sentinel/__init__.py
new file mode 100644
index 00000000000..cba11ad4731
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/__init__.py
@@ -0,0 +1,50 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+from azure.cli.core import AzCommandsLoader
+from azext_sentinel.generated._help import helps # pylint: disable=unused-import
+try:
+ from azext_sentinel.manual._help import helps # pylint: disable=reimported
+except ImportError:
+ pass
+
+
+class SecurityInsightsCommandsLoader(AzCommandsLoader):
+
+ def __init__(self, cli_ctx=None):
+ from azure.cli.core.commands import CliCommandType
+ from azext_sentinel.generated._client_factory import cf_sentinel_cl
+ sentinel_custom = CliCommandType(
+ operations_tmpl='azext_sentinel.custom#{}',
+ client_factory=cf_sentinel_cl)
+ parent = super(SecurityInsightsCommandsLoader, self)
+ parent.__init__(cli_ctx=cli_ctx, custom_command_type=sentinel_custom)
+
+ def load_command_table(self, args):
+ from azext_sentinel.generated.commands import load_command_table
+ load_command_table(self, args)
+ try:
+ from azext_sentinel.manual.commands import load_command_table as load_command_table_manual
+ load_command_table_manual(self, args)
+ except ImportError:
+ pass
+ return self.command_table
+
+ def load_arguments(self, command):
+ from azext_sentinel.generated._params import load_arguments
+ load_arguments(self, command)
+ try:
+ from azext_sentinel.manual._params import load_arguments as load_arguments_manual
+ load_arguments_manual(self, command)
+ except ImportError:
+ pass
+
+
+COMMAND_LOADER_CLS = SecurityInsightsCommandsLoader
diff --git a/src/securityinsight/azext_sentinel/action.py b/src/securityinsight/azext_sentinel/action.py
new file mode 100644
index 00000000000..d95d53bf711
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/action.py
@@ -0,0 +1,17 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=wildcard-import
+# pylint: disable=unused-wildcard-import
+
+from .generated.action import * # noqa: F403
+try:
+ from .manual.action import * # noqa: F403
+except ImportError:
+ pass
diff --git a/src/securityinsight/azext_sentinel/azext_metadata.json b/src/securityinsight/azext_sentinel/azext_metadata.json
new file mode 100644
index 00000000000..4f48fa652a5
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/azext_metadata.json
@@ -0,0 +1,4 @@
+{
+ "azext.isExperimental": true,
+ "azext.minCliCoreVersion": "2.11.0"
+}
\ No newline at end of file
diff --git a/src/securityinsight/azext_sentinel/custom.py b/src/securityinsight/azext_sentinel/custom.py
new file mode 100644
index 00000000000..dbe9d5f9742
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/custom.py
@@ -0,0 +1,17 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=wildcard-import
+# pylint: disable=unused-wildcard-import
+
+from .generated.custom import * # noqa: F403
+try:
+ from .manual.custom import * # noqa: F403
+except ImportError:
+ pass
diff --git a/src/securityinsight/azext_sentinel/generated/__init__.py b/src/securityinsight/azext_sentinel/generated/__init__.py
new file mode 100644
index 00000000000..c9cfdc73e77
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/__init__.py
@@ -0,0 +1,12 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/securityinsight/azext_sentinel/generated/_client_factory.py b/src/securityinsight/azext_sentinel/generated/_client_factory.py
new file mode 100644
index 00000000000..6868ae4601c
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/_client_factory.py
@@ -0,0 +1,44 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+
+def cf_sentinel_cl(cli_ctx, *_):
+ from azure.cli.core.commands.client_factory import get_mgmt_service_client
+ from ..vendored_sdks.securityinsight import SecurityInsights
+ return get_mgmt_service_client(cli_ctx,
+ SecurityInsights)
+
+
+def cf_alert_rule(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).alert_rule
+
+
+def cf_action(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).action
+
+
+def cf_alert_rule_template(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).alert_rule_template
+
+
+def cf_bookmark(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).bookmark
+
+
+def cf_data_connector(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).data_connector
+
+
+def cf_incident(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).incident
+
+
+def cf_incident_comment(cli_ctx, *_):
+ return cf_sentinel_cl(cli_ctx).incident_comment
diff --git a/src/securityinsight/azext_sentinel/generated/_help.py b/src/securityinsight/azext_sentinel/generated/_help.py
new file mode 100644
index 00000000000..09a6f71e5c0
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/_help.py
@@ -0,0 +1,676 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=too-many-lines
+
+from knack.help_files import helps
+
+
+helps['sentinel alert-rule'] = """
+ type: group
+ short-summary: sentinel alert-rule
+"""
+
+helps['sentinel alert-rule list'] = """
+ type: command
+ short-summary: "Gets all alert rules."
+ examples:
+ - name: Get all alert rules.
+ text: |-
+ az sentinel alert-rule list --resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule show'] = """
+ type: command
+ short-summary: "Gets the alert rule."
+ examples:
+ - name: Get a Fusion alert rule.
+ text: |-
+ az sentinel alert-rule show --resource-group "myRg" --rule-id "myFirstFusionRule" --workspace-name \
+"myWorkspace"
+ - name: Get a MicrosoftSecurityIncidentCreation rule.
+ text: |-
+ az sentinel alert-rule show --resource-group "myRg" --rule-id "microsoftSecurityIncidentCreationRuleExam\
+ple" --workspace-name "myWorkspace"
+ - name: Get a Scheduled alert rule.
+ text: |-
+ az sentinel alert-rule show --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule create'] = """
+ type: command
+ short-summary: "Creates or updates the action of alert rule. And Create the alert rule."
+ parameters:
+ - name: --fusion-alert-rule
+ short-summary: "Represents Fusion alert rule."
+ long-summary: |
+ Usage: --fusion-alert-rule alert-rule-template-name=XX enabled=XX kind=XX etag=XX
+
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+ - name: --microsoft-security-incident-creation-alert-rule
+ short-summary: "Represents MicrosoftSecurityIncidentCreation rule."
+ long-summary: |
+ Usage: --microsoft-security-incident-creation-alert-rule display-names-filter=XX \
+display-names-exclude-filter=XX product-filter=XX severities-filter=XX alert-rule-template-name=XX description=XX \
+display-name=XX enabled=XX kind=XX etag=XX
+
+ display-names-filter: the alerts' displayNames on which the cases will be generated
+ display-names-exclude-filter: the alerts' displayNames on which the cases will not be generated
+ product-filter: The alerts' productName on which the cases will be generated
+ severities-filter: the alerts' severities on which the cases will be generated
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ description: The description of the alert rule.
+ display-name: The display name for alerts created by this alert rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+ - name: --scheduled-alert-rule
+ short-summary: "Represents scheduled alert rule."
+ long-summary: |
+ Usage: --scheduled-alert-rule query=XX query-frequency=XX query-period=XX severity=XX trigger-operator=XX \
+trigger-threshold=XX alert-rule-template-name=XX description=XX display-name=XX enabled=XX suppression-duration=XX \
+suppression-enabled=XX tactics=XX kind=XX etag=XX
+
+ query: The query that creates alerts for this rule.
+ query-frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ query-period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ severity: The severity for alerts created by this alert rule.
+ trigger-operator: The operation against the threshold that triggers alert rule.
+ trigger-threshold: The threshold triggers this alert rule.
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ description: The description of the alert rule.
+ display-name: The display name for alerts created by this alert rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ suppression-duration: The suppression (in ISO 8601 duration format) to wait since last time this alert \
+rule been triggered.
+ suppression-enabled: Determines whether the suppression for this alert rule is enabled or disabled.
+ tactics: The tactics of the alert rule
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+ examples:
+ - name: Creates or updates an action of alert rule.
+ text: |-
+ az sentinel alert-rule create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+--logic-app-resource-id "/subscriptions/d0cfe6b2-9ac0-4464-9919-dccaee2e48c0/resourceGroups/myRg/providers/Microsoft.Lo\
+gic/workflows/MyAlerts" --trigger-uri "https://prod-31.northcentralus.logic.azure.com:443/workflows/cd3765391efd48549fd\
+7681ded1d48d7/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=signature" \
+--action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2\
+ab5" --workspace-name "myWorkspace"
+ - name: Creates or updates a Fusion alert rule.
+ text: |-
+ az sentinel alert-rule create --fusion-alert-rule etag="3d00c3ca-0000-0100-0000-5d42d5010000" \
+alert-rule-template-name="f71aba3d-28fb-450b-b192-4e76a83015c8" enabled=true --resource-group "myRg" --rule-id \
+"myFirstFusionRule" --workspace-name "myWorkspace"
+ - name: Creates or updates a MicrosoftSecurityIncidentCreation rule.
+ text: |-
+ az sentinel alert-rule create --microsoft-security-incident-creation-alert-rule \
+etag="\\"260097e0-0000-0d00-0000-5d6fa88f0000\\"" product-filter="Microsoft Cloud App Security" display-name="testing \
+displayname" enabled=true --resource-group "myRg" --rule-id "microsoftSecurityIncidentCreationRuleExample" \
+--workspace-name "myWorkspace"
+ - name: Creates or updates a Scheduled alert rule.
+ text: |-
+ az sentinel alert-rule create --scheduled-alert-rule etag="\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+query="ProtectionStatus | extend HostCustomEntity = Computer | extend IPCustomEntity = ComputerIP_Hidden" \
+query-frequency="PT1H" query-period="P2DT1H30M" severity="High" trigger-operator="GreaterThan" trigger-threshold=0 \
+description="" display-name="Rule2" enabled=true suppression-duration="PT1H" suppression-enabled=false \
+tactics="Persistence" tactics="LateralMovement" --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5\
+" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule update'] = """
+ type: command
+ short-summary: "Update the alert rule."
+ parameters:
+ - name: --fusion-alert-rule
+ short-summary: "Represents Fusion alert rule."
+ long-summary: |
+ Usage: --fusion-alert-rule alert-rule-template-name=XX enabled=XX kind=XX etag=XX
+
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+ - name: --microsoft-security-incident-creation-alert-rule
+ short-summary: "Represents MicrosoftSecurityIncidentCreation rule."
+ long-summary: |
+ Usage: --microsoft-security-incident-creation-alert-rule display-names-filter=XX \
+display-names-exclude-filter=XX product-filter=XX severities-filter=XX alert-rule-template-name=XX description=XX \
+display-name=XX enabled=XX kind=XX etag=XX
+
+ display-names-filter: the alerts' displayNames on which the cases will be generated
+ display-names-exclude-filter: the alerts' displayNames on which the cases will not be generated
+ product-filter: The alerts' productName on which the cases will be generated
+ severities-filter: the alerts' severities on which the cases will be generated
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ description: The description of the alert rule.
+ display-name: The display name for alerts created by this alert rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+ - name: --scheduled-alert-rule
+ short-summary: "Represents scheduled alert rule."
+ long-summary: |
+ Usage: --scheduled-alert-rule query=XX query-frequency=XX query-period=XX severity=XX trigger-operator=XX \
+trigger-threshold=XX alert-rule-template-name=XX description=XX display-name=XX enabled=XX suppression-duration=XX \
+suppression-enabled=XX tactics=XX kind=XX etag=XX
+
+ query: The query that creates alerts for this rule.
+ query-frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ query-period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ severity: The severity for alerts created by this alert rule.
+ trigger-operator: The operation against the threshold that triggers alert rule.
+ trigger-threshold: The threshold triggers this alert rule.
+ alert-rule-template-name: The Name of the alert rule template used to create this rule.
+ description: The description of the alert rule.
+ display-name: The display name for alerts created by this alert rule.
+ enabled: Determines whether this alert rule is enabled or disabled.
+ suppression-duration: The suppression (in ISO 8601 duration format) to wait since last time this alert \
+rule been triggered.
+ suppression-enabled: Determines whether the suppression for this alert rule is enabled or disabled.
+ tactics: The tactics of the alert rule
+ kind: Required. The alert rule kind
+ etag: Etag of the azure resource
+"""
+
+helps['sentinel alert-rule delete'] = """
+ type: command
+ short-summary: "Delete the action of alert rule. And Delete the alert rule."
+ examples:
+ - name: Delete an action of alert rule.
+ text: |-
+ az sentinel alert-rule delete --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group \
+"myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+ - name: Delete an alert rule.
+ text: |-
+ az sentinel alert-rule delete --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule get-action'] = """
+ type: command
+ short-summary: "Gets the action of alert rule."
+ examples:
+ - name: Get an action of alert rule.
+ text: |-
+ az sentinel alert-rule get-action --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group \
+"myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel action'] = """
+ type: group
+ short-summary: sentinel action
+"""
+
+helps['sentinel action list'] = """
+ type: command
+ short-summary: "Gets all actions of alert rule."
+ examples:
+ - name: Get all actions of alert rule.
+ text: |-
+ az sentinel action list --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule-template'] = """
+ type: group
+ short-summary: sentinel alert-rule-template
+"""
+
+helps['sentinel alert-rule-template list'] = """
+ type: command
+ short-summary: "Gets all alert rule templates."
+ examples:
+ - name: Get all alert rule templates.
+ text: |-
+ az sentinel alert-rule-template list --resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel alert-rule-template show'] = """
+ type: command
+ short-summary: "Gets the alert rule template."
+ examples:
+ - name: Get alert rule template by Id.
+ text: |-
+ az sentinel alert-rule-template show --alert-rule-template-id "65360bb0-8986-4ade-a89d-af3cf44d28aa" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel bookmark'] = """
+ type: group
+ short-summary: sentinel bookmark
+"""
+
+helps['sentinel bookmark list'] = """
+ type: command
+ short-summary: "Gets all bookmarks."
+ examples:
+ - name: Get all bookmarks.
+ text: |-
+ az sentinel bookmark list --resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel bookmark show'] = """
+ type: command
+ short-summary: "Gets a bookmark."
+ examples:
+ - name: Get a bookmark.
+ text: |-
+ az sentinel bookmark show --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel bookmark create'] = """
+ type: command
+ short-summary: "Create the bookmark."
+ parameters:
+ - name: --incident-info
+ short-summary: "Describes an incident that relates to bookmark"
+ long-summary: |
+ Usage: --incident-info incident-id=XX severity=XX title=XX relation-name=XX
+
+ incident-id: Required. Incident Id
+ severity: Required. The severity of the incident
+ title: Required. The title of the incident
+ relation-name: Required. Relation Name
+ examples:
+ - name: Creates or updates a bookmark.
+ text: |-
+ az sentinel bookmark create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --created \
+"2019-01-01T13:15:30Z" --display-name "My bookmark" --labels "Tag1" --labels "Tag2" --notes "Found a suspicious \
+activity" --query "SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)" --query-result "Security \
+Event query result" --updated "2019-01-01T13:15:30Z" --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel bookmark update'] = """
+ type: command
+ short-summary: "Update the bookmark."
+ parameters:
+ - name: --incident-info
+ short-summary: "Describes an incident that relates to bookmark"
+ long-summary: |
+ Usage: --incident-info incident-id=XX severity=XX title=XX relation-name=XX
+
+ incident-id: Required. Incident Id
+ severity: Required. The severity of the incident
+ title: Required. The title of the incident
+ relation-name: Required. Relation Name
+"""
+
+helps['sentinel bookmark delete'] = """
+ type: command
+ short-summary: "Delete the bookmark."
+ examples:
+ - name: Delete a bookmark.
+ text: |-
+ az sentinel bookmark delete --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group \
+"myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel data-connector'] = """
+ type: group
+ short-summary: sentinel data-connector
+"""
+
+helps['sentinel data-connector list'] = """
+ type: command
+ short-summary: "Gets all data connectors."
+ examples:
+ - name: Get all data connectors.
+ text: |-
+ az sentinel data-connector list --resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel data-connector show'] = """
+ type: command
+ short-summary: "Gets a data connector."
+ examples:
+ - name: Get a ASC data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "763f9fa1-c2d3-4fa2-93e9-bccd4899aa12" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get a MCAS data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "b96d014d-b5c2-4a01-9aba-a8058f629d42" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get a MDATP data connector
+ text: |-
+ az sentinel data-connector show --data-connector-id "06b3ccb8-1384-4bcc-aec7-852f6d57161b" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get a TI data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get an AAD data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "f0cd27d2-5f03-4c06-ba31-d2dc82dcb51d" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get an AATP data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "07e42cb3-e658-4e90-801c-efa0f29d3d44" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get an AwsCloudTrail data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+ - name: Get an Office365 data connector.
+ text: |-
+ az sentinel data-connector show --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel data-connector create'] = """
+ type: command
+ short-summary: "Create the data connector."
+ parameters:
+ - name: --aad-data-connector
+ short-summary: "Represents AAD (Azure Active Directory) data connector."
+ long-summary: |
+ Usage: --aad-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --aatp-data-connector
+ short-summary: "Represents AATP (Azure Advanced Threat Protection) data connector."
+ long-summary: |
+ Usage: --aatp-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --asc-data-connector
+ short-summary: "Represents ASC (Azure Security Center) data connector."
+ long-summary: |
+ Usage: --asc-data-connector subscription-id=XX state=XX kind=XX etag=XX
+
+ subscription-id: The subscription id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --aws-cloud-trail-data-connector
+ short-summary: "Represents Amazon Web Services CloudTrail data connector."
+ long-summary: |
+ Usage: --aws-cloud-trail-data-connector aws-role-arn=XX state=XX kind=XX etag=XX
+
+ aws-role-arn: The Aws Role Arn (with CloudTrailReadOnly policy) that is used to access the Aws account.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --mcas-data-connector
+ short-summary: "Represents MCAS (Microsoft Cloud App Security) data connector."
+ long-summary: |
+ Usage: --mcas-data-connector tenant-id=XX state-data-types-alerts-state=XX state-data-types-discovery-logs-\
+state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state-data-types-alerts-state: Describe whether this data type connection is enabled or not.
+ state-data-types-discovery-logs-state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --mdatp-data-connector
+ short-summary: "Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector."
+ long-summary: |
+ Usage: --mdatp-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --office-data-connector
+ short-summary: "Represents office data connector."
+ long-summary: |
+ Usage: --office-data-connector tenant-id=XX state-data-types-share-point-state=XX \
+state-data-types-exchange-state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state-data-types-share-point-state: Describe whether this data type connection is enabled or not.
+ state-data-types-exchange-state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --ti-data-connector
+ short-summary: "Represents threat intelligence data connector."
+ long-summary: |
+ Usage: --ti-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ examples:
+ - name: Creates or updates an Office365 data connector.
+ text: |-
+ az sentinel data-connector create --office-data-connector etag="\\"0300bf09-0000-0000-0000-5c37296e0000\
+\\"" tenant-id="2070ecc9-b4d5-4ae4-adaa-936fa1954fa8" --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel data-connector update'] = """
+ type: command
+ short-summary: "Update the data connector."
+ parameters:
+ - name: --aad-data-connector
+ short-summary: "Represents AAD (Azure Active Directory) data connector."
+ long-summary: |
+ Usage: --aad-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --aatp-data-connector
+ short-summary: "Represents AATP (Azure Advanced Threat Protection) data connector."
+ long-summary: |
+ Usage: --aatp-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --asc-data-connector
+ short-summary: "Represents ASC (Azure Security Center) data connector."
+ long-summary: |
+ Usage: --asc-data-connector subscription-id=XX state=XX kind=XX etag=XX
+
+ subscription-id: The subscription id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --aws-cloud-trail-data-connector
+ short-summary: "Represents Amazon Web Services CloudTrail data connector."
+ long-summary: |
+ Usage: --aws-cloud-trail-data-connector aws-role-arn=XX state=XX kind=XX etag=XX
+
+ aws-role-arn: The Aws Role Arn (with CloudTrailReadOnly policy) that is used to access the Aws account.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --mcas-data-connector
+ short-summary: "Represents MCAS (Microsoft Cloud App Security) data connector."
+ long-summary: |
+ Usage: --mcas-data-connector tenant-id=XX state-data-types-alerts-state=XX state-data-types-discovery-logs-\
+state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state-data-types-alerts-state: Describe whether this data type connection is enabled or not.
+ state-data-types-discovery-logs-state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --mdatp-data-connector
+ short-summary: "Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector."
+ long-summary: |
+ Usage: --mdatp-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --office-data-connector
+ short-summary: "Represents office data connector."
+ long-summary: |
+ Usage: --office-data-connector tenant-id=XX state-data-types-share-point-state=XX \
+state-data-types-exchange-state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state-data-types-share-point-state: Describe whether this data type connection is enabled or not.
+ state-data-types-exchange-state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+ - name: --ti-data-connector
+ short-summary: "Represents threat intelligence data connector."
+ long-summary: |
+ Usage: --ti-data-connector tenant-id=XX state=XX kind=XX etag=XX
+
+ tenant-id: The tenant id to connect to, and get the data from.
+ state: Describe whether this data type connection is enabled or not.
+ kind: Required. The data connector kind
+ etag: Etag of the azure resource
+"""
+
+helps['sentinel data-connector delete'] = """
+ type: command
+ short-summary: "Delete the data connector."
+ examples:
+ - name: Delete an Office365 data connector.
+ text: |-
+ az sentinel data-connector delete --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident'] = """
+ type: group
+ short-summary: sentinel incident
+"""
+
+helps['sentinel incident list'] = """
+ type: command
+ short-summary: "Gets all incidents."
+ examples:
+ - name: Get all incidents.
+ text: |-
+ az sentinel incident list --orderby "properties/createdTimeUtc desc" --top 1 --resource-group "myRg" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident show'] = """
+ type: command
+ short-summary: "Gets an incident."
+ examples:
+ - name: Get an incident.
+ text: |-
+ az sentinel incident show --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident create'] = """
+ type: command
+ short-summary: "Create the incident."
+ parameters:
+ - name: --labels
+ short-summary: "List of labels relevant to this incident"
+ long-summary: |
+ Usage: --labels label-name=XX
+
+ label-name: Required. The name of the label
+
+ Multiple actions can be specified by using more than one --labels argument.
+ - name: --owner
+ short-summary: "Describes a user that the incident is assigned to"
+ long-summary: |
+ Usage: --owner email=XX assigned-to=XX object-id=XX user-principal-name=XX
+
+ email: The email of the user the incident is assigned to.
+ assigned-to: The name of the user the incident is assigned to.
+ object-id: The object id of the user the incident is assigned to.
+ user-principal-name: The user principal name of the user the incident is assigned to.
+ examples:
+ - name: Creates or updates an incident.
+ text: |-
+ az sentinel incident create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --description "This is \
+a demo incident" --classification "FalsePositive" --classification-comment "Not a malicious activity" \
+--classification-reason "IncorrectAlertLogic" --first-activity-time-utc "2019-01-01T13:00:30Z" \
+--last-activity-time-utc "2019-01-01T13:05:30Z" --owner object-id="2046feea-040d-4a46-9e2b-91c2941bfa70" --severity \
+"High" --status "Closed" --title "My incident" --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group \
+"myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident update'] = """
+ type: command
+ short-summary: "Update the incident."
+ parameters:
+ - name: --labels
+ short-summary: "List of labels relevant to this incident"
+ long-summary: |
+ Usage: --labels label-name=XX
+
+ label-name: Required. The name of the label
+
+ Multiple actions can be specified by using more than one --labels argument.
+ - name: --owner
+ short-summary: "Describes a user that the incident is assigned to"
+ long-summary: |
+ Usage: --owner email=XX assigned-to=XX object-id=XX user-principal-name=XX
+
+ email: The email of the user the incident is assigned to.
+ assigned-to: The name of the user the incident is assigned to.
+ object-id: The object id of the user the incident is assigned to.
+ user-principal-name: The user principal name of the user the incident is assigned to.
+"""
+
+helps['sentinel incident delete'] = """
+ type: command
+ short-summary: "Delete the incident."
+ examples:
+ - name: Delete an incident.
+ text: |-
+ az sentinel incident delete --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group \
+"myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident-comment'] = """
+ type: group
+ short-summary: sentinel incident-comment
+"""
+
+helps['sentinel incident-comment list'] = """
+ type: command
+ short-summary: "Gets all incident comments."
+ examples:
+ - name: Get all incident comments.
+ text: |-
+ az sentinel incident-comment list --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group \
+"myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident-comment show'] = """
+ type: command
+ short-summary: "Gets an incident comment."
+ examples:
+ - name: Get an incident comment.
+ text: |-
+ az sentinel incident-comment show --incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" \
+--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+"""
+
+helps['sentinel incident-comment create'] = """
+ type: command
+ short-summary: "Creates the incident comment."
+ examples:
+ - name: Creates an incident comment.
+ text: |-
+ az sentinel incident-comment create --message "Some message" --incident-comment-id \
+"4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+"""
diff --git a/src/securityinsight/azext_sentinel/generated/_params.py b/src/securityinsight/azext_sentinel/generated/_params.py
new file mode 100644
index 00000000000..1d0fd616a6f
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/_params.py
@@ -0,0 +1,293 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=too-many-lines
+# pylint: disable=too-many-statements
+
+from azure.cli.core.commands.parameters import (
+ get_enum_type,
+ resource_group_name_type
+)
+from azext_sentinel.action import (
+ AddFusionAlertRule,
+ AddMicrosoftSecurityIncidentCreationAlertRule,
+ AddScheduledAlertRule,
+ AddIncidentInfo,
+ AddAadDataConnector,
+ AddAatpDataConnector,
+ AddAscDataConnector,
+ AddAwsCloudTrailDataConnector,
+ AddMcasDataConnector,
+ AddMdatpDataConnector,
+ AddOfficeDataConnector,
+ AddTiDataConnector,
+ AddLabels,
+ AddOwner
+)
+
+
+def load_arguments(self, _):
+
+ with self.argument_context('sentinel alert-rule list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+
+ with self.argument_context('sentinel alert-rule show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('rule_id', type=str, help='Alert rule ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel alert-rule create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('rule_id', type=str, help='Alert rule ID')
+ c.argument('action_id', type=str, help='Action ID')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('logic_app_resource_id', type=str, help='Logic App Resource Id, /subscriptions/{my-subscription}/res'
+ 'ourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-workflow-id}.')
+ c.argument('trigger_uri', type=str, help='Logic App Callback URL for this specific workflow.')
+ c.argument('fusion_alert_rule', action=AddFusionAlertRule, nargs='*', help='Represents Fusion alert rule.',
+ arg_group='AlertRule')
+ c.argument('microsoft_security_incident_creation_alert_rule',
+ action=AddMicrosoftSecurityIncidentCreationAlertRule, nargs='*', help='Represents '
+ 'MicrosoftSecurityIncidentCreation rule.', arg_group='AlertRule')
+ c.argument('scheduled_alert_rule', action=AddScheduledAlertRule, nargs='*', help='Represents scheduled alert '
+ 'rule.', arg_group='AlertRule')
+
+ with self.argument_context('sentinel alert-rule update') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('rule_id', type=str, help='Alert rule ID', id_part='child_name_1')
+ c.argument('fusion_alert_rule', action=AddFusionAlertRule, nargs='*', help='Represents Fusion alert rule.',
+ arg_group='AlertRule')
+ c.argument('microsoft_security_incident_creation_alert_rule',
+ action=AddMicrosoftSecurityIncidentCreationAlertRule, nargs='*', help='Represents '
+ 'MicrosoftSecurityIncidentCreation rule.', arg_group='AlertRule')
+ c.argument('scheduled_alert_rule', action=AddScheduledAlertRule, nargs='*', help='Represents scheduled alert '
+ 'rule.', arg_group='AlertRule')
+
+ with self.argument_context('sentinel alert-rule delete') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('rule_id', type=str, help='Alert rule ID', id_part='child_name_1')
+ c.argument('action_id', type=str, help='Action ID', id_part='child_name_2')
+
+ with self.argument_context('sentinel alert-rule get-action') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('rule_id', type=str, help='Alert rule ID', id_part='child_name_1')
+ c.argument('action_id', type=str, help='Action ID', id_part='child_name_2')
+
+ with self.argument_context('sentinel action list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('rule_id', type=str, help='Alert rule ID')
+
+ with self.argument_context('sentinel alert-rule-template list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+
+ with self.argument_context('sentinel alert-rule-template show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('alert_rule_template_id', type=str, help='Alert rule template ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel bookmark list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+
+ with self.argument_context('sentinel bookmark show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('bookmark_id', type=str, help='Bookmark ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel bookmark create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('bookmark_id', type=str, help='Bookmark ID')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('created', help='The time the bookmark was created')
+ c.argument('display_name', type=str, help='The display name of the bookmark')
+ c.argument('labels', nargs='*', help='List of labels relevant to this bookmark')
+ c.argument('notes', type=str, help='The notes of the bookmark')
+ c.argument('query', type=str, help='The query of the bookmark.')
+ c.argument('query_result', type=str, help='The query result of the bookmark.')
+ c.argument('updated', help='The last time the bookmark was updated')
+ c.argument('incident_info', action=AddIncidentInfo, nargs='*', help='Describes an incident that relates to '
+ 'bookmark')
+ c.argument('updated_by_object_id', help='The object id of the user.')
+
+ with self.argument_context('sentinel bookmark update') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('bookmark_id', type=str, help='Bookmark ID', id_part='child_name_1')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('created', help='The time the bookmark was created')
+ c.argument('display_name', type=str, help='The display name of the bookmark')
+ c.argument('labels', nargs='*', help='List of labels relevant to this bookmark')
+ c.argument('notes', type=str, help='The notes of the bookmark')
+ c.argument('query', type=str, help='The query of the bookmark.')
+ c.argument('query_result', type=str, help='The query result of the bookmark.')
+ c.argument('updated', help='The last time the bookmark was updated')
+ c.argument('incident_info', action=AddIncidentInfo, nargs='*', help='Describes an incident that relates to '
+ 'bookmark')
+ c.argument('updated_by_object_id', help='The object id of the user.')
+
+ with self.argument_context('sentinel bookmark delete') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('bookmark_id', type=str, help='Bookmark ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel data-connector list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+
+ with self.argument_context('sentinel data-connector show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('data_connector_id', type=str, help='Connector ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel data-connector create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('data_connector_id', type=str, help='Connector ID')
+ c.argument('aad_data_connector', action=AddAadDataConnector, nargs='*', help='Represents AAD (Azure Active '
+ 'Directory) data connector.', arg_group='DataConnector')
+ c.argument('aatp_data_connector', action=AddAatpDataConnector, nargs='*', help='Represents AATP (Azure '
+ 'Advanced Threat Protection) data connector.', arg_group='DataConnector')
+ c.argument('asc_data_connector', action=AddAscDataConnector, nargs='*', help='Represents ASC (Azure Security '
+ 'Center) data connector.', arg_group='DataConnector')
+ c.argument('aws_cloud_trail_data_connector', action=AddAwsCloudTrailDataConnector, nargs='*', help='Represents '
+ 'Amazon Web Services CloudTrail data connector.', arg_group='DataConnector')
+ c.argument('mcas_data_connector', action=AddMcasDataConnector, nargs='*', help='Represents MCAS (Microsoft '
+ 'Cloud App Security) data connector.', arg_group='DataConnector')
+ c.argument('mdatp_data_connector', action=AddMdatpDataConnector, nargs='*', help='Represents MDATP (Microsoft '
+ 'Defender Advanced Threat Protection) data connector.', arg_group='DataConnector')
+ c.argument('office_data_connector', action=AddOfficeDataConnector, nargs='*', help='Represents office data '
+ 'connector.', arg_group='DataConnector')
+ c.argument('ti_data_connector', action=AddTiDataConnector, nargs='*', help='Represents threat intelligence '
+ 'data connector.', arg_group='DataConnector')
+
+ with self.argument_context('sentinel data-connector update') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('data_connector_id', type=str, help='Connector ID', id_part='child_name_1')
+ c.argument('aad_data_connector', action=AddAadDataConnector, nargs='*', help='Represents AAD (Azure Active '
+ 'Directory) data connector.', arg_group='DataConnector')
+ c.argument('aatp_data_connector', action=AddAatpDataConnector, nargs='*', help='Represents AATP (Azure '
+ 'Advanced Threat Protection) data connector.', arg_group='DataConnector')
+ c.argument('asc_data_connector', action=AddAscDataConnector, nargs='*', help='Represents ASC (Azure Security '
+ 'Center) data connector.', arg_group='DataConnector')
+ c.argument('aws_cloud_trail_data_connector', action=AddAwsCloudTrailDataConnector, nargs='*', help='Represents '
+ 'Amazon Web Services CloudTrail data connector.', arg_group='DataConnector')
+ c.argument('mcas_data_connector', action=AddMcasDataConnector, nargs='*', help='Represents MCAS (Microsoft '
+ 'Cloud App Security) data connector.', arg_group='DataConnector')
+ c.argument('mdatp_data_connector', action=AddMdatpDataConnector, nargs='*', help='Represents MDATP (Microsoft '
+ 'Defender Advanced Threat Protection) data connector.', arg_group='DataConnector')
+ c.argument('office_data_connector', action=AddOfficeDataConnector, nargs='*', help='Represents office data '
+ 'connector.', arg_group='DataConnector')
+ c.argument('ti_data_connector', action=AddTiDataConnector, nargs='*', help='Represents threat intelligence '
+ 'data connector.', arg_group='DataConnector')
+
+ with self.argument_context('sentinel data-connector delete') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('data_connector_id', type=str, help='Connector ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel incident list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('filter_', options_list=['--filter'], type=str, help='Filters the results, based on a Boolean '
+ 'condition. Optional.')
+ c.argument('orderby', type=str, help='Sorts the results. Optional.')
+ c.argument('top', type=int, help='Returns only the first n results. Optional.')
+ c.argument('skip_token', type=str, help='Skiptoken is only used if a previous operation returned a partial '
+ 'result. If a previous response contains a nextLink element, the value of the nextLink element will '
+ 'include a skiptoken parameter that specifies a starting point to use for subsequent calls. '
+ 'Optional.')
+
+ with self.argument_context('sentinel incident show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('incident_id', type=str, help='Incident ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel incident create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('incident_id', type=str, help='Incident ID')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('classification', arg_type=get_enum_type(['Undetermined', 'TruePositive', 'BenignPositive', ''
+ 'FalsePositive']), help='The reason the incident was '
+ 'closed')
+ c.argument('classification_comment', type=str, help='Describes the reason the incident was closed')
+ c.argument('classification_reason', arg_type=get_enum_type(['SuspiciousActivity', 'SuspiciousButExpected', ''
+ 'IncorrectAlertLogic', 'InaccurateData']), help=''
+ 'The classification reason the incident was closed with')
+ c.argument('description', type=str, help='The description of the incident')
+ c.argument('first_activity_time_utc', help='The time of the first activity in the incident')
+ c.argument('labels', action=AddLabels, nargs='*', help='List of labels relevant to this incident')
+ c.argument('last_activity_time_utc', help='The time of the last activity in the incident')
+ c.argument('owner', action=AddOwner, nargs='*', help='Describes a user that the incident is assigned to')
+ c.argument('severity', arg_type=get_enum_type(['High', 'Medium', 'Low', 'Informational']), help='The severity '
+ 'of the incident')
+ c.argument('status', arg_type=get_enum_type(['New', 'Active', 'Closed']), help='The status of the incident')
+ c.argument('title', type=str, help='The title of the incident')
+
+ with self.argument_context('sentinel incident update') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('incident_id', type=str, help='Incident ID', id_part='child_name_1')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('classification', arg_type=get_enum_type(['Undetermined', 'TruePositive', 'BenignPositive', ''
+ 'FalsePositive']), help='The reason the incident was '
+ 'closed')
+ c.argument('classification_comment', type=str, help='Describes the reason the incident was closed')
+ c.argument('classification_reason', arg_type=get_enum_type(['SuspiciousActivity', 'SuspiciousButExpected', ''
+ 'IncorrectAlertLogic', 'InaccurateData']), help=''
+ 'The classification reason the incident was closed with')
+ c.argument('description', type=str, help='The description of the incident')
+ c.argument('first_activity_time_utc', help='The time of the first activity in the incident')
+ c.argument('labels', action=AddLabels, nargs='*', help='List of labels relevant to this incident')
+ c.argument('last_activity_time_utc', help='The time of the last activity in the incident')
+ c.argument('owner', action=AddOwner, nargs='*', help='Describes a user that the incident is assigned to')
+ c.argument('severity', arg_type=get_enum_type(['High', 'Medium', 'Low', 'Informational']), help='The severity '
+ 'of the incident')
+ c.argument('status', arg_type=get_enum_type(['New', 'Active', 'Closed']), help='The status of the incident')
+ c.argument('title', type=str, help='The title of the incident')
+
+ with self.argument_context('sentinel incident delete') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('incident_id', type=str, help='Incident ID', id_part='child_name_1')
+
+ with self.argument_context('sentinel incident-comment list') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('incident_id', type=str, help='Incident ID')
+ c.argument('filter_', options_list=['--filter'], type=str, help='Filters the results, based on a Boolean '
+ 'condition. Optional.')
+ c.argument('orderby', type=str, help='Sorts the results. Optional.')
+ c.argument('top', type=int, help='Returns only the first n results. Optional.')
+ c.argument('skip_token', type=str, help='Skiptoken is only used if a previous operation returned a partial '
+ 'result. If a previous response contains a nextLink element, the value of the nextLink element will '
+ 'include a skiptoken parameter that specifies a starting point to use for subsequent calls. '
+ 'Optional.')
+
+ with self.argument_context('sentinel incident-comment show') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('incident_id', type=str, help='Incident ID', id_part='child_name_1')
+ c.argument('incident_comment_id', type=str, help='Incident comment ID', id_part='child_name_2')
+
+ with self.argument_context('sentinel incident-comment create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('incident_id', type=str, help='Incident ID')
+ c.argument('incident_comment_id', type=str, help='Incident comment ID')
+ c.argument('message', type=str, help='The comment message')
diff --git a/src/securityinsight/azext_sentinel/generated/_validators.py b/src/securityinsight/azext_sentinel/generated/_validators.py
new file mode 100644
index 00000000000..b33a44c1ebf
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/_validators.py
@@ -0,0 +1,9 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
diff --git a/src/securityinsight/azext_sentinel/generated/action.py b/src/securityinsight/azext_sentinel/generated/action.py
new file mode 100644
index 00000000000..640e939dbf8
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/action.py
@@ -0,0 +1,427 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=protected-access
+
+import argparse
+from collections import defaultdict
+from knack.util import CLIError
+
+
+class AddFusionAlertRule(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.fusion_alert_rule = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'alert-rule-template-name':
+ d['alert_rule_template_name'] = v[0]
+ elif kl == 'enabled':
+ d['enabled'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'Fusion'
+ return d
+
+
+class AddMicrosoftSecurityIncidentCreationAlertRule(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.microsoft_security_incident_creation_alert_rule = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'display-names-filter':
+ d['display_names_filter'] = v
+ elif kl == 'display-names-exclude-filter':
+ d['display_names_exclude_filter'] = v
+ elif kl == 'product-filter':
+ d['product_filter'] = v[0]
+ elif kl == 'severities-filter':
+ d['severities_filter'] = v
+ elif kl == 'alert-rule-template-name':
+ d['alert_rule_template_name'] = v[0]
+ elif kl == 'description':
+ d['description'] = v[0]
+ elif kl == 'display-name':
+ d['display_name'] = v[0]
+ elif kl == 'enabled':
+ d['enabled'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'MicrosoftSecurityIncidentCreation'
+ return d
+
+
+class AddScheduledAlertRule(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.scheduled_alert_rule = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'query':
+ d['query'] = v[0]
+ elif kl == 'query-frequency':
+ d['query_frequency'] = v[0]
+ elif kl == 'query-period':
+ d['query_period'] = v[0]
+ elif kl == 'severity':
+ d['severity'] = v[0]
+ elif kl == 'trigger-operator':
+ d['trigger_operator'] = v[0]
+ elif kl == 'trigger-threshold':
+ d['trigger_threshold'] = v[0]
+ elif kl == 'alert-rule-template-name':
+ d['alert_rule_template_name'] = v[0]
+ elif kl == 'description':
+ d['description'] = v[0]
+ elif kl == 'display-name':
+ d['display_name'] = v[0]
+ elif kl == 'enabled':
+ d['enabled'] = v[0]
+ elif kl == 'suppression-duration':
+ d['suppression_duration'] = v[0]
+ elif kl == 'suppression-enabled':
+ d['suppression_enabled'] = v[0]
+ elif kl == 'tactics':
+ d['tactics'] = v
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'Scheduled'
+ return d
+
+
+class AddIncidentInfo(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.incident_info = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'incident-id':
+ d['incident_id'] = v[0]
+ elif kl == 'severity':
+ d['severity'] = v[0]
+ elif kl == 'title':
+ d['title'] = v[0]
+ elif kl == 'relation-name':
+ d['relation_name'] = v[0]
+ return d
+
+
+class AddAadDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.aad_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'AzureActiveDirectory'
+ return d
+
+
+class AddAatpDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.aatp_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'AzureAdvancedThreatProtection'
+ return d
+
+
+class AddAscDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.asc_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'subscription-id':
+ d['subscription_id'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'AzureSecurityCenter'
+ return d
+
+
+class AddAwsCloudTrailDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.aws_cloud_trail_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'aws-role-arn':
+ d['aws_role_arn'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'AmazonWebServicesCloudTrail'
+ return d
+
+
+class AddMcasDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.mcas_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state-data-types-alerts-state':
+ d['state_data_types_alerts_state'] = v[0]
+ elif kl == 'state-data-types-discovery-logs-state':
+ d['state_data_types_discovery_logs_state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'MicrosoftCloudAppSecurity'
+ return d
+
+
+class AddMdatpDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.mdatp_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'MicrosoftDefenderAdvancedThreatProtection'
+ return d
+
+
+class AddOfficeDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.office_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state-data-types-share-point-state':
+ d['state_data_types_share_point_state'] = v[0]
+ elif kl == 'state-data-types-exchange-state':
+ d['state_data_types_exchange_state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'Office365'
+ return d
+
+
+class AddTiDataConnector(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.ti_data_connector = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'tenant-id':
+ d['tenant_id'] = v[0]
+ elif kl == 'state':
+ d['state'] = v[0]
+ elif kl == 'etag':
+ d['etag'] = v[0]
+ d['kind'] = 'ThreatIntelligence'
+ return d
+
+
+class AddLabels(argparse._AppendAction):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ super(AddLabels, self).__call__(parser, namespace, action, option_string)
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'label-name':
+ d['label_name'] = v[0]
+ return d
+
+
+class AddOwner(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ action = self.get_action(values, option_string)
+ namespace.owner = action
+
+ def get_action(self, values, option_string): # pylint: disable=no-self-use
+ try:
+ properties = defaultdict(list)
+ for (k, v) in (x.split('=', 1) for x in values):
+ properties[k].append(v)
+ properties = dict(properties)
+ except ValueError:
+ raise CLIError('usage error: {} [KEY=VALUE ...]'.format(option_string))
+ d = {}
+ for k in properties:
+ kl = k.lower()
+ v = properties[k]
+ if kl == 'email':
+ d['email'] = v[0]
+ elif kl == 'assigned-to':
+ d['assigned_to'] = v[0]
+ elif kl == 'object-id':
+ d['object_id'] = v[0]
+ elif kl == 'user-principal-name':
+ d['user_principal_name'] = v[0]
+ return d
diff --git a/src/securityinsight/azext_sentinel/generated/commands.py b/src/securityinsight/azext_sentinel/generated/commands.py
new file mode 100644
index 00000000000..f8dac3f83d6
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/commands.py
@@ -0,0 +1,100 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=too-many-statements
+# pylint: disable=too-many-locals
+
+from azure.cli.core.commands import CliCommandType
+
+
+def load_command_table(self, _):
+
+ from azext_sentinel.generated._client_factory import cf_alert_rule
+ sentinel_alert_rule = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._alert_rule_operations#AlertRuleOperat'
+ 'ions.{}',
+ client_factory=cf_alert_rule)
+ with self.command_group('sentinel alert-rule', sentinel_alert_rule, client_factory=cf_alert_rule,
+ is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_alert_rule_list')
+ g.custom_show_command('show', 'sentinel_alert_rule_show')
+ g.custom_command('create', 'sentinel_alert_rule_create')
+ g.generic_update_command('update', setter_arg_name='alert_rule',
+ custom_func_name='sentinel_alert_rule_update')
+ g.custom_command('delete', 'sentinel_alert_rule_delete', confirmation=True)
+ g.custom_command('get-action', 'sentinel_alert_rule_get_action')
+
+ from azext_sentinel.generated._client_factory import cf_action
+ sentinel_action = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._action_operations#ActionOperations.{}'
+ '',
+ client_factory=cf_action)
+ with self.command_group('sentinel action', sentinel_action, client_factory=cf_action, is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_action_list')
+
+ from azext_sentinel.generated._client_factory import cf_alert_rule_template
+ sentinel_alert_rule_template = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._alert_rule_template_operations#AlertR'
+ 'uleTemplateOperations.{}',
+ client_factory=cf_alert_rule_template)
+ with self.command_group('sentinel alert-rule-template', sentinel_alert_rule_template,
+ client_factory=cf_alert_rule_template, is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_alert_rule_template_list')
+ g.custom_show_command('show', 'sentinel_alert_rule_template_show')
+
+ from azext_sentinel.generated._client_factory import cf_bookmark
+ sentinel_bookmark = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._bookmark_operations#BookmarkOperation'
+ 's.{}',
+ client_factory=cf_bookmark)
+ with self.command_group('sentinel bookmark', sentinel_bookmark, client_factory=cf_bookmark,
+ is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_bookmark_list')
+ g.custom_show_command('show', 'sentinel_bookmark_show')
+ g.custom_command('create', 'sentinel_bookmark_create')
+ g.custom_command('update', 'sentinel_bookmark_update')
+ g.custom_command('delete', 'sentinel_bookmark_delete', confirmation=True)
+
+ from azext_sentinel.generated._client_factory import cf_data_connector
+ sentinel_data_connector = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._data_connector_operations#DataConnect'
+ 'orOperations.{}',
+ client_factory=cf_data_connector)
+ with self.command_group('sentinel data-connector', sentinel_data_connector, client_factory=cf_data_connector,
+ is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_data_connector_list')
+ g.custom_show_command('show', 'sentinel_data_connector_show')
+ g.custom_command('create', 'sentinel_data_connector_create')
+ g.generic_update_command('update', setter_arg_name='data_connector', custom_func_name=''
+ 'sentinel_data_connector_update')
+ g.custom_command('delete', 'sentinel_data_connector_delete', confirmation=True)
+
+ from azext_sentinel.generated._client_factory import cf_incident
+ sentinel_incident = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._incident_operations#IncidentOperation'
+ 's.{}',
+ client_factory=cf_incident)
+ with self.command_group('sentinel incident', sentinel_incident, client_factory=cf_incident,
+ is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_incident_list')
+ g.custom_show_command('show', 'sentinel_incident_show')
+ g.custom_command('create', 'sentinel_incident_create')
+ g.custom_command('update', 'sentinel_incident_update')
+ g.custom_command('delete', 'sentinel_incident_delete', confirmation=True)
+
+ from azext_sentinel.generated._client_factory import cf_incident_comment
+ sentinel_incident_comment = CliCommandType(
+ operations_tmpl='azext_sentinel.vendored_sdks.securityinsight.operations._incident_comment_operations#IncidentC'
+ 'ommentOperations.{}',
+ client_factory=cf_incident_comment)
+ with self.command_group('sentinel incident-comment', sentinel_incident_comment, client_factory=cf_incident_comment,
+ is_experimental=True) as g:
+ g.custom_command('list', 'sentinel_incident_comment_list')
+ g.custom_show_command('show', 'sentinel_incident_comment_show')
+ g.custom_command('create', 'sentinel_incident_comment_create')
diff --git a/src/securityinsight/azext_sentinel/generated/custom.py b/src/securityinsight/azext_sentinel/generated/custom.py
new file mode 100644
index 00000000000..aecb82f2db6
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/generated/custom.py
@@ -0,0 +1,433 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=too-many-lines
+# pylint: disable=unused-argument
+
+from knack.util import CLIError
+
+
+def sentinel_alert_rule_list(client,
+ resource_group_name,
+ workspace_name):
+ return client.list(resource_group_name=resource_group_name,
+ workspace_name=workspace_name)
+
+
+def sentinel_alert_rule_show(client,
+ resource_group_name,
+ workspace_name,
+ rule_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id)
+
+
+def sentinel_alert_rule_create(client,
+ resource_group_name,
+ workspace_name,
+ rule_id,
+ action_id=None,
+ etag=None,
+ logic_app_resource_id=None,
+ trigger_uri=None,
+ fusion_alert_rule=None,
+ microsoft_security_incident_creation_alert_rule=None,
+ scheduled_alert_rule=None):
+ all_alert_rule = []
+ if fusion_alert_rule is not None:
+ all_alert_rule.append(fusion_alert_rule)
+ if microsoft_security_incident_creation_alert_rule is not None:
+ all_alert_rule.append(microsoft_security_incident_creation_alert_rule)
+ if scheduled_alert_rule is not None:
+ all_alert_rule.append(scheduled_alert_rule)
+ if len(all_alert_rule) > 1:
+ raise CLIError('at most one of fusion_alert_rule, microsoft_security_incident_creation_alert_rule, '
+ 'scheduled_alert_rule is needed for alert_rule!')
+ alert_rule = all_alert_rule[0] if len(all_alert_rule) == 1 else None
+ if resource_group_name and workspace_name is not None and rule_id is not None and action_id is not None:
+ return client.create_or_update_action(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id,
+ action_id=action_id,
+ etag=etag,
+ logic_app_resource_id=logic_app_resource_id,
+ trigger_uri=trigger_uri)
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id,
+ alert_rule=alert_rule)
+
+
+def sentinel_alert_rule_update(instance,
+ resource_group_name,
+ workspace_name,
+ rule_id,
+ fusion_alert_rule=None,
+ microsoft_security_incident_creation_alert_rule=None,
+ scheduled_alert_rule=None):
+ return instance
+
+
+def sentinel_alert_rule_delete(client,
+ resource_group_name,
+ workspace_name,
+ rule_id,
+ action_id=None):
+ if resource_group_name and workspace_name is not None and rule_id is not None and action_id is not None:
+ return client.delete_action(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id,
+ action_id=action_id)
+ return client.delete(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id)
+
+
+def sentinel_alert_rule_get_action(client,
+ resource_group_name,
+ workspace_name,
+ rule_id,
+ action_id):
+ return client.get_action(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id,
+ action_id=action_id)
+
+
+def sentinel_action_list(client,
+ resource_group_name,
+ workspace_name,
+ rule_id):
+ return client.list_by_alert_rule(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ rule_id=rule_id)
+
+
+def sentinel_alert_rule_template_list(client,
+ resource_group_name,
+ workspace_name):
+ return client.list(resource_group_name=resource_group_name,
+ workspace_name=workspace_name)
+
+
+def sentinel_alert_rule_template_show(client,
+ resource_group_name,
+ workspace_name,
+ alert_rule_template_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ alert_rule_template_id=alert_rule_template_id)
+
+
+def sentinel_bookmark_list(client,
+ resource_group_name,
+ workspace_name):
+ return client.list(resource_group_name=resource_group_name,
+ workspace_name=workspace_name)
+
+
+def sentinel_bookmark_show(client,
+ resource_group_name,
+ workspace_name,
+ bookmark_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ bookmark_id=bookmark_id)
+
+
+def sentinel_bookmark_create(client,
+ resource_group_name,
+ workspace_name,
+ bookmark_id,
+ etag=None,
+ created=None,
+ display_name=None,
+ labels=None,
+ notes=None,
+ query=None,
+ query_result=None,
+ updated=None,
+ incident_info=None,
+ updated_by_object_id=None):
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ bookmark_id=bookmark_id,
+ etag=etag,
+ created=created,
+ display_name=display_name,
+ labels=labels,
+ notes=notes,
+ query=query,
+ query_result=query_result,
+ updated=updated,
+ incident_info=incident_info,
+ object_id=updated_by_object_id)
+
+
+def sentinel_bookmark_update(client,
+ resource_group_name,
+ workspace_name,
+ bookmark_id,
+ etag=None,
+ created=None,
+ display_name=None,
+ labels=None,
+ notes=None,
+ query=None,
+ query_result=None,
+ updated=None,
+ incident_info=None,
+ updated_by_object_id=None):
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ bookmark_id=bookmark_id,
+ etag=etag,
+ created=created,
+ display_name=display_name,
+ labels=labels,
+ notes=notes,
+ query=query,
+ query_result=query_result,
+ updated=updated,
+ incident_info=incident_info,
+ object_id=updated_by_object_id)
+
+
+def sentinel_bookmark_delete(client,
+ resource_group_name,
+ workspace_name,
+ bookmark_id):
+ return client.delete(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ bookmark_id=bookmark_id)
+
+
+def sentinel_data_connector_list(client,
+ resource_group_name,
+ workspace_name):
+ return client.list(resource_group_name=resource_group_name,
+ workspace_name=workspace_name)
+
+
+def sentinel_data_connector_show(client,
+ resource_group_name,
+ workspace_name,
+ data_connector_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ data_connector_id=data_connector_id)
+
+
+def sentinel_data_connector_create(client,
+ resource_group_name,
+ workspace_name,
+ data_connector_id,
+ aad_data_connector=None,
+ aatp_data_connector=None,
+ asc_data_connector=None,
+ aws_cloud_trail_data_connector=None,
+ mcas_data_connector=None,
+ mdatp_data_connector=None,
+ office_data_connector=None,
+ ti_data_connector=None):
+ all_data_connector = []
+ if aad_data_connector is not None:
+ all_data_connector.append(aad_data_connector)
+ if aatp_data_connector is not None:
+ all_data_connector.append(aatp_data_connector)
+ if asc_data_connector is not None:
+ all_data_connector.append(asc_data_connector)
+ if aws_cloud_trail_data_connector is not None:
+ all_data_connector.append(aws_cloud_trail_data_connector)
+ if mcas_data_connector is not None:
+ all_data_connector.append(mcas_data_connector)
+ if mdatp_data_connector is not None:
+ all_data_connector.append(mdatp_data_connector)
+ if office_data_connector is not None:
+ all_data_connector.append(office_data_connector)
+ if ti_data_connector is not None:
+ all_data_connector.append(ti_data_connector)
+ if len(all_data_connector) > 1:
+ raise CLIError('at most one of aad_data_connector, aatp_data_connector, asc_data_connector, '
+ 'aws_cloud_trail_data_connector, mcas_data_connector, mdatp_data_connector, '
+ 'office_data_connector, ti_data_connector is needed for data_connector!')
+ if len(all_data_connector) != 1:
+ raise CLIError('data_connector is required. but none of aad_data_connector, aatp_data_connector, '
+ 'asc_data_connector, aws_cloud_trail_data_connector, mcas_data_connector, mdatp_data_connector, '
+ 'office_data_connector, ti_data_connector is provided!')
+ data_connector = all_data_connector[0] if len(all_data_connector) == 1 else None
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ data_connector_id=data_connector_id,
+ data_connector=data_connector)
+
+
+def sentinel_data_connector_update(instance,
+ resource_group_name,
+ workspace_name,
+ data_connector_id,
+ aad_data_connector=None,
+ aatp_data_connector=None,
+ asc_data_connector=None,
+ aws_cloud_trail_data_connector=None,
+ mcas_data_connector=None,
+ mdatp_data_connector=None,
+ office_data_connector=None,
+ ti_data_connector=None):
+ return instance
+
+
+def sentinel_data_connector_delete(client,
+ resource_group_name,
+ workspace_name,
+ data_connector_id):
+ return client.delete(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ data_connector_id=data_connector_id)
+
+
+def sentinel_incident_list(client,
+ resource_group_name,
+ workspace_name,
+ filter_=None,
+ orderby=None,
+ top=None,
+ skip_token=None):
+ return client.list(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ filter=filter_,
+ orderby=orderby,
+ top=top,
+ skip_token=skip_token)
+
+
+def sentinel_incident_show(client,
+ resource_group_name,
+ workspace_name,
+ incident_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id)
+
+
+def sentinel_incident_create(client,
+ resource_group_name,
+ workspace_name,
+ incident_id,
+ etag=None,
+ classification=None,
+ classification_comment=None,
+ classification_reason=None,
+ description=None,
+ first_activity_time_utc=None,
+ labels=None,
+ last_activity_time_utc=None,
+ owner=None,
+ severity=None,
+ status=None,
+ title=None):
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id,
+ etag=etag,
+ classification=classification,
+ classification_comment=classification_comment,
+ classification_reason=classification_reason,
+ description=description,
+ first_activity_time_utc=first_activity_time_utc,
+ labels=labels,
+ last_activity_time_utc=last_activity_time_utc,
+ owner=owner,
+ severity=severity,
+ status=status,
+ title=title)
+
+
+def sentinel_incident_update(client,
+ resource_group_name,
+ workspace_name,
+ incident_id,
+ etag=None,
+ classification=None,
+ classification_comment=None,
+ classification_reason=None,
+ description=None,
+ first_activity_time_utc=None,
+ labels=None,
+ last_activity_time_utc=None,
+ owner=None,
+ severity=None,
+ status=None,
+ title=None):
+ return client.create_or_update(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id,
+ etag=etag,
+ classification=classification,
+ classification_comment=classification_comment,
+ classification_reason=classification_reason,
+ description=description,
+ first_activity_time_utc=first_activity_time_utc,
+ labels=labels,
+ last_activity_time_utc=last_activity_time_utc,
+ owner=owner,
+ severity=severity,
+ status=status,
+ title=title)
+
+
+def sentinel_incident_delete(client,
+ resource_group_name,
+ workspace_name,
+ incident_id):
+ return client.delete(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id)
+
+
+def sentinel_incident_comment_list(client,
+ resource_group_name,
+ workspace_name,
+ incident_id,
+ filter_=None,
+ orderby=None,
+ top=None,
+ skip_token=None):
+ return client.list_by_incident(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id,
+ filter=filter_,
+ orderby=orderby,
+ top=top,
+ skip_token=skip_token)
+
+
+def sentinel_incident_comment_show(client,
+ resource_group_name,
+ workspace_name,
+ incident_id,
+ incident_comment_id):
+ return client.get(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id,
+ incident_comment_id=incident_comment_id)
+
+
+def sentinel_incident_comment_create(client,
+ resource_group_name,
+ workspace_name,
+ incident_id,
+ incident_comment_id,
+ message=None):
+ return client.create_comment(resource_group_name=resource_group_name,
+ workspace_name=workspace_name,
+ incident_id=incident_id,
+ incident_comment_id=incident_comment_id,
+ message=message)
diff --git a/src/securityinsight/azext_sentinel/manual/__init__.py b/src/securityinsight/azext_sentinel/manual/__init__.py
new file mode 100644
index 00000000000..c9cfdc73e77
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/manual/__init__.py
@@ -0,0 +1,12 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/securityinsight/azext_sentinel/manual/_params.py b/src/securityinsight/azext_sentinel/manual/_params.py
new file mode 100644
index 00000000000..fa718718d51
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/manual/_params.py
@@ -0,0 +1,49 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+# pylint: disable=too-many-lines
+# pylint: disable=too-many-statements
+
+from azure.cli.core.commands.parameters import resource_group_name_type
+from azext_sentinel.action import AddIncidentInfo
+
+
+def load_arguments(self, _):
+
+ with self.argument_context('sentinel bookmark create') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.')
+ c.argument('bookmark_id', type=str, help='Bookmark ID')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('created', help='The time the bookmark was created')
+ c.argument('display_name', type=str, help='The display name of the bookmark')
+ c.argument('labels', nargs='*', help='List of labels relevant to this bookmark')
+ c.argument('notes', type=str, help='The notes of the bookmark')
+ c.argument('query_content', options_list=['-q'], type=str, help='The query of the bookmark.')
+ c.argument('query_result', type=str, help='The query result of the bookmark.')
+ c.argument('updated', help='The last time the bookmark was updated')
+ c.argument('incident_info', action=AddIncidentInfo, nargs='*', help='Describes an incident that relates to '
+ 'bookmark')
+ c.argument('updated_by_object_id', help='The object id of the user.')
+
+ with self.argument_context('sentinel bookmark update') as c:
+ c.argument('resource_group_name', resource_group_name_type)
+ c.argument('workspace_name', type=str, help='The name of the workspace.', id_part='name')
+ c.argument('bookmark_id', type=str, help='Bookmark ID', id_part='child_name_1')
+ c.argument('etag', type=str, help='Etag of the azure resource')
+ c.argument('created', help='The time the bookmark was created')
+ c.argument('display_name', type=str, help='The display name of the bookmark')
+ c.argument('labels', nargs='*', help='List of labels relevant to this bookmark')
+ c.argument('notes', type=str, help='The notes of the bookmark')
+ c.argument('query_content', options_list=['-q'], type=str, help='The query of the bookmark.')
+ c.argument('query_result', type=str, help='The query result of the bookmark.')
+ c.argument('updated', help='The last time the bookmark was updated')
+ c.argument('incident_info', action=AddIncidentInfo, nargs='*', help='Describes an incident that relates to '
+ 'bookmark')
+ c.argument('updated_by_object_id', help='The object id of the user.')
diff --git a/src/securityinsight/azext_sentinel/tests/__init__.py b/src/securityinsight/azext_sentinel/tests/__init__.py
new file mode 100644
index 00000000000..50e0627daff
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/tests/__init__.py
@@ -0,0 +1,114 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+import inspect
+import logging
+import os
+import sys
+import traceback
+import datetime as dt
+
+from azure.core.exceptions import AzureError
+from azure.cli.testsdk.exceptions import CliTestError, CliExecutionError, JMESPathCheckAssertionError
+
+
+logger = logging.getLogger('azure.cli.testsdk')
+logger.addHandler(logging.StreamHandler())
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
+exceptions = []
+test_map = dict()
+SUCCESSED = "successed"
+FAILED = "failed"
+
+
+def try_manual(func):
+ def import_manual_function(origin_func):
+ from importlib import import_module
+ decorated_path = inspect.getfile(origin_func)
+ module_path = __path__[0]
+ if not decorated_path.startswith(module_path):
+ raise Exception("Decorator can only be used in submodules!")
+ manual_path = os.path.join(
+ decorated_path[module_path.rfind(os.path.sep) + 1:])
+ manual_file_path, manual_file_name = os.path.split(manual_path)
+ module_name, _ = os.path.splitext(manual_file_name)
+ manual_module = "..manual." + \
+ ".".join(manual_file_path.split(os.path.sep) + [module_name, ])
+ return getattr(import_module(manual_module, package=__name__), origin_func.__name__)
+
+ def get_func_to_call():
+ func_to_call = func
+ try:
+ func_to_call = import_manual_function(func)
+ func_to_call = import_manual_function(func)
+ logger.info("Found manual override for %s(...)", func.__name__)
+ except (ImportError, AttributeError):
+ pass
+ return func_to_call
+
+ def wrapper(*args, **kwargs):
+ func_to_call = get_func_to_call()
+ logger.info("running %s()...", func.__name__)
+ try:
+ test_map[func.__name__] = dict()
+ test_map[func.__name__]["result"] = SUCCESSED
+ test_map[func.__name__]["error_message"] = ""
+ test_map[func.__name__]["error_stack"] = ""
+ test_map[func.__name__]["error_normalized"] = ""
+ test_map[func.__name__]["start_dt"] = dt.datetime.utcnow()
+ ret = func_to_call(*args, **kwargs)
+ except (AssertionError, AzureError, CliTestError, CliExecutionError, SystemExit,
+ JMESPathCheckAssertionError) as e:
+ test_map[func.__name__]["end_dt"] = dt.datetime.utcnow()
+ test_map[func.__name__]["result"] = FAILED
+ test_map[func.__name__]["error_message"] = str(e).replace("\r\n", " ").replace("\n", " ")[:500]
+ test_map[func.__name__]["error_stack"] = traceback.format_exc().replace(
+ "\r\n", " ").replace("\n", " ")[:500]
+ logger.info("--------------------------------------")
+ logger.info("step exception: %s", e)
+ logger.error("--------------------------------------")
+ logger.error("step exception in %s: %s", func.__name__, e)
+ logger.info(traceback.format_exc())
+ exceptions.append((func.__name__, sys.exc_info()))
+ else:
+ test_map[func.__name__]["end_dt"] = dt.datetime.utcnow()
+ return ret
+
+ if inspect.isclass(func):
+ return get_func_to_call()
+ return wrapper
+
+
+def calc_coverage(filename):
+ filename = filename.split(".")[0]
+ coverage_name = filename + "_coverage.md"
+ with open(coverage_name, "w") as f:
+ f.write("|Scenario|Result|ErrorMessage|ErrorStack|ErrorNormalized|StartDt|EndDt|\n")
+ total = len(test_map)
+ covered = 0
+ for k, v in test_map.items():
+ if not k.startswith("step_"):
+ total -= 1
+ continue
+ if v["result"] == SUCCESSED:
+ covered += 1
+ f.write("|{step_name}|{result}|{error_message}|{error_stack}|{error_normalized}|{start_dt}|"
+ "{end_dt}|\n".format(step_name=k, **v))
+ f.write("Coverage: {}/{}\n".format(covered, total))
+ print("Create coverage\n", file=sys.stderr)
+
+
+def raise_if():
+ if exceptions:
+ if len(exceptions) <= 1:
+ raise exceptions[0][1][1]
+ message = "{}\nFollowed with exceptions in other steps:\n".format(str(exceptions[0][1][1]))
+ message += "\n".join(["{}: {}".format(h[0], h[1][1]) for h in exceptions[1:]])
+ raise exceptions[0][1][0](message).with_traceback(exceptions[0][1][2])
diff --git a/src/securityinsight/azext_sentinel/tests/latest/__init__.py b/src/securityinsight/azext_sentinel/tests/latest/__init__.py
new file mode 100644
index 00000000000..c9cfdc73e77
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/tests/latest/__init__.py
@@ -0,0 +1,12 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/securityinsight/azext_sentinel/tests/latest/recordings/test_sentinel.yaml b/src/securityinsight/azext_sentinel/tests/latest/recordings/test_sentinel.yaml
new file mode 100644
index 00000000000..5ad10bbf566
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/tests/latest/recordings/test_sentinel.yaml
@@ -0,0 +1,5262 @@
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - monitor log-analytics workspace create
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - -g -n
+ User-Agent:
+ - python/3.8.5 (Windows-10-10.0.19041-SP0) msrest/0.6.18 msrest_azure/0.6.3
+ azure-mgmt-resource/10.2.0 Azure-SDK-For-Python AZURECLI/2.15.0
+ accept-language:
+ - en-US
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001?api-version=2020-06-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001","name":"clitest000001","type":"Microsoft.Resources/resourceGroups","location":"westus","tags":{"product":"azurecli","cause":"automation","date":"2020-11-30T05:11:21Z"},"properties":{"provisioningState":"Succeeded"}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '428'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:11:27 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: '{"location": "westus", "properties": {"sku": {"name": "PerGB2018"}, "retentionInDays":
+ 30, "workspaceCapping": {}}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - monitor log-analytics workspace create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '115'
+ Content-Type:
+ - application/json; charset=utf-8
+ ParameterSetName:
+ - -g -n
+ User-Agent:
+ - python/3.8.5 (Windows-10-10.0.19041-SP0) msrest/0.6.18 msrest_azure/0.6.3
+ azure-mgmt-loganalytics/0.7.0 Azure-SDK-For-Python AZURECLI/2.15.0
+ accept-language:
+ - en-US
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002?api-version=2020-03-01-preview
+ response:
+ body:
+ string: "{\r\n \"properties\": {\r\n \"source\": \"Azure\",\r\n \"customerId\":
+ \"09dfc1f0-16e6-4a13-a83d-ec40b7a1679b\",\r\n \"provisioningState\": \"Creating\",\r\n
+ \ \"sku\": {\r\n \"name\": \"pergb2018\",\r\n \"maxCapacityReservationLevel\":
+ 3000,\r\n \"lastSkuUpdate\": \"Mon, 30 Nov 2020 05:11:36 GMT\"\r\n },\r\n
+ \ \"retentionInDays\": 30,\r\n \"features\": {\r\n \"legacy\": 0,\r\n
+ \ \"searchVersion\": 1,\r\n \"enableLogAccessUsingOnlyResourcePermissions\":
+ true\r\n },\r\n \"workspaceCapping\": {\r\n \"dailyQuotaGb\": -1.0,\r\n
+ \ \"quotaNextResetTime\": \"Mon, 30 Nov 2020 07:00:00 GMT\",\r\n \"dataIngestionStatus\":
+ \"RespectQuota\"\r\n },\r\n \"publicNetworkAccessForIngestion\": \"Enabled\",\r\n
+ \ \"publicNetworkAccessForQuery\": \"Enabled\",\r\n \"createdDate\":
+ \"Mon, 30 Nov 2020 05:11:36 GMT\",\r\n \"modifiedDate\": \"Mon, 30 Nov
+ 2020 05:11:36 GMT\"\r\n },\r\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/microsoft.operationalinsights/workspaces/cli-test-ws-000002\",\r\n
+ \ \"name\": \"cli-test-ws-000002\",\r\n \"type\": \"Microsoft.OperationalInsights/workspaces\",\r\n
+ \ \"location\": \"westus\"\r\n}"
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '1185'
+ content-type:
+ - application/json
+ date:
+ - Mon, 30 Nov 2020 05:11:37 GMT
+ pragma:
+ - no-cache
+ server:
+ - Microsoft-IIS/10.0
+ - Microsoft-IIS/10.0
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1199'
+ x-powered-by:
+ - ASP.NET
+ - ASP.NET
+ status:
+ code: 201
+ message: Created
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - monitor log-analytics workspace create
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - -g -n
+ User-Agent:
+ - python/3.8.5 (Windows-10-10.0.19041-SP0) msrest/0.6.18 msrest_azure/0.6.3
+ azure-mgmt-loganalytics/0.7.0 Azure-SDK-For-Python AZURECLI/2.15.0
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002?api-version=2020-03-01-preview
+ response:
+ body:
+ string: "{\r\n \"properties\": {\r\n \"source\": \"Azure\",\r\n \"customerId\":
+ \"09dfc1f0-16e6-4a13-a83d-ec40b7a1679b\",\r\n \"provisioningState\": \"Succeeded\",\r\n
+ \ \"sku\": {\r\n \"name\": \"pergb2018\",\r\n \"maxCapacityReservationLevel\":
+ 3000,\r\n \"lastSkuUpdate\": \"Mon, 30 Nov 2020 05:11:36 GMT\"\r\n },\r\n
+ \ \"retentionInDays\": 30,\r\n \"features\": {\r\n \"legacy\": 0,\r\n
+ \ \"searchVersion\": 1,\r\n \"enableLogAccessUsingOnlyResourcePermissions\":
+ true\r\n },\r\n \"workspaceCapping\": {\r\n \"dailyQuotaGb\": -1.0,\r\n
+ \ \"quotaNextResetTime\": \"Mon, 30 Nov 2020 07:00:00 GMT\",\r\n \"dataIngestionStatus\":
+ \"RespectQuota\"\r\n },\r\n \"publicNetworkAccessForIngestion\": \"Enabled\",\r\n
+ \ \"publicNetworkAccessForQuery\": \"Enabled\",\r\n \"createdDate\":
+ \"Mon, 30 Nov 2020 05:11:36 GMT\",\r\n \"modifiedDate\": \"Mon, 30 Nov
+ 2020 05:11:38 GMT\"\r\n },\r\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/microsoft.operationalinsights/workspaces/cli-test-ws-000002\",\r\n
+ \ \"name\": \"cli-test-ws-000002\",\r\n \"type\": \"Microsoft.OperationalInsights/workspaces\",\r\n
+ \ \"location\": \"westus\"\r\n}"
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '1186'
+ content-type:
+ - application/json
+ date:
+ - Mon, 30 Nov 2020 05:12:09 GMT
+ pragma:
+ - no-cache
+ server:
+ - Microsoft-IIS/10.0
+ - Microsoft-IIS/10.0
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-powered-by:
+ - ASP.NET
+ - ASP.NET
+ status:
+ code: 200
+ message: OK
+- request:
+ body: '{"etag": "3d00c3ca-0000-0100-0000-5d42d5010000", "kind": "Fusion", "properties":
+ {"alertRuleTemplateName": "f71aba3d-28fb-450b-b192-4e76a83015c8", "enabled":
+ true}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '164'
+ Content-Type:
+ - application/json
+ ParameterSetName:
+ - --fusion-alert-rule --resource-group --rule-id --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule","name":"myFirstFusionRule","etag":"\"8901b2c8-0000-0100-0000-5fc47f2d0000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"Fusion","properties":{"displayName":"Advanced
+ Multistage Attack Detection","description":"Using Fusion technology based
+ on machine learning, Azure Sentinel automatically detects multistage attacks
+ by identifying combinations of anomalous behaviors and suspicious activities
+ observed at various stages of the kill chain. On the basis of these discoveries,
+ Azure Sentinel generates incidents that would otherwise be very difficult
+ to catch. By design, these incidents are low-volume, high-fidelity, and high-severity,
+ which is why this detection is turned ON by default.\n\nThere are a total
+ of 70 Fusion incident types detected by Azure Sentinel.\n- 65 of these show
+ the combination of suspicious Azure Active Directory sign-in events followed
+ by anomalous Office 365 activity. Out of these 65, 30 are in public preview.
+ \n- The remaining five incident types show the combination of anomalous signals
+ from Microsoft Defender Advanced Threat Protection and from Palo Alto Networks
+ firewalls. These five types are all in public preview.\n\nTo detect these
+ multistage attacks, the following data connectors must be configured:\n- Azure
+ Active Directory Identity Protection.\n- Microsoft Cloud App Security.\n-
+ Microsoft Defender Advanced Threat Protection.\n- Palo Alto Networks.\n\nFor
+ a full list and description of each scenario that is supported for these multistage
+ attacks, go to https://aka.ms/SentinelFusion.","alertRuleTemplateName":"f71aba3d-28fb-450b-b192-4e76a83015c8","tactics":["Collection","CommandAndControl","DefenseEvasion","Discovery","Execution","Exfiltration","Impact","InitialAccess","LateralMovement","Persistence","PrivilegeEscalation"],"severity":"High","enabled":true,"lastModifiedUtc":"2020-11-30T05:12:13.9883966Z"}}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '2165'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:13 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1199'
+ status:
+ code: 201
+ message: Created
+- request:
+ body: '{"etag": "260097e0-0000-0d00-0000-5d6fa88f0000", "kind": "MicrosoftSecurityIncidentCreation",
+ "properties": {"productFilter": "Microsoft Cloud App Security", "displayName":
+ "testing displayname", "enabled": true}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '213'
+ Content-Type:
+ - application/json
+ ParameterSetName:
+ - --microsoft-security-incident-creation-alert-rule --resource-group --rule-id
+ --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/microsoftSecurityIncidentCreationRuleExample?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/microsoftSecurityIncidentCreationRuleExample","name":"microsoftSecurityIncidentCreationRuleExample","etag":"\"8901b3c8-0000-0100-0000-5fc47f300000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"MicrosoftSecurityIncidentCreation","properties":{"productFilter":"Microsoft
+ Cloud App Security","severitiesFilter":null,"displayNamesFilter":null,"displayNamesExcludeFilter":null,"displayName":"testing
+ displayname","enabled":true,"description":null,"tactics":null,"alertRuleTemplateName":null,"lastModifiedUtc":"2020-11-30T05:12:16.7234969Z"}}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '822'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:16 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1199'
+ status:
+ code: 201
+ message: Created
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --resource-group --rule-id --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule","name":"myFirstFusionRule","etag":"\"8901b2c8-0000-0100-0000-5fc47f2d0000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"Fusion","properties":{"displayName":"Advanced
+ Multistage Attack Detection","description":"Using Fusion technology based
+ on machine learning, Azure Sentinel automatically detects multistage attacks
+ by identifying combinations of anomalous behaviors and suspicious activities
+ observed at various stages of the kill chain. On the basis of these discoveries,
+ Azure Sentinel generates incidents that would otherwise be very difficult
+ to catch. By design, these incidents are low-volume, high-fidelity, and high-severity,
+ which is why this detection is turned ON by default.\n\nThere are a total
+ of 70 Fusion incident types detected by Azure Sentinel.\n- 65 of these show
+ the combination of suspicious Azure Active Directory sign-in events followed
+ by anomalous Office 365 activity. Out of these 65, 30 are in public preview.
+ \n- The remaining five incident types show the combination of anomalous signals
+ from Microsoft Defender Advanced Threat Protection and from Palo Alto Networks
+ firewalls. These five types are all in public preview.\n\nTo detect these
+ multistage attacks, the following data connectors must be configured:\n- Azure
+ Active Directory Identity Protection.\n- Microsoft Cloud App Security.\n-
+ Microsoft Defender Advanced Threat Protection.\n- Palo Alto Networks.\n\nFor
+ a full list and description of each scenario that is supported for these multistage
+ attacks, go to https://aka.ms/SentinelFusion.","alertRuleTemplateName":"f71aba3d-28fb-450b-b192-4e76a83015c8","tactics":["Collection","CommandAndControl","DefenseEvasion","Discovery","Execution","Exfiltration","Impact","InitialAccess","LateralMovement","Persistence","PrivilegeEscalation"],"severity":"High","enabled":true,"lastModifiedUtc":"2020-11-30T05:12:13.9883966Z"}}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '2165'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:18 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --resource-group --rule-id --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/microsoftSecurityIncidentCreationRuleExample?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/microsoftSecurityIncidentCreationRuleExample","name":"microsoftSecurityIncidentCreationRuleExample","etag":"\"8901b3c8-0000-0100-0000-5fc47f300000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"MicrosoftSecurityIncidentCreation","properties":{"productFilter":"Microsoft
+ Cloud App Security","severitiesFilter":null,"displayNamesFilter":null,"displayNamesExcludeFilter":null,"displayName":"testing
+ displayname","enabled":true,"description":null,"tactics":null,"alertRuleTemplateName":null,"lastModifiedUtc":"2020-11-30T05:12:16.7234969Z"}}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '822'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:20 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule list
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules?api-version=2020-01-01
+ response:
+ body:
+ string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule","name":"myFirstFusionRule","etag":"\"8901b2c8-0000-0100-0000-5fc47f2d0000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"Fusion","properties":{"displayName":"Advanced
+ Multistage Attack Detection","description":"Using Fusion technology based
+ on machine learning, Azure Sentinel automatically detects multistage attacks
+ by identifying combinations of anomalous behaviors and suspicious activities
+ observed at various stages of the kill chain. On the basis of these discoveries,
+ Azure Sentinel generates incidents that would otherwise be very difficult
+ to catch. By design, these incidents are low-volume, high-fidelity, and high-severity,
+ which is why this detection is turned ON by default.\n\nThere are a total
+ of 70 Fusion incident types detected by Azure Sentinel.\n- 65 of these show
+ the combination of suspicious Azure Active Directory sign-in events followed
+ by anomalous Office 365 activity. Out of these 65, 30 are in public preview.
+ \n- The remaining five incident types show the combination of anomalous signals
+ from Microsoft Defender Advanced Threat Protection and from Palo Alto Networks
+ firewalls. These five types are all in public preview.\n\nTo detect these
+ multistage attacks, the following data connectors must be configured:\n- Azure
+ Active Directory Identity Protection.\n- Microsoft Cloud App Security.\n-
+ Microsoft Defender Advanced Threat Protection.\n- Palo Alto Networks.\n\nFor
+ a full list and description of each scenario that is supported for these multistage
+ attacks, go to https://aka.ms/SentinelFusion.","alertRuleTemplateName":"f71aba3d-28fb-450b-b192-4e76a83015c8","tactics":["Collection","CommandAndControl","DefenseEvasion","Discovery","Execution","Exfiltration","Impact","InitialAccess","LateralMovement","Persistence","PrivilegeEscalation"],"severity":"High","enabled":true,"lastModifiedUtc":"2020-11-30T05:12:13.9883966Z"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/microsoftSecurityIncidentCreationRuleExample","name":"microsoftSecurityIncidentCreationRuleExample","etag":"\"8901b3c8-0000-0100-0000-5fc47f300000\"","type":"Microsoft.SecurityInsights/alertRules","kind":"MicrosoftSecurityIncidentCreation","properties":{"productFilter":"Microsoft
+ Cloud App Security","severitiesFilter":null,"displayNamesFilter":null,"displayNamesExcludeFilter":null,"displayName":"testing
+ displayname","enabled":true,"description":null,"tactics":null,"alertRuleTemplateName":null,"lastModifiedUtc":"2020-11-30T05:12:16.7234969Z"}}]}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '3000'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:23 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule delete
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '0'
+ ParameterSetName:
+ - -y --resource-group --rule-id --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: DELETE
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRules/myFirstFusionRule?api-version=2020-01-01
+ response:
+ body:
+ string: '{}'
+ headers:
+ api-supported-versions:
+ - 2019-01-01-preview
+ cache-control:
+ - no-cache
+ content-length:
+ - '2'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:26 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-deletes:
+ - '14999'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule-template show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --alert-rule-template-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRuleTemplates/65360bb0-8986-4ade-a89d-af3cf44d28aa?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/65360bb0-8986-4ade-a89d-af3cf44d28aa","name":"65360bb0-8986-4ade-a89d-af3cf44d28aa","type":"Microsoft.SecurityInsights/AlertRuleTemplates","kind":"Scheduled","properties":{"severity":"Low","query":"let
+ timeframe = 1d;\nlet EventNameList = dynamic([\"CreateNetworkAclEntry\",\"CreateRoute\",\"CreateRouteTable\",\"CreateInternetGateway\",\"CreateNatGateway\"]);\nAWSCloudTrail\n|
+ where TimeGenerated > ago(timeframe)\n| where EventName in~ (EventNameList)\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid,
+ UserAgent, \nUserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress,
+ AWSRegion, EventSource, AdditionalEventData, ResponseElements\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = UserIdentityUserName, IPCustomEntity
+ = SourceIpAddress","queryFrequency":"P1D","queryPeriod":"P1D","triggerOperator":"GreaterThan","triggerThreshold":0,"displayName":"Changes
+ to Amazon VPC settings","description":"Amazon Virtual Private Cloud (Amazon
+ VPC) lets you provision a logically isolated section of the AWS Cloud where
+ you can launch AWS resources\nin a virtual network that you define.\nThis
+ identifies changes to Amazon VPC (Virtual Private Cloud) settings such as
+ new ACL entries,routes, routetable or Gateways.\nMore information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255
+ \nand AWS VPC API Docs: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/OperationList-query-vpc.html","tactics":["PrivilegeEscalation","LateralMovement"],"createdDateUTC":"2019-02-27T00:00:00Z","status":"Available","requiredDataConnectors":[{"connectorId":"AWS","dataTypes":["AWSCloudTrail"]}],"alertRulesCreatedByTemplateCount":0}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '2077'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:28 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel alert-rule-template list
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/alertRuleTemplates?api-version=2020-01-01
+ response:
+ body:
+ string: "{\"value\":[{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/826bb2f8-7894-4785-9a6b-a8a855d8366f\",\"name\":\"826bb2f8-7894-4785-9a6b-a8a855d8366f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ EventNameList = dynamic([\\\"AttachUserPolicy\\\",\\\"AttachRolePolicy\\\",\\\"AttachGroupPolicy\\\"]);\\nlet
+ createPolicy = \\\"CreatePolicy\\\";\\nlet timeframe = 1d;\\nlet lookback
+ = 14d;\\n// Creating Master table with all the events to use with materialize
+ for better performance\\nlet EventInfo = AWSCloudTrail\\n| where TimeGenerated
+ >= ago(lookback)\\n| where EventName in (EventNameList) or EventName == createPolicy;\\n//Checking
+ for Policy creation event with Full Admin Privileges since lookback period.\\nlet
+ FullAdminPolicyEvents = materialize( EventInfo\\n| where TimeGenerated >=
+ ago(lookback)\\n| where EventName == createPolicy\\n| extend PolicyName =
+ tostring(parse_json(RequestParameters).policyName)\\n| extend Statement =
+ parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement\\n|
+ mvexpand Statement\\n| extend Action = parse_json(Statement).Action , Effect
+ = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource)\\n|
+ mvexpand Action\\n| extend Action = tostring(Action)\\n| where Effect =~ \\\"Allow\\\"
+ and Action == \\\"*\\\" and Resource == \\\"*\\\"\\n| distinct TimeGenerated,
+ EventName, PolicyName, SourceIpAddress, UserIdentityArn, UserIdentityUserName\\n|
+ extend UserIdentityUserName = iff(isnotempty(UserIdentityUserName), UserIdentityUserName,
+ tostring(split(UserIdentityArn,'/')[-1]))\\n| project-rename StartTime = TimeGenerated
+ \ );\\nlet PolicyAttach = materialize( EventInfo\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where EventName in (EventNameList)\\n| extend PolicyName
+ = tostring(split(tostring(parse_json(RequestParameters).policyArn),\\\"/\\\")[1])\\n|
+ summarize AttachEventCount=count(), StartTime = min(TimeGenerated), EndTime
+ = max(TimeGenerated) by EventSource, EventName, UserIdentityType , UserIdentityArn,
+ SourceIpAddress, UserIdentityUserName = iff(isnotempty(UserIdentityUserName),
+ \ UserIdentityUserName, tostring(split(UserIdentityArn,'/')[-1])), PolicyName\\n|
+ extend AttachEvent = pack(\\\"StartTime\\\", StartTime, \\\"EndTime\\\", EndTime,
+ \\\"EventName\\\", EventName, \\\"UserIdentityType\\\", UserIdentityType,
+ \\\"UserIdentityArn\\\", UserIdentityArn, \\\"SourceIpAddress\\\", SourceIpAddress,
+ \\\"UserIdentityUserName\\\", UserIdentityUserName)\\n| project EventSource,
+ PolicyName, AttachEvent, AttachEventCount\\n);\\n// Joining the list of PolicyNames
+ and checking if it has been attached to any Roles/Users/Groups.\\n// These
+ Roles/Users/Groups will be Privileged and can be used by adversaries as pivot
+ point for privilege escalation via multiple ways.\\nFullAdminPolicyEvents\\n|
+ join kind=leftouter\\n(\\n PolicyAttach\\n)\\non PolicyName\\n| project-away
+ PolicyName1\\n| extend timestamp = StartTime, IPCustomEntity = SourceIpAddress,
+ AccountCustomEntity = UserIdentityUserName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Full
+ Admin policy created and then attached to Roles, Users or Groups\",\"description\":\"Identity
+ and Access Management (IAM) securely manages access to AWS services and resources.
+ \\nIdentifies when a policy is created with Full Administrators Access (Allow-Action:*,Resource:*).
+ \\nThis policy can be attached to role,user or group and may be used by an
+ adversary to escalate a normal user privileges to an adminsitrative level.\\nAWS
+ IAM Policy Grammar: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_grammar.html\\nand
+ AWS IAM API at https://docs.aws.amazon.com/IAM/latest/APIReference/API_Operations.html\",\"tactics\":[\"PrivilegeEscalation\"],\"createdDateUTC\":\"2020-04-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/fb0f4a93-d8ad-4b54-9931-85bdb7550f90\",\"name\":\"fb0f4a93-d8ad-4b54-9931-85bdb7550f90\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nSymantecProxySG\\n| where TimeGenerated >= timeframe\\n|
+ mv-expand cs_categories\\n| where cs_categories has_any (\\\"Suspicious\\\",\\\"phishing\\\",
+ \\\"hacking\\\")\\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated),
+ count() by sc_filter_result, cs_userdn, c_ip, cs_host, Computer, tostring(cs_categories)\\n|
+ extend timestamp = StartTime, AccountCustomEntity = cs_userdn, IPCustomEntity
+ = c_ip, HostCustomEntity = Computer\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ Accessed Suspicious URL Categories\",\"description\":\"Creates an incident
+ in the event the requested URL accessed by the user has been identified as
+ Suspicious, Phishing, or Hacking.\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SymantecProxySG\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a2e0eb51-1f11-461a-999b-cd0ebe5c7a72\",\"name\":\"a2e0eb51-1f11-461a-999b-cd0ebe5c7a72\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Azure
+ Security Center for IoT\",\"displayName\":\"Create incidents based on Azure
+ Security Center for IoT alerts\",\"description\":\"Create incidents based
+ on all alerts generated in Azure Security Center for IoT\",\"createdDateUTC\":\"2019-12-24T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"IoT\",\"dataTypes\":[\"SecurityAlert
+ (ASC for IoT)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/83ba3057-9ea3-4759-bf6a-933f2e5bc7ee\",\"name\":\"83ba3057-9ea3-4759-bf6a-933f2e5bc7ee\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ current = 1d;\\nlet auditLookback = 7d;\\n// Setting threshold to 3 as a default,
+ change as needed. \\n// Any operation that has been initiated by a user or
+ app more than 3 times in the past 7 days will be excluded\\nlet threshold
+ = 3;\\n// Gather initial data from lookback period, excluding current, adjust
+ current to more than a single day if no results\\nlet AuditTrail = AuditLogs
+ | where TimeGenerated >= ago(auditLookback) and TimeGenerated < ago(current)\\n//
+ 2 other operations that can be part of malicious activity in this situation
+ are \\n// \\\"Add OAuth2PermissionGrant\\\" and \\\"Add service principal\\\",
+ extend the filter below to capture these too\\n| where OperationName == \\\"Consent
+ to application\\\"\\n| extend InitiatedBy = iff(isnotempty(tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)),
+ \\ntostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName), tostring(parse_json(tostring(InitiatedBy.app)).displayName))\\n|
+ extend TargetResourceName = tolower(tostring(TargetResources.[0].displayName))\\n|
+ summarize max(TimeGenerated), OperationCount = count() by OperationName, InitiatedBy,
+ TargetResourceName\\n// only including operations by initiated by a user or
+ app that is above the threshold so we produce only rare and has not occurred
+ in last 7 days\\n| where OperationCount > threshold\\n;\\n// Gather current
+ period of audit data\\nlet RecentConsent = AuditLogs | where TimeGenerated
+ >= ago(current)\\n| where OperationName == \\\"Consent to application\\\"\\n|
+ extend IpAddress = iff(isnotempty(tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)),
+ \\ntostring(parse_json(tostring(InitiatedBy.user)).ipAddress), tostring(parse_json(tostring(InitiatedBy.app)).ipAddress))\\n|
+ extend InitiatedBy = iff(isnotempty(tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)),
+ \\ntostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName), tostring(parse_json(tostring(InitiatedBy.app)).displayName))\\n|
+ extend TargetResourceName = tolower(tostring(TargetResources.[0].displayName))\\n|
+ parse TargetResources.[0].modifiedProperties with * \\\"ConsentType: \\\"
+ ConsentType \\\"]\\\" *\\n| project TimeGenerated, InitiatedBy, IpAddress,
+ TargetResourceName, Category, OperationName, ConsentType , CorrelationId,
+ Type;\\n// Exclude previously seen audit activity for \\\"Consent to application\\\"
+ that was seen in the lookback period\\n// First for rare InitiatedBy\\nlet
+ RareConsentBy = RecentConsent | join kind= leftanti AuditTrail on OperationName,
+ InitiatedBy \\n| extend Reason = \\\"Previously unseen user consenting\\\";\\n//
+ Second for rare TargetResourceName\\nlet RareConsentApp = RecentConsent |
+ join kind= leftanti AuditTrail on OperationName, TargetResourceName\\n| extend
+ Reason = \\\"Previously unseen app granted consent\\\";\\nRareConsentBy |
+ union RareConsentApp\\n| summarize Reason = makeset(Reason) by TimeGenerated,
+ InitiatedBy, IpAddress, TargetResourceName, Category, OperationName, ConsentType,
+ CorrelationId, Type\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = InitiatedBy, HostCustomEntity = TargetResourceName, IPCustomEntity = IpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":3,\"displayName\":\"Rare
+ application consent\",\"description\":\"This will alert when the \\\"Consent
+ to application\\\" operation occurs by a user that has not done this operation
+ before or rarely does this.\\nThis could indicate that permissions to access
+ the listed Azure App were provided to a malicious actor. \\nConsent to application,
+ Add service principal and Add OAuth2PermissionGrant should typically be rare
+ events. \\nThis may help detect the Oauth2 attack that can be initiated by
+ this publicly available tool - https://github.com/fireeye/PwnAuth\\nFor further
+ information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.\",\"tactics\":[\"Persistence\",\"LateralMovement\",\"Collection\"],\"createdDateUTC\":\"2019-07-04T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2441bce9-02e4-407b-8cc7-7d597f38b8b0\",\"name\":\"2441bce9-02e4-407b-8cc7-7d597f38b8b0\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n AzureActivity | where
+ TimeGenerated >= ago(dt_lookBack)\\n // renaming time column so it is clear
+ the log this came from\\n | extend AzureActivity_TimeGenerated = TimeGenerated\\n)\\non
+ $left.TI_ipEntity == $right.CallerIpAddress\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime,
+ ConfidenceScore, AzureActivity_TimeGenerated,\\nTI_ipEntity, CallerIpAddress,
+ Caller, OperationName, ActivityStatus, Category, ResourceId, NetworkIP, NetworkDestinationIP,
+ NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp = AzureActivity_TimeGenerated,
+ IPCustomEntity = CallerIpAddress, AccountCustomEntity = Caller, URLCustomEntity
+ = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to AzureActivity\",\"description\":\"Identifies a match in
+ AzureActivity from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ee1d718b-9ed9-4a71-90cd-a483a4f008df\",\"name\":\"ee1d718b-9ed9-4a71-90cd-a483a4f008df\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Office
+ 365 Advanced Threat Protection\",\"displayName\":\"Create incidents based
+ on Office 365 Advanced Threat Protection alerts\",\"description\":\"Create
+ incidents based on all alerts generated in Office 365 Advanced Threat Protection\",\"createdDateUTC\":\"2020-04-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"OfficeATP\",\"dataTypes\":[\"SecurityAlert
+ (OATP)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/106813db-679e-4382-a51b-1bfc463befc3\",\"name\":\"106813db-679e-4382-a51b-1bfc463befc3\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(Url)\\n| join (\\n CommonSecurityLog\\n | extend
+ IngestionTime = ingestion_time()\\n | where IngestionTime > ago(dt_lookBack)\\n
+ \ // Select on Palo Alto logs\\n | where DeviceVendor =~ \\\"Palo Alto Networks\\\"\\n
+ \ | where DeviceEventClassID =~ 'url'\\n //Uncomment the line below to only
+ alert on allowed connections\\n //| where DeviceAction !~ \\\"block-url\\\"\\n
+ \ //Select logs where URL data is populated\\n | extend PA_Url = columnifexists(\\\"RequestURL\\\",
+ \\\"None\\\")\\n | extend PA_Url = iif(isempty(PA_Url), extract(\\\"([^\\\\\\\"]+)\\\",
+ 1, tolower(AdditionalExtensions)), trim('\\\"', PA_Url))\\n | extend PA_Url
+ = iif(PA_Url !startswith \\\"http://\\\" and ApplicationProtocol !~ \\\"ssl\\\",
+ strcat('http://', PA_Url), iif(PA_Url !startswith \\\"https://\\\" and ApplicationProtocol
+ =~ \\\"ssl\\\", strcat('https://', PA_Url), PA_Url))\\n | where isnotempty(PA_Url)\\n
+ \ | extend CSL_TimeGenerated = TimeGenerated\\n) on $left.Url == $right.PA_Url\\n|
+ project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId,
+ ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, SourceIP, CSL_TimeGenerated,
+ PA_Url, DeviceName\\n| extend timestamp = CSL_TimeGenerated, IPCustomEntity
+ = SourceIP, HostCustomEntity = DeviceName, URLCustomEntity = PA_Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map URL entity to PaloAlto data\",\"description\":\"Identifies a match
+ in PaloAlto data from any URL IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/5dd76a87-9f87-4576-bab3-268b0e2b338b\",\"name\":\"5dd76a87-9f87-4576-bab3-268b0e2b338b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ threshold = 5;\\nlet szSharePointFileOperation = \\\"SharePointFileOperation\\\";\\nlet
+ szOperations = dynamic([\\\"FileDownloaded\\\", \\\"FileUploaded\\\"]);\\nlet
+ starttime = 14d;\\nlet endtime = 1d;\\nlet historicalActivity =\\nOfficeActivity\\n|
+ where TimeGenerated between(ago(starttime)..ago(endtime))\\n| where RecordType
+ =~ szSharePointFileOperation\\n| where Operation in~ (szOperations)\\n| where
+ isnotempty(UserAgent)\\n| summarize historicalCount = count() by UserAgent,
+ RecordType, Operation;\\nlet recentActivity = OfficeActivity\\n| where RecordType
+ =~ szSharePointFileOperation\\n| where Operation in~ (szOperations)\\n| where
+ TimeGenerated > ago(endtime)\\n| where isnotempty(UserAgent)\\n| summarize
+ min(Start_Time), max(Start_Time), recentCount = count() by UserAgent, RecordType,
+ Operation;\\nlet RareUserAgent = recentActivity | join kind = leftanti (historicalActivity)
+ on UserAgent\\n| order by recentCount desc, UserAgent\\n// More than 3 downloads/uploads
+ from a new user agent today\\n| where recentCount > threshold;\\nOfficeActivity
+ \\n| where TimeGenerated > ago(endtime) \\n| where RecordType =~ szSharePointFileOperation
+ \\n| where Operation in~ (szOperations)\\n| where isnotempty(UserAgent)\\n|
+ join kind= inner (RareUserAgent)\\non UserAgent, RecordType, Operation \\n|
+ where Start_Time between(min_Start_Time .. max_Start_Time)\\n| summarize StartTimeUtc
+ = min(min_Start_Time), EndTimeUtc = max(max_Start_Time) by RecordType, Operation,
+ UserAgent, UserType, UserId, ClientIP, OfficeWorkload, Site_Url, OfficeObjectId,
+ UserAgentSeenCount = recentCount\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = UserId, IPCustomEntity = ClientIP, URLCustomEntity = Site_Url\\n| order
+ by UserAgentSeenCount desc, UserAgent asc, Operation asc, UserId asc\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"SharePointFileOperation
+ via devices with previously unseen user agents\",\"description\":\"Identifies
+ if the number of documents uploaded or downloaded from device(s) associated\\nwith
+ a previously unseen user agent exceeds a threshold (default is 5).\",\"tactics\":[\"Exfiltration\"],\"createdDateUTC\":\"2019-08-23T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2c55fe7a-b06f-4029-a5b9-c54a2320d7b8\",\"name\":\"2c55fe7a-b06f-4029-a5b9-c54a2320d7b8\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\nlet timeframe = 1h;\\nlet TotalEventsThreshold
+ = 5;\\nlet ExeList = dynamic([\\\"powershell.exe\\\",\\\"cmd.exe\\\",\\\"wmic.exe\\\",\\\"psexec.exe\\\",\\\"cacls.exe\\\",\\\"rundll.exe\\\"]);\\nlet
+ TimeSeriesData = \\nSecurityEvent\\n| where EventID == 4688 | extend Process
+ = tolower(Process)\\n| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime)))\\n|
+ where Process in (ExeList)\\n| project TimeGenerated, Computer, AccountType,
+ Account, Process\\n| make-series Total=count() on TimeGenerated from ago(starttime)
+ to ago(endtime) step timeframe by Process;\\nlet TimeSeriesAlerts = TimeSeriesData\\n|
+ extend (anomalies, score, baseline) = series_decompose_anomalies(Total, 1.5,
+ -1, 'linefit')\\n| mv-expand Total to typeof(double), TimeGenerated to typeof(datetime),
+ anomalies to typeof(double), score to typeof(double), baseline to typeof(long)\\n|
+ where anomalies > 0\\n| project Process, TimeGenerated, Total, baseline, anomalies,
+ score\\n| where Total > TotalEventsThreshold;\\nTimeSeriesAlerts\\n| join
+ (\\nSecurityEvent\\n| where EventID == 4688 | extend Process = tolower(Process)\\n|
+ summarize CommandlineCount = count() by bin(TimeGenerated, 1h), Process, CommandLine,
+ Computer, Account\\n) on Process, TimeGenerated \\n| project AnomalyHour =
+ TimeGenerated, Computer, Account, Process, CommandLine, CommandlineCount,
+ Total, baseline, anomalies, score \\n| extend timestamp = AnomalyHour, AccountCustomEntity
+ = Account, HostCustomEntity = Computer\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Process
+ execution frequency anomaly\",\"description\":\"Identifies anomalous spike
+ in frequency of executions of sensitive processes which are often leveraged
+ as attack vectors. \\nThe query leverages KQL built-in anomaly detection algorithms
+ to find large deviations from baseline patterns. \\nSudden increases in execution
+ frequency of sensitive processes should be further investigated for malicious
+ activity.\\nTune the values from 1.5 to 3 in series_decompose_anomalies for
+ further outliers or based on custom threshold values for score.\",\"tactics\":[\"Execution\"],\"createdDateUTC\":\"2019-05-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f0be259a-34ac-4946-aa15-ca2b115d5feb\",\"name\":\"f0be259a-34ac-4946-aa15-ca2b115d5feb\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 2d;\\nlet endtime = 1d;\\nlet TimeDeltaThreshold = 10;\\nlet TotalEventsThreshold
+ = 15;\\nlet PercentBeaconThreshold = 80;\\nlet PrivateIPregex = @'^127\\\\.|^10\\\\.|^172\\\\.1[6-9]\\\\.|^172\\\\.2[0-9]\\\\.|^172\\\\.3[0-1]\\\\.|^192\\\\.168\\\\.';\\nCommonSecurityLog\\n|
+ where DeviceVendor == \\\"Palo Alto Networks\\\" and Activity == \\\"TRAFFIC\\\"\\n|
+ where TimeGenerated between (ago(starttime)..ago(endtime))\\n| extend DestinationIPType
+ = iff(DestinationIP matches regex PrivateIPregex,\\\"private\\\" ,\\\"public\\\"
+ )\\n| where DestinationIPType == \\\"public\\\"\\n| project TimeGenerated,
+ DeviceName, SourceUserID, SourceIP, SourcePort, DestinationIP, DestinationPort,
+ ReceivedBytes, SentBytes\\n| sort by SourceIP asc,TimeGenerated asc, DestinationIP
+ asc, DestinationPort asc\\n| serialize\\n| extend nextTimeGenerated = next(TimeGenerated,
+ 1), nextSourceIP = next(SourceIP, 1)\\n| extend TimeDeltainSeconds = datetime_diff('second',nextTimeGenerated,TimeGenerated)\\n|
+ where SourceIP == nextSourceIP\\n//Whitelisting criteria/ threshold criteria\\n|
+ where TimeDeltainSeconds > TimeDeltaThreshold \\n| project TimeGenerated,
+ TimeDeltainSeconds, DeviceName, SourceUserID, SourceIP, SourcePort, DestinationIP,
+ DestinationPort, ReceivedBytes, SentBytes\\n| summarize count(), sum(ReceivedBytes),
+ sum(SentBytes), make_list(TimeDeltainSeconds) \\nby TimeDeltainSeconds, bin(TimeGenerated,
+ 1h), DeviceName, SourceUserID, SourceIP, DestinationIP, DestinationPort\\n|
+ summarize (MostFrequentTimeDeltaCount, MostFrequentTimeDeltainSeconds) = arg_max(count_,
+ TimeDeltainSeconds), TotalEvents=sum(count_), TotalSentBytes = sum(sum_SentBytes),
+ TotalReceivedBytes = sum(sum_ReceivedBytes) \\nby bin(TimeGenerated, 1h),
+ DeviceName, SourceUserID, SourceIP, DestinationIP, DestinationPort\\n| where
+ TotalEvents > TotalEventsThreshold \\n| extend BeaconPercent = MostFrequentTimeDeltaCount/toreal(TotalEvents)
+ * 100\\n| where BeaconPercent > PercentBeaconThreshold\\n| extend timestamp
+ = TimeGenerated, IPCustomEntity = DestinationIP, AccountCustomEntity = SourceUserID,
+ HostCustomEntity = DeviceName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Palo
+ Alto - potential beaconing detected\",\"description\":\"Identifies beaconing
+ patterns from Palo Alto Network traffic logs based on recurrent timedelta
+ patterns. \\nThe query leverages various KQL functions to calculate time deltas
+ and then compares it with total events observed in a day to find percentage
+ of beaconing. \\nThis outbound beaconing pattern to untrusted public networks
+ should be investigated for any malware callbacks or data exfiltration attempts.\\nReference
+ Blog:\\nhttp://www.austintaylor.io/detect/beaconing/intrusion/detection/system/command/control/flare/elastic/stack/2017/06/10/detect-beaconing-with-flare-elasticsearch-and-intrusion-detection-systems/\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-05-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/c775a46b-21b1-46d7-afa6-37e3e577a27b\",\"name\":\"c775a46b-21b1-46d7-afa6-37e3e577a27b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 15;\\nSymantecVIP\\n| where TimeGenerated
+ > timeframe\\n| where isnotempty(RADIUSAuth)\\n| where RADIUSAuth =~ \\\"Reject\\\"\\n|
+ summarize Total = count() by bin(TimeGenerated, 15m), User, ClientIP\\n| where
+ Total > threshold\\n| extend timestamp = TimeGenerated, IPCustomEntity = ClientIP,
+ AccountCustomEntity = User\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Excessive
+ Failed Authentication from Invalid Inputs\",\"description\":\"Creates an incident
+ in the event that a user generates an excessive amount of failed authentications
+ due to invalid inputs, indications of a potential brute force.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SymantecVIP\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/69a45b05-71f5-45ca-8944-2e038747fb39\",\"name\":\"69a45b05-71f5-45ca-8944-2e038747fb39\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ endtime = 1d;\\nlet starttime = 8d;\\n// The threshold below excludes matching
+ on RDP connection computer counts of 5 or more by a given account and IP in
+ a given day. Change the threshold as needed.\\nlet threshold = 5;\\nSecurityEvent\\n|
+ where TimeGenerated >= ago(endtime) \\n| where EventID == 4624 and LogonType
+ == 10\\n// Labeling the first RDP connection time, computer and ip\\n| extend
+ FirstHop = TimeGenerated, FirstComputer = toupper(Computer), FirstIPAddress
+ = IpAddress, Account = tolower(Account) \\n| join kind=inner (\\nSecurityEvent\\n|
+ where TimeGenerated >= ago(endtime) \\n| where EventID == 4624 and LogonType
+ == 10\\n// Labeling the second RDP connection time, computer and ip\\n| extend
+ SecondHop = TimeGenerated, SecondComputer = toupper(Computer), SecondIPAddress
+ = IpAddress, Account = tolower(Account)\\n) on Account\\n// Make sure that
+ the first connection is after the second connection --> SecondHop > FirstHop\\n//
+ Then identify only RDP to another computer from within the first RDP connection
+ by only choosing matches where the Computer names do not match --> FirstComputer
+ != SecondComputer\\n// Then make sure the IPAddresses do not match by excluding
+ connections from the same computers with first hop RDP connections to multiple
+ computers --> FirstIPAddress != SecondIPAddress\\n| where FirstComputer !=
+ SecondComputer and FirstIPAddress != SecondIPAddress and SecondHop > FirstHop\\n//
+ where the second hop occurs within 30 minutes of the first hop\\n| where SecondHop
+ <= FirstHop+30m\\n| distinct Account, FirstHop, FirstComputer, FirstIPAddress,
+ SecondHop, SecondComputer, SecondIPAddress, AccountType, Activity, LogonTypeName,
+ ProcessName\\n// use left anti to exclude anything from the previous 7 days
+ where the Account and IP has connected 5 or more computers.\\n| join kind=leftanti
+ (\\nSecurityEvent\\n| where TimeGenerated >= ago(starttime) and TimeGenerated
+ < ago(endtime) \\n| where EventID == 4624 and LogonType == 10\\n| summarize
+ makeset(Computer), ComputerCount = dcount(Computer) by bin(TimeGenerated,
+ 1d), Account = tolower(Account), IpAddress\\n// Connection count to computer
+ by same account and IP to exclude counts of 5 or more on a given day\\n| where
+ ComputerCount >= threshold\\n| mvexpand set_Computer\\n| extend Computer =
+ toupper(set_Computer)\\n) on Account, $left.SecondComputer == $right.Computer,
+ $left.SecondIPAddress == $right.IpAddress\\n| summarize FirstHopFirstSeen
+ = min(FirstHop), FirstHopLastSeen = max(FirstHop) by Account, FirstComputer,
+ FirstIPAddress, SecondHop, SecondComputer, \\nSecondIPAddress, AccountType,
+ Activity, LogonTypeName, ProcessName\\n| extend timestamp = FirstHopFirstSeen,
+ AccountCustomEntity = Account, HostCustomEntity = FirstComputer, IPCustomEntity
+ = FirstIPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P8D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"RDP
+ Nesting\",\"description\":\"Identifies when an RDP connection is made to a
+ first system and then an RDP connection is made from the first system \\nto
+ another system with the same account within the 60 minutes. Additionally,
+ if historically daily \\nRDP connections are indicated by the logged EventID
+ 4624 with LogonType = 10\",\"tactics\":[\"LateralMovement\"],\"createdDateUTC\":\"2019-10-21T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/cf3ede88-a429-493b-9108-3e46d3c741f7\",\"name\":\"cf3ede88-a429-493b-9108-3e46d3c741f7\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeRange = 6h;\\nlet authenticationWindow = 1h;\\nlet authenticationThreshold
+ = 5;\\nSecurityEvent\\n| where TimeGenerated > ago(timeRange)\\n| where EventID
+ == 4624 or EventID == 4625\\n| where IpAddress != \\\"-\\\" and isnotempty(Account)\\n|
+ extend Outcome = iff(EventID == 4624, \\\"Success\\\", \\\"Failure\\\")\\n//
+ bin outcomes into 5 minute windows to reduce the volume of data\\n| summarize
+ OutcomeCount=count() by Account, IpAddress, Computer, Outcome, bin(TimeGenerated,
+ 5m)\\n| project TimeGenerated, Account, IpAddress, Computer, Outcome, OutcomeCount\\n//
+ sort ready for sessionizing - by account and time of the authentication outcome\\n|
+ sort by Account asc, TimeGenerated asc\\n| serialize \\n// sessionize into
+ failure groupings until either the account changes or there is a success\\n|
+ extend SessionStartedUtc = row_window_session(TimeGenerated, timeRange, authenticationWindow,
+ Account != prev(Account) or prev(Outcome) == \\\"Success\\\")\\n// count the
+ failures in each session\\n| summarize FailureCountBeforeSuccess=sumif(OutcomeCount,
+ Outcome == \\\"Failure\\\"), StartTime=min(TimeGenerated), EndTime=max(TimeGenerated),
+ makelist(Outcome), makeset(Computer), makeset(IpAddress) by SessionStartedUtc,
+ Account\\n// the session must not start with a success, and must end with
+ one\\n| where array_index_of(list_Outcome, \\\"Success\\\") != 0\\n| where
+ array_index_of(list_Outcome, \\\"Success\\\") == array_length(list_Outcome)
+ - 1\\n| project-away SessionStartedUtc, list_Outcome \\n// where the number
+ of failures before the success is above the threshold \\n| where FailureCountBeforeSuccess
+ >= authenticationThreshold\\n// expand out ip and computer for customer entity
+ assignment\\n| mvexpand set_IpAddress, set_Computer\\n| extend IpAddress =
+ tostring(set_IpAddress), Computer = tostring(set_Computer)\\n| extend timestamp=StartTime,
+ AccountCustomEntity=Account, HostCustomEntity=Computer, IPCustomEntity=IpAddress\",\"queryFrequency\":\"PT6H\",\"queryPeriod\":\"PT6H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"SecurityEvent
+ - Multiple authentication failures followed by a success\",\"description\":\"Identifies
+ accounts who have failed to logon to the domain multiple times in a row, followed
+ by a successful authentication\\nwithin a short time frame. Multiple failed
+ attempts followed by a success can be an indication of a brute force attempt
+ or\\npossible mis-configuration of a service account within an environment.\\nThe
+ lookback is set to 6h and the authentication window and threshold are set
+ to 1h and 5, meaning we need to see a minimum\\nof 5 failures followed by
+ a success for an account within 1 hour to surface an alert.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-04-03T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4f19d4e3-ec5f-4abc-9e61-819eb131758c\",\"name\":\"4f19d4e3-ec5f-4abc-9e61-819eb131758c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet EventNameList = dynamic([ \\\"AuthorizeSecurityGroupEgress\\\",
+ \\\"AuthorizeSecurityGroupIngress\\\", \\\"RevokeSecurityGroupEgress\\\",
+ \\\"RevokeSecurityGroupIngress\\\"]);\\nAWSCloudTrail\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where EventName in~ (EventNameList)\\n| extend User
+ = iif(isnotempty(UserIdentityUserName), UserIdentityUserName, SessionIssuerUserName)\\n|
+ summarize EventCount=count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc
+ = max(TimeGenerated) \\nby EventSource, EventName, UserIdentityType, User,
+ SourceIpAddress, UserAgent, SessionMfaAuthenticated, AWSRegion, \\nAdditionalEventData,
+ UserIdentityAccountId, UserIdentityPrincipalid, ResponseElements\\n| extend
+ timestamp = StartTimeUtc, AccountCustomEntity = User , IPCustomEntity = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Changes
+ to AWS Security Group ingress and egress settings\",\"description\":\"A Security
+ Group acts as a virtual firewall of an instance to control inbound and outbound
+ traffic. \\n Hence, ingress and egress settings changes to AWS Security Group
+ should be monitored as these can expose the enviornment to new attack vectors.\\nMore
+ information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255.\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/84cf1d59-f620-4fee-b569-68daf7008b7b\",\"name\":\"84cf1d59-f620-4fee-b569-68daf7008b7b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 10;\\nQualysHostDetection_CL\\n| where
+ TimeGenerated >= timeframe\\n| mv-expand todynamic(Detections_s)\\n| extend
+ Status = tostring(Detections_s.Status), Vulnerability = tostring(Detections_s.Results),
+ Severity = tostring(Detections_s.Severity)\\n| where Status =~ \\\"New\\\"
+ and Severity == \\\"5\\\"\\n| summarize StartTime = min(TimeGenerated), EndTime
+ = max(TimeGenerated), dcount(NetBios_s) by tostring(Detections_s.QID)\\n|
+ where dcount_NetBios_s >= threshold\\n| extend timestamp = StartTime\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"New
+ High Severity Vulnerability Detected Across Multiple Hosts\",\"description\":\"This
+ creates an incident when a new high severity vulnerability is detected across
+ multilple hosts\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"QualysVulnerabilityManagement\",\"dataTypes\":[\"QualysHostDetection_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/fbd72eb8-087e-466b-bd54-1ca6ea08c6d3\",\"name\":\"fbd72eb8-087e-466b-bd54-1ca6ea08c6d3\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nOfficeActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where RecordType =~ \\\"ExchangeAdmin\\\"\\n| where UserType in~ (\\\"Admin\\\",\\\"DcAdmin\\\")
+ \\n// Only admin or global-admin can disable/remove policy\\n| where Operation
+ startswith \\\"Remove-\\\" or Operation startswith \\\"Disable-\\\"\\n| where
+ Operation has_any (\\\"AntiPhish\\\", \\\"SafeAttachment\\\", \\\"SafeLinks\\\",
+ \\\"Dlp\\\", \\\"Audit\\\")\\n| extend ClientIPOnly = case( \\nClientIP has
+ \\\".\\\", tostring(split(ClientIP,\\\":\\\")[0]), \\nClientIP has \\\"[\\\",
+ tostring(trim_start(@'[[]',tostring(split(ClientIP,\\\"]\\\")[0]))),\\nClientIP\\n)
+ \ \\n| extend Port = case(\\nClientIP has \\\".\\\", (split(ClientIP,\\\":\\\")[1]),\\nClientIP
+ has \\\"[\\\", tostring(split(ClientIP,\\\"]:\\\")[1]),\\nClientIP\\n)\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ OperationCount = count() by Operation, UserType, UserId, ClientIP = ClientIPOnly,
+ Port, ResultStatus, Parameters\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = UserId, IPCustomEntity = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Office
+ policy tampering\",\"description\":\"Identifies if any tampering is done to
+ either auditlog, ATP Safelink, SafeAttachment, AntiPhish or Dlp policy. \\nAn
+ adversary may use this technique to evade detection or avoid other policy
+ based defenses.\\nReferences: https://docs.microsoft.com/powershell/module/exchange/advanced-threat-protection/remove-antiphishrule?view=exchange-ps.\",\"tactics\":[\"Persistence\",\"DefenseEvasion\"],\"createdDateUTC\":\"2019-04-15T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2b701288-b428-4fb8-805e-e4372c574786\",\"name\":\"2b701288-b428-4fb8-805e-e4372c574786\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"//The
+ bigger the window the better the data sample size, as we use IP prevalence,
+ more sample data is better.\\nlet timeRange = 30d;\\n//The minimum number
+ of countries that the account has been accessed from [default: 2]\\nlet minimumCountries
+ = 2;\\n//The delta (%) between the largest in-use IP and the smallest [default:
+ 90]\\nlet deltaThreshold = 95;\\n//The maximum (%) threshold that the country
+ appears in login data [default: 10]\\nlet countryPrevalenceThreshold = 10;\\n//The
+ time to project forward after the last login activity [default: 60min]\\nlet
+ projectedEndTime = 60min; \\n//Get Teams successful signins globally\\nlet
+ signinData =\\n SigninLogs\\n | where TimeGenerated >= ago(timeRange)\\n
+ \ | where AppDisplayName has \\\"Teams\\\"\\n | where ConditionalAccessStatus
+ =~ \\\"success\\\"\\n | extend country = tostring(LocationDetails['countryOrRegion'])\\n
+ \ | where isnotempty(country) and isnotempty(IPAddress);\\n// Collect successful
+ signins to teams\\nlet loginEvents = \\n signinData\\n | summarize count(),
+ country=any(country), make_list(TimeGenerated) by IPAddress, UserPrincipalName;\\n//Calcualte
+ delta between logins\\nlet loginDelta =\\n loginEvents\\n | summarize max(count_),
+ min(count_) by UserPrincipalName\\n | extend delta = toreal(max_count_ -
+ min_count_) / max_count_ * 100\\n | where delta >= deltaThreshold;\\n//Count
+ number of countries used to sign in\\nlet countryCount =\\n loginEvents\\n
+ \ | summarize Countries = dcount(country) by UserPrincipalName;\\n//Join delta
+ and sign in counts to successful logins\\nloginDelta\\n| join kind=rightouter
+ \ (\\n loginEvents\\n) on UserPrincipalName\\n| join kind=rightouter (\\n
+ \ countryCount\\n) on UserPrincipalName\\n//Check where the record meets the
+ minimum required countries\\n| where Countries >= minimumCountries\\n| join
+ kind=leftouter (\\n signinData\\n | summarize count() by country\\n
+ \ | join (\\n //Now get the total number of logins from any country
+ and join it to the previous count in a single table\\n signinData\\n
+ \ | summarize count() by country\\n | summarize sum(count_),
+ make_list(country)\\n | mv-expand list_country\\n | extend
+ country = tostring(list_country)\\n ) on country\\n | summarize
+ by country, count_, sum_count_\\n //Now calculate each countries prevalence
+ within login events\\n | extend prevalence = toreal(count_) / toreal(sum_count_)
+ * 100\\n | project-away sum_count_\\n | order by prevalence\\n)
+ on country\\n//The % that suspicious country is prevalent in data, this can
+ be configured, less than 10% is uncommon\\n| where prevalence < countryPrevalenceThreshold\\n|
+ where min_count_ == count_\\n//Login start and end times from the JSON object,
+ this is the activity window the suspicious IP was active within\\n| extend
+ EventTimes = list_TimeGenerated\\n| extend SuspiciousIP = IPAddress\\n| project
+ UserPrincipalName, SuspiciousIP, UserIPDelta = delta, SuspiciousLoginCountry
+ = country, SuspiciousCountryPrevalence = prevalence, EventTimes\\n//Teams
+ join to collect operations the user account has performed within the given
+ time range\\n| join kind=inner( \\n TeamsData \\n | where TimeGenerated
+ >= ago(timeRange)\\n | where Operation in~ (\\\"TeamsAdminAction\\\", \\\"MemberAdded\\\",
+ \\\"MemberRemoved\\\", \\\"MemberRoleChanged\\\", \\\"AppInstalled\\\", \\\"BotAddedToTeam\\\")\\n
+ \ | project Operation, UserId=tolower(UserId), OperationTime=TimeGenerated\\n)
+ on $left.UserPrincipalName == $right.UserId\\n| mv-expand StartTime = EventTimes\\n|
+ extend StartTime = make_datetime(StartTime)\\n//The end time is projected
+ 60 minutes forward, in case actions took place within the last hour of the
+ final login for the suspicious IP\\n| extend ProjectedEndTime = make_datetime(StartTime
+ + projectedEndTime)\\n//Limit to operations carried out by the user account
+ in the timeframe the IP was active\\n| where OperationTime between (StartTime
+ .. ProjectedEndTime)\\n| project UserPrincipalName, SuspiciousIP, StartTime,
+ ProjectedEndTime, OperationTime, Operation, SuspiciousLoginCountry, SuspiciousCountryPrevalence\\n//Filter
+ on suspicious actions\\n| extend activitySummary = pack(tostring(StartTime),
+ pack(\\\"Operation\\\",tostring(Operation), \\\"OperationTime\\\", OperationTime))\\n|
+ summarize make_bag(activitySummary) by UserPrincipalName, SuspiciousIP, SuspiciousLoginCountry,
+ SuspiciousCountryPrevalence\\n| extend IPCustomEntity = SuspiciousIP, AccountCustomEntity
+ = UserPrincipalName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Anomalous
+ login followed by Teams action\",\"description\":\"Detects anomalous IP address
+ usage by user accounts and then checks to see if a suspicious Teams action
+ is performed.\\nQuery calculates IP usage Delta for each user account and
+ selects accounts where a delta >= 90% is observed between the most and least
+ used IP.\\nTo further reduce results the query performs a prevalence check
+ on the lowest used IP's country, only keeping IP's where the country is unusual
+ for the tenant (dynamic ranges)\\nFinally the user accounts activity within
+ Teams logs is checked for suspicious commands (modifying user privileges or
+ admin actions) during the period the suspicious IP was active.\",\"tactics\":[\"InitialAccess\",\"Persistence\"],\"createdDateUTC\":\"2020-06-30T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]},{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f7f4a77e-f68f-4b56-9aaf-a0c9d87d7a8e\",\"name\":\"f7f4a77e-f68f-4b56-9aaf-a0c9d87d7a8e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"//
+ Replace these with the usename or emails of your VIP users you wish to monitor
+ for.\\nlet vips = dynamic(['vip1@email.com','vip2@email.com']);\\nlet timeframe
+ = 1d;\\nLAQueryLogs\\n| where TimeGenerated > ago(timeframe)\\n| where QueryText
+ has_any (vips)\\n| project TimeGenerated, AADEmail, RequestClientApp, QueryText,
+ ResponseRowCount, RequestTarget\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Users
+ searching for VIP user activity\",\"description\":\"This query monitors for
+ users running Log Analytics queries that contain filters \\nfor specific,
+ defined VIP user accounts. Use this detection to alert for users specifically
+ \\nsearching for activity of sensitive users.\",\"tactics\":[\"Collection\",\"Exfiltration\"],\"createdDateUTC\":\"2020-09-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(Query
+ Audit)\",\"dataTypes\":[\"LAQueryLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/223db5c1-1bf8-47d8-8806-bed401b356a4\",\"name\":\"223db5c1-1bf8-47d8-8806-bed401b356a4\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeRange = 1d;\\nlet lookBack = 7d;\\nlet threshold_Failed = 5;\\nlet threshold_FailedwithSingleIP
+ = 20;\\nlet threshold_IPAddressCount = 2;\\nlet isGUID = \\\"[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}\\\";\\nlet
+ azPortalSignins = materialize(SigninLogs\\n| where TimeGenerated >= ago(lookBack)\\n//
+ Azure Portal only\\n| where AppDisplayName =~ \\\"Azure Portal\\\")\\n;\\nlet
+ successPortalSignins = azPortalSignins\\n| where TimeGenerated >= ago(timeRange)\\n//
+ Azure Portal only and exclude non-failure Result Types\\n| where ResultType
+ in (\\\"0\\\", \\\"50125\\\", \\\"50140\\\")\\n// Tagging identities not resolved
+ to friendly names\\n//| extend Unresolved = iff(Identity matches regex isGUID,
+ true, false)\\n| distinct TimeGenerated, UserPrincipalName, Id, ResultType\\n;\\nlet
+ failPortalSignins = azPortalSignins\\n| where TimeGenerated >= ago(timeRange)\\n//
+ Azure Portal only and exclude non-failure Result Types\\n| where ResultType
+ !in (\\\"0\\\", \\\"50125\\\", \\\"50140\\\")\\n// Tagging identities not
+ resolved to friendly names\\n| extend Unresolved = iff(Identity matches regex
+ isGUID, true, false)\\n;\\n// Verify there is no success for the same connection
+ attempt after the fail\\nlet failnoSuccess = failPortalSignins | join kind=
+ leftouter (\\n successPortalSignins \\n) on UserPrincipalName, Id\\n| where
+ TimeGenerated > TimeGenerated1\\n| project-away TimeGenerated1, UserPrincipalName1,
+ Id1, ResultType1\\n;\\n// Lookup up resolved identities from last 7 days\\nlet
+ identityLookup = azPortalSignins\\n| where TimeGenerated >= ago(lookBack)\\n|
+ where not(Identity matches regex isGUID)\\n| summarize by UserId, lu_UserDisplayName
+ = UserDisplayName, lu_UserPrincipalName = UserPrincipalName;\\n// Join resolved
+ names to unresolved list from portal signins\\nlet unresolvedNames = failnoSuccess
+ | where Unresolved == true | join kind= inner (\\n identityLookup \\n) on
+ UserId\\n| extend UserDisplayName = lu_UserDisplayName, UserPrincipalName
+ = lu_UserPrincipalName\\n| project-away lu_UserDisplayName, lu_UserPrincipalName;\\n//
+ Join Signins that had resolved names with list of unresolved that now have
+ a resolved name\\nlet u_azPortalSignins = failnoSuccess | where Unresolved
+ == false | union unresolvedNames;\\nu_azPortalSignins\\n| extend Status =
+ strcat(ResultType, \\\": \\\", ResultDescription), OS = tostring(DeviceDetail.operatingSystem),
+ Browser = tostring(DeviceDetail.browser)\\n| extend FullLocation = strcat(Location,'|',
+ LocationDetails.state, '|', LocationDetails.city)\\n| summarize TimeGenerated
+ = makelist(TimeGenerated), Status = makelist(Status), IPAddresses = makelist(IPAddress),
+ IPAddressCount = dcount(IPAddress), FailedLogonCount = count()\\nby UserPrincipalName,
+ UserId, UserDisplayName, AppDisplayName, Browser, OS, FullLocation\\n| mvexpand
+ TimeGenerated, IPAddresses, Status\\n| extend TimeGenerated = todatetime(tostring(TimeGenerated)),
+ IPAddress = tostring(IPAddresses), Status = tostring(Status)\\n| project-away
+ IPAddresses\\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated)
+ by UserPrincipalName, UserId, UserDisplayName, Status, FailedLogonCount, IPAddress,
+ IPAddressCount, AppDisplayName, Browser, OS, FullLocation\\n| where (IPAddressCount
+ >= threshold_IPAddressCount and FailedLogonCount >= threshold_Failed) or FailedLogonCount
+ >= threshold_FailedwithSingleIP\\n| extend timestamp = StartTime, AccountCustomEntity
+ = UserPrincipalName, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ login attempts to Azure Portal\",\"description\":\"Identifies failed login
+ attempts in the Azure Active Directory SigninLogs to the Azure Portal. Many
+ failed logon \\nattempts or some failed logon attempts from multiple IPs could
+ indicate a potential brute force attack. \\nThe following are excluded due
+ to success and non-failure results:\\nReferences: https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes\\n0
+ - successful logon\\n50125 - Sign-in was interrupted due to a password reset
+ or password registration entry.\\n50140 - This error occurred due to 'Keep
+ me signed in' interrupt when the user was signing-in.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-11T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/80da0a8f-cfe1-4cd0-a895-8bc1771a720e\",\"name\":\"80da0a8f-cfe1-4cd0-a895-8bc1771a720e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where EventID == 1102 and EventSourceName == \\\"Microsoft-Windows-Eventlog\\\"
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ EventCount = count() by Computer, Account, EventID, Activity\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = Account, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Security
+ Event log cleared\",\"description\":\"Checks for event id 1102 which indicates
+ the security event log was cleared. \\nIt uses Event Source Name \\\"Microsoft-Windows-Eventlog\\\"
+ to avoid generating false positives from other sources, like AD FS servers
+ for instance.\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2019-02-22T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7cb8f77d-c52f-4e46-b82f-3cf2e106224a\",\"name\":\"7cb8f77d-c52f-4e46-b82f-3cf2e106224a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ lookBack_long = 14d;\\nlet lookBack_med = 7d;\\nlet lookBack = 1d;\\nSigninLogs\\n|
+ where TimeGenerated >= startofday(ago(lookBack_long))\\n| extend locationString
+ = strcat(tostring(LocationDetails[\\\"countryOrRegion\\\"]), \\\"/\\\", tostring(LocationDetails[\\\"state\\\"]),
+ \\\"/\\\", tostring(LocationDetails[\\\"city\\\"]), \\\";\\\") \\n| project
+ TimeGenerated, AppDisplayName , UserPrincipalName, locationString \\n// Create
+ time series \\n| make-series dLocationCount = dcount(locationString) on TimeGenerated
+ in range(startofday(ago(lookBack_long)),now(), 1d) \\nby UserPrincipalName,
+ AppDisplayName \\n// Compute best fit line for each entry \\n| extend (RSquare,Slope,Variance,RVariance,Interception,LineFit)=series_fit_line(dLocationCount)
+ \\n// Chart the 3 most interesting lines \\n// A 0-value slope corresponds
+ to an account being completely stable over time for a given Azure Active Directory
+ application\\n| where Slope > 0.3\\n| top 50 by Slope desc\\n| join kind =
+ leftsemi (\\nSigninLogs\\n| where TimeGenerated >= startofday(ago(lookBack_med))\\n|
+ extend locationString = strcat(tostring(LocationDetails[\\\"countryOrRegion\\\"]),
+ \\\"/\\\", tostring(LocationDetails[\\\"state\\\"]), \\\"/\\\", tostring(LocationDetails[\\\"city\\\"]),
+ \\\";\\\") \\n| project TimeGenerated, AppDisplayName , UserPrincipalName,
+ locationString \\n| make-series dLocationCount = dcount(locationString) on
+ TimeGenerated in range(startofday(ago(lookBack_med)) ,now(), 1d) \\nby UserPrincipalName,
+ AppDisplayName \\n| extend (RSquare,Slope,Variance,RVariance,Interception,LineFit)=series_fit_line(dLocationCount)
+ \\n| top 50 by Slope desc\\n| where Slope > 0.3\\n) on UserPrincipalName,
+ AppDisplayName\\n| join kind = leftsemi (\\nSigninLogs\\n| where TimeGenerated
+ >= startofday(ago(lookBack))\\n| extend locationString = strcat(tostring(LocationDetails[\\\"countryOrRegion\\\"]),
+ \\\"/\\\", tostring(LocationDetails[\\\"state\\\"]), \\\"/\\\", tostring(LocationDetails[\\\"city\\\"]),
+ \\\";\\\") \\n| project TimeGenerated, AppDisplayName , UserPrincipalName,
+ locationString \\n| make-series dLocationCount = dcount(locationString) on
+ TimeGenerated in range(startofday(ago(lookBack)) ,now(), 1d) \\nby UserPrincipalName,
+ AppDisplayName \\n| extend (RSquare,Slope,Variance,RVariance,Interception,LineFit)=series_fit_line(dLocationCount)
+ \\n| top 50 by Slope desc\\n// Higher threshold requirement on last day anomaly\\n|
+ where Slope > 5\\n) on UserPrincipalName, AppDisplayName\\n| extend timestamp
+ = TimeGenerated, AccountCustomEntity = UserPrincipalName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Anomalous
+ sign-in location by user account and authenticating application\",\"description\":\"This
+ query over Azure Active Directory sign-in considers all user sign-ins for
+ each Azure Active \\nDirectory application and picks out the most anomalous
+ change in location profile for a user within an \\nindividual application.
+ An alert is generated for recent sign-ins that have location counts that are
+ anomalous\\nover last day but also over the last 7-day and 14-day periods.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-02-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ec21493c-2684-4acd-9bc2-696dbad72426\",\"name\":\"ec21493c-2684-4acd-9bc2-696dbad72426\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\n//Create a list of TLDs in our
+ threat feed for later validation of extracted domains\\nlet list_tlds = ThreatIntelligenceIndicator\\n
+ \ | where TimeGenerated > ago(ioc_lookBack)\\n | where isnotempty(DomainName)\\n
+ \ | extend DomainName = tolower(DomainName)\\n | extend parts = split(DomainName,
+ '.')\\n | extend tld = parts[(array_length(parts)-1)]\\n | summarize
+ count() by tostring(tld)\\n | summarize make_list(tld);\\n ThreatIntelligenceIndicator\\n
+ \ | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n
+ \ | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n
+ \ | where Active == true\\n // Picking up only IOC's that contain the
+ entities we want\\n | where isnotempty(DomainName)\\n | join (\\n CommonSecurityLog\\n
+ \ | extend IngestionTime = ingestion_time()\\n | where IngestionTime
+ > ago(dt_lookBack)\\n | where DeviceVendor =~ 'Palo Alto Networks'\\n
+ \ | where DeviceEventClassID =~ 'url'\\n //Uncomment the line
+ below to only alert on allowed connections\\n //| where DeviceAction
+ !~ \\\"block-url\\\"\\n //Extract domain from RequestURL, if not present
+ extarct it from AdditionalExtentions\\n | extend PA_Url = columnifexists(\\\"RequestURL\\\",
+ \\\"None\\\")\\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions
+ !startswith \\\"PanOS\\\", extract(\\\"([^\\\\\\\"]+)\\\", 1, tolower(AdditionalExtensions)),
+ trim('\\\"', PA_Url))\\n | extend PA_Url = iif(PA_Url !startswith \\\"http://\\\"
+ and ApplicationProtocol !~ \\\"ssl\\\", strcat('http://', PA_Url), iif(PA_Url
+ !startswith \\\"https://\\\" and ApplicationProtocol =~ \\\"ssl\\\", strcat('https://',
+ PA_Url), PA_Url))\\n | extend Domain = trim(@\\\"\\\"\\\"\\\",tostring(parse_url(PA_Url).Host))\\n
+ \ | where isnotempty(Domain)\\n | extend Domain = tolower(Domain)\\n
+ \ | extend parts = split(Domain, '.')\\n //Split out the TLD
+ for the purpose of checking if we have any TI indicators with this TLD to
+ match on\\n | extend tld = parts[(array_length(parts)-1)]\\n //Validate
+ parsed domain by checking TLD against TLDs from threat feed and drop domains
+ where there is no chance of a match\\n | where tld in~ (list_tlds)\\n
+ \ | extend CSL_TimeGenerated = TimeGenerated\\n ) on $left.DomainName==$right.Domain\\n
+ \ | project LatestIndicatorTime, Description, ActivityGroupNames, PA_Url,
+ Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, CSL_TimeGenerated,
+ DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort,
+ ApplicationProtocol, RequestMethod\\n | extend timestamp = CSL_TimeGenerated,
+ IPCustomEntity = SourceIP, HostCustomEntity = DeviceName, URLCustomEntity
+ = PA_Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Domain entity to PaloAlto\",\"description\":\"Identifies a match in
+ Palo Alto data in CommonSecurityLog table from any Domain IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/28b42356-45af-40a6-a0b4-a554cdfd5d8a\",\"name\":\"28b42356-45af-40a6-a0b4-a554cdfd5d8a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ failureCountThreshold = 5;\\nlet successCountThreshold = 1;\\nlet timeRange
+ = 1d;\\nlet authenticationWindow = 20m;\\nSigninLogs\\n| where TimeGenerated
+ >= ago(timeRange)\\n| extend OS = DeviceDetail.operatingSystem, Browser =
+ DeviceDetail.browser\\n| extend StatusCode = tostring(Status.errorCode), StatusDetails
+ = tostring(Status.additionalDetails)\\n| extend State = tostring(LocationDetails.state),
+ City = tostring(LocationDetails.city)\\n| where AppDisplayName contains \\\"Azure
+ Portal\\\"\\n// Split out failure versus non-failure types\\n| extend FailureOrSuccess
+ = iff(ResultType in (\\\"0\\\", \\\"50125\\\", \\\"50140\\\", \\\"70043\\\",
+ \\\"70044\\\"), \\\"Success\\\", \\\"Failure\\\")\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), IPAddress = makeset(IPAddress),
+ makeset(OS), makeset(Browser), makeset(City), \\nmakeset(ResultType), FailureCount
+ = countif(FailureOrSuccess==\\\"Failure\\\"), SuccessCount = countif(FailureOrSuccess==\\\"Success\\\")
+ \\nby bin(TimeGenerated, authenticationWindow), UserDisplayName, UserPrincipalName,
+ AppDisplayName\\n| where FailureCount >= failureCountThreshold and SuccessCount
+ >= successCountThreshold\\n| mvexpand IPAddress\\n| extend IPAddress = tostring(IPAddress)\\n|
+ extend timestamp = StartTimeUtc, AccountCustomEntity = UserPrincipalName,
+ IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Brute
+ force attack against Azure Portal\",\"description\":\"Identifies evidence
+ of brute force activity against Azure Portal by highlighting multiple authentication
+ failures \\nand by a successful authentication within a given time window.
+ \\n(The query does not enforce any sequence - eg requiring the successful
+ authentication to occur last.)\\nDefault Failure count is 5, Default Success
+ count is 1 and default Time Window is 20 minutes.\\nReferences: https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-04-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a9956d3a-07a9-44a6-a279-081a85020cae\",\"name\":\"a9956d3a-07a9-44a6-a279-081a85020cae\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 15;\\nlet rejectedAccess = SymantecVIP\\n|
+ where TimeGenerated > timeframe\\n| where isnotempty(RADIUSAuth)\\n| where
+ RADIUSAuth =~ \\\"Reject\\\"\\n| summarize Total = count() by ClientIP, bin(TimeGenerated,
+ 15m)\\n| where Total > threshold\\n| project ClientIP;\\nSymantecVIP\\n| where
+ TimeGenerated > timeframe\\n| where isnotempty(RADIUSAuth)\\n| where RADIUSAuth
+ =~ \\\"Reject\\\"\\n| join kind=inner rejectedAccess() on ClientIP\\n| summarize
+ StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), count() by ClientIP,
+ User\\n| extend timestamp = StartTime, IPCustomEntity = ClientIP, AccountCustomEntity
+ = User\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"ClientDeniedAccess\",\"description\":\"Creates
+ an incident in the event a Client has an excessive amounts of denied access
+ requests.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SymantecVIP\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a7564d76-ec6b-4519-a66b-fcc80c42332b\",\"name\":\"a7564d76-ec6b-4519-a66b-fcc80c42332b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1h;\\nlet WellKnownLocalSID = \\\"S-1-5-32-5[0-9][0-9]$\\\";\\nlet
+ WellKnownGroupSID = \\\"S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-498$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1000$\\\";\\nlet
+ GroupAddition = SecurityEvent \\n| where TimeGenerated > ago(timeframe)\\n//
+ 4728 - A member was added to a security-enabled global group\\n// 4732 - A
+ member was added to a security-enabled local group\\n// 4756 - A member was
+ added to a security-enabled universal group \\n| where EventID in (\\\"4728\\\",
+ \\\"4732\\\", \\\"4756\\\") \\n| where AccountType =~ \\\"User\\\" and MemberName
+ == \\\"-\\\"\\n// Exclude Remote Desktop Users group: S-1-5-32-555\\n| where
+ TargetSid !in (\\\"S-1-5-32-555\\\")\\n| where TargetSid matches regex WellKnownLocalSID
+ or TargetSid matches regex WellKnownGroupSID\\n| project GroupAddTime = TimeGenerated,
+ GroupAddEventID = EventID, GroupAddActivity = Activity, GroupAddComputer =
+ Computer, \\nGroupAddTargetUserName = TargetUserName, GroupAddTargetDomainName
+ = TargetDomainName, GroupAddTargetSid = TargetSid, \\nGroupAddSubjectUserName
+ = SubjectUserName, GroupAddSubjectUserSid = SubjectUserSid, GroupSid = MemberSid;\\nlet
+ GroupCreated = SecurityEvent\\n| where TimeGenerated > ago(timeframe)\\n//
+ 4727 - A security-enabled global group was created\\n// 4731 - A security-enabled
+ local group was created\\n// 4754 - A security-enabled universal group was
+ created\\n| where EventID in (\\\"4727\\\", \\\"4731\\\", \\\"4754\\\")\\n|
+ where AccountType =~ \\\"User\\\"\\n| project GroupCreateTime = TimeGenerated,
+ GroupCreateEventID = EventID, GroupCreateActivity = Activity, GroupCreateComputer
+ = Computer, \\nGroupCreateTargetUserName = TargetUserName, GroupCreateTargetDomainName
+ = TargetDomainName, GroupCreateSubjectUserName = SubjectUserName, \\nGroupCreateSubjectDomainName
+ = SubjectDomainName, GroupCreateSubjectUserSid = SubjectUserSid, GroupSid
+ = TargetSid;\\nGroupCreated\\n| join (\\nGroupAddition\\n) on GroupSid \\n|
+ extend timestamp = GroupCreateTime, AccountCustomEntity = GroupCreateSubjectUserName,
+ HostCustomEntity = GroupCreateComputer\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Group
+ added to built in domain local or global group\",\"description\":\"Identifies
+ when a recently created Group was added to a privileged built in domain local
+ group or global group such as the \\nEnterprise Admins, Cert Publishers or
+ DnsAdmins. Be sure to verify this is an expected addition.\\nReferences:
+ For AD SID mappings - https://docs.microsoft.com/windows/security/identity-protection/access-control/active-directory-security-groups.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0914adab-90b5-47a3-a79f-7cdcac843aa7\",\"name\":\"0914adab-90b5-47a3-a79f-7cdcac843aa7\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 14d;\\nlet timeframe = 1d;\\nlet scorethreshold = 3;\\nlet baselinethreshold
+ = 5;\\nlet OperationList = dynamic(\\n[\\\"SecretGet\\\", \\\"KeyGet\\\",
+ \\\"VaultGet\\\"]);\\nlet TimeSeriesData = AzureDiagnostics\\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(now()))\\n| extend ResultType
+ = columnifexists(\\\"ResultType\\\", \\\"None\\\"), CallerIPAddress = columnifexists(\\\"CallerIPAddress\\\",
+ \\\"None\\\")\\n| where ResultType !~ \\\"None\\\" and isnotempty(ResultType)\\n|
+ where CallerIPAddress !~ \\\"None\\\" and isnotempty(CallerIPAddress)\\n|
+ where ResourceType =~ \\\"VAULTS\\\" and ResultType =~ \\\"Success\\\"\\n|
+ where OperationName in (OperationList) \\n| project TimeGenerated, OperationName,
+ Resource, CallerIPAddress \\n| make-series HourlyCount=count() on TimeGenerated
+ from startofday(ago(starttime)) to startofday(now()) step timeframe by Resource;\\n//Filter
+ anomolies against TimeSeriesData\\nlet TimeSeriesAlerts = TimeSeriesData\\n|
+ extend (anomalies, score, baseline) = series_decompose_anomalies(HourlyCount,
+ scorethreshold, -1, 'linefit')\\n| mv-expand HourlyCount to typeof(double),
+ TimeGenerated to typeof(datetime), anomalies to typeof(double),score to typeof(double),
+ baseline to typeof(long)\\n| where anomalies > 0 | extend AnomalyHour = TimeGenerated\\n|
+ where baseline > baselinethreshold // Filtering low count events per baselinethreshold\\n|
+ project Resource, AnomalyHour, TimeGenerated, HourlyCount, baseline, anomalies,
+ score;\\n// Filter the alerts since specified timeframe\\nTimeSeriesAlerts\\n|
+ where TimeGenerated > ago(timeframe)\\n// Join against base logs since specified
+ timeframe to retrive records associated with the hour of anomoly\\n| join
+ (\\nAzureDiagnostics\\n| where TimeGenerated > ago(timeframe)\\n| extend ResultType
+ = columnifexists(\\\"ResultType\\\", \\\"NoResultType\\\")\\n| extend requestUri_s
+ = columnifexists(\\\"requestUri_s\\\", \\\"None\\\"), identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ = columnifexists(\\\"identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\\\",
+ \\\"None\\\")\\n| extend id_s = columnifexists(\\\"id_s\\\", \\\"None\\\"),
+ CallerIPAddress = columnifexists(\\\"CallerIPAddress\\\", \\\"None\\\"), clientInfo_s
+ = columnifexists(\\\"clientInfo_s\\\", \\\"None\\\")\\n| where ResultType
+ !~ \\\"None\\\" and isnotempty(ResultType)\\n| where identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ !~ \\\"None\\\" and isnotempty(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g)\\n|
+ where id_s !~ \\\"None\\\" and isnotempty(id_s)\\n| where CallerIPAddress
+ !~ \\\"None\\\" and isnotempty(CallerIPAddress)\\n| where clientInfo_s !~
+ \\\"None\\\" and isnotempty(clientInfo_s)\\n| where requestUri_s !~ \\\"None\\\"
+ and isnotempty(requestUri_s)\\n| where ResourceType =~ \\\"VAULTS\\\" and
+ ResultType =~ \\\"Success\\\"\\n| where OperationName in (OperationList) \\n|
+ summarize PerOperationCount=count(), LatestAnomalyTime = arg_max(TimeGenerated,*)
+ by bin(TimeGenerated,1h), Resource, OperationName, id_s, CallerIPAddress,
+ identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g,
+ requestUri_s, clientInfo_s \\n) on Resource, TimeGenerated \\n| summarize
+ EventCount=count(), OperationNameList = make_set(OperationName), RequestURLList
+ = make_set(requestUri_s), AccountList = make_set(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g),
+ AccountMax = arg_max(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g,*)
+ by Resource, id_s, clientInfo_s, LatestAnomalyTime\\n| extend timestamp =
+ LatestAnomalyTime, IPCustomEntity = CallerIPAddress, AccountCustomEntity =
+ AccountMax\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Azure
+ Key Vault access TimeSeries anomaly\",\"description\":\"Indentifies a sudden
+ increase in count of Azure Key Vault secret or vault access operations by
+ CallerIPAddress. The query leverages a built-in KQL anomaly detection algorithm
+ \\nto find large deviations from baseline Azure Key Vault access patterns.
+ Any sudden increase in the count of Azure Key Vault accesses can be an \\nindication
+ of adversary dumping credentials via automated methods. If you are seeing
+ any noise, try filtering known source(IP/Account) and user-agent combinations.\\nTimeSeries
+ Reference Blog: https://techcommunity.microsoft.com/t5/azure-sentinel/looking-for-unknown-anomalies-what-is-normal-time-series/ba-p/555052\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-07-01T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(Keyvault)\",\"dataTypes\":[\"AzureDiagnostics\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/884c4957-70ea-4f57-80b9-1bca3890315b\",\"name\":\"884c4957-70ea-4f57-80b9-1bca3890315b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeFrame = 1d;\\nlet timeBin = 10m;\\nlet failedThreshold = 100;\\nW3CIISLog\\n|
+ where TimeGenerated >= ago(timeFrame)\\n| where scStatus in (\\\"401\\\",\\\"403\\\")\\n|
+ where csUserName != \\\"-\\\"\\n// Handling Exchange specific items in IIS
+ logs to remove the unique log identifier in the URI\\n| extend csUriQuery
+ = iff(csUriQuery startswith \\\"MailboxId=\\\", tostring(split(csUriQuery,
+ \\\"&\\\")[0]) , csUriQuery )\\n| extend csUriQuery = iff(csUriQuery startswith
+ \\\"X-ARR-CACHE-HIT=\\\", strcat(tostring(split(csUriQuery, \\\"&\\\")[0]),tostring(split(csUriQuery,
+ \\\"&\\\")[1])) , csUriQuery )\\n| extend scStatusFull = strcat(scStatus,
+ \\\".\\\",scSubStatus) \\n// Map common IIS codes\\n| extend scStatusFull_Friendly
+ = case(\\nscStatusFull == \\\"401.0\\\", \\\"Access denied.\\\",\\nscStatusFull
+ == \\\"401.1\\\", \\\"Logon failed.\\\",\\nscStatusFull == \\\"401.2\\\",
+ \\\"Logon failed due to server configuration.\\\",\\nscStatusFull == \\\"401.3\\\",
+ \\\"Unauthorized due to ACL on resource.\\\",\\nscStatusFull == \\\"401.4\\\",
+ \\\"Authorization failed by filter.\\\",\\nscStatusFull == \\\"401.5\\\",
+ \\\"Authorization failed by ISAPI/CGI application.\\\",\\nscStatusFull ==
+ \\\"403.0\\\", \\\"Forbidden.\\\",\\nscStatusFull == \\\"403.4\\\", \\\"SSL
+ required.\\\",\\n\\\"See - https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\\")\\n//
+ Mapping to Hex so can be mapped using website in comments above\\n| extend
+ scWin32Status_Hex = tohex(tolong(scWin32Status)) \\n// Map common win32 codes\\n|
+ extend scWin32Status_Friendly = case(\\nscWin32Status_Hex =~ \\\"775\\\",
+ \\\"The referenced account is currently locked out and cannot be logged on
+ to.\\\",\\nscWin32Status_Hex =~ \\\"52e\\\", \\\"Logon failure: Unknown user
+ name or bad password.\\\",\\nscWin32Status_Hex =~ \\\"532\\\", \\\"Logon failure:
+ The specified account password has expired.\\\",\\nscWin32Status_Hex =~ \\\"533\\\",
+ \\\"Logon failure: Account currently disabled.\\\", \\nscWin32Status_Hex =~
+ \\\"2ee2\\\", \\\"The request has timed out.\\\", \\nscWin32Status_Hex =~
+ \\\"0\\\", \\\"The operation completed successfully.\\\", \\nscWin32Status_Hex
+ =~ \\\"1\\\", \\\"Incorrect function.\\\", \\nscWin32Status_Hex =~ \\\"2\\\",
+ \\\"The system cannot find the file specified.\\\", \\nscWin32Status_Hex =~
+ \\\"3\\\", \\\"The system cannot find the path specified.\\\", \\nscWin32Status_Hex
+ =~ \\\"4\\\", \\\"The system cannot open the file.\\\", \\nscWin32Status_Hex
+ =~ \\\"5\\\", \\\"Access is denied.\\\", \\nscWin32Status_Hex =~ \\\"8009030e\\\",
+ \\\"SEC_E_NO_CREDENTIALS\\\", \\nscWin32Status_Hex =~ \\\"8009030C\\\", \\\"SEC_E_LOGON_DENIED\\\",
+ \\n\\\"See - https://msdn.microsoft.com/library/cc231199.aspx\\\")\\n// decode
+ URI when available\\n| extend decodedUriQuery = url_decode(csUriQuery)\\n//
+ Count of failed logons by a user\\n| summarize makeset(decodedUriQuery), makeset(cIP),
+ makeset(sSiteName), makeset(sPort), makeset(csUserAgent), makeset(csMethod),
+ makeset(csUriQuery), makeset(scStatusFull), makeset(scStatusFull_Friendly),
+ makeset(scWin32Status_Hex), makeset(scWin32Status_Friendly), FailedConnectionsCount
+ = count() by bin(TimeGenerated, timeBin), csUserName, Computer, sIP\\n| where
+ FailedConnectionsCount >= failedThreshold\\n| project TimeGenerated, csUserName,
+ set_decodedUriQuery, Computer, set_sSiteName, sIP, set_cIP, set_sPort, set_csUserAgent,
+ set_csMethod, set_scStatusFull, set_scStatusFull_Friendly, set_scWin32Status_Hex,
+ set_scWin32Status_Friendly, FailedConnectionsCount\\n| order by FailedConnectionsCount\\n|
+ extend timestamp = TimeGenerated, AccountCustomEntity = csUserName, HostCustomEntity
+ = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"High
+ count of failed logons by a user\",\"description\":\"Identifies when 100 or
+ more failed attempts by a given user in 10 minutes occur on the IIS Server.\\nThis
+ could be indicative of attempted brute force based on known account information.\\nThis
+ could also simply indicate a misconfigured service or device. \\nReferences:\\nIIS
+ status code mapping - https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\nWin32
+ Status code mapping - https://msdn.microsoft.com/library/cc231199.aspx\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-03-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/8b8aec75-dc5e-4661-bc0c-9e4fff6aad02\",\"name\":\"8b8aec75-dc5e-4661-bc0c-9e4fff6aad02\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Anomaly\",\"properties\":{\"severity\":\"High\",\"anomalyDefinitionVersion\":\"1.0.0\",\"techniques\":[\"T1027\"],\"customizableObservations\":{\"multiSelectObservations\":[{\"supportedValues\":[\"Highly
+ Confidential to Confidential\",\"Highly Confidential to General\",\"Highly
+ Confidential to Public\",\"Highly Confidential to Archive\",\"Confidential
+ to General\",\"Confidential to Public\",\"Confidential to Archive\",\"General
+ to Public\",\"General to Archive\",\"Public to Archive\"],\"values\":[\"Highly
+ Confidential to General\",\"Highly Confidential to Public\",\"Highly Confidential
+ to Archive\"],\"supportedValuesKql\":null,\"valuesKql\":null,\"name\":\"Document
+ sensitivity label change\",\"description\":\"Sensitivity labels are security
+ settings that have been automatically or manually applied to your files.\\nSometimes
+ it is normal to change the labels of files.\\nChoose which label changes are
+ severe enough to generate anomalies.\\n\",\"sequenceNumber\":0,\"rerun\":\"RerunAlways\"},{\"supportedValues\":[\".doc\",\".docm\",\".docx\",\".dot\",\".dotm\",\".dotx\"],\"values\":[\".doc\",\".docx\"],\"supportedValuesKql\":null,\"valuesKql\":null,\"name\":\"Document
+ type\",\"description\":\"Choose which document types to include or exclude
+ from this rule.\",\"sequenceNumber\":0,\"rerun\":\"NotRequired\"},{\"supportedValues\":[\"Discover,
+ open, remove protection\",\"Discover, open, remove label\",\"Discover, open,
+ downgrade label\",\"Discover, remove protection\",\"Discover, remove label\",\"Discover,
+ downgrade label\"],\"values\":[\"Discover, open, remove protection\",\"Discover,
+ open, downgrade label\"],\"supportedValuesKql\":null,\"valuesKql\":null,\"name\":\"Document
+ action sequence\",\"description\":\"Document action sequence is the order
+ of events that occurred while changes were made to these files. Based on the
+ way you normally interact with your files, you may choose which actions are
+ flagged as anomalous.\\n\",\"sequenceNumber\":0,\"rerun\":\"RerunAlways\"}],\"singleSelectObservations\":[{\"supportedValues\":[\"Include\",\"Exclude\"],\"supportedValuesKql\":null,\"value\":\"Include\",\"name\":\"Private
+ IP\",\"description\":\"Private IP relates to the status of the IP address
+ where the operation occurred. Choose to either include or exclude operations
+ from Private IPs.\\n\",\"sequenceNumber\":0,\"rerun\":\"RerunAlways\"}],\"prioritizeExcludeObservations\":[{\"prioritize\":\"[60-100]\",\"exclude\":\"[200-]\",\"dataType\":\"number\",\"name\":\"Document
+ count\",\"description\":\"Document count is the number of files that were
+ involved in a particular downgrade operation. Choose a number that would indicate
+ an unusual number of files to be edited in one batch.\\nYou may *prioritize*
+ a certain range of numbers and you may *exclude* a certain range of numbers.\\n\",\"sequenceNumber\":0,\"rerun\":\"RerunAlways\"},{\"prioritize\":null,\"exclude\":\"financial,
+ $hr.+$\",\"dataType\":\"string\",\"name\":\"Document name\",\"description\":\"Choose
+ to *prioritize* or *exclude* strings that appear in the names of documents.
+ You may enter plain text and regular expressions separated by commas.\\n\",\"sequenceNumber\":0,\"rerun\":\"NotRequired\"}],\"thresholdObservations\":[{\"minimum\":\"0.3\",\"maximum\":\"1\",\"value\":\"0.3\",\"name\":\"Score\",\"description\":\"Generate
+ an anomaly when score is greater than the chosen value\",\"sequenceNumber\":0,\"rerun\":\"NotRequired\"}]},\"frequency\":\"PT2H\",\"displayName\":\"(Preview)
+ Anomalous Document Mass Downgrade\",\"description\":\"Description for Anomalous
+ mass downgrade of sensitive documents template\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-09-12T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureInformationProtection\",\"dataTypes\":[\"InformationProtectionLogs_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0558155e-4556-447e-9a22-828f2a7de06b\",\"name\":\"0558155e-4556-447e-9a22-828f2a7de06b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nProofPointTAPMessagesDelivered_CL\\n| where TimeGenerated
+ >= timeframe\\n| mv-expand todynamic(threatsInfoMap_s)\\n| mv-expand todynamic(messageParts_s)\\n|
+ extend threatType = tostring(threatsInfoMap_s.threatType), classification
+ = tostring(threatsInfoMap_s.classification)\\n| extend filename = tostring(messageParts_s.filename)\\n|
+ where threatType =~ \\\"attachment\\\" and classification =~ \\\"malware\\\"\\n|
+ summarize filenames = make_set(filename), StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated), count() by TimeGenerated, Sender = sender_s,
+ SenderIPAddress = senderIP_s, Recipient = recipient_s, threatType, classification,
+ \ Subject = subject_s\\n| extend timestamp = StartTime, AccountCustomEntity
+ = Recipient, IPCustomEntity = SenderIPAddress\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malware
+ attachment delivered\",\"description\":\"This query identifies a message containing
+ a malware attachment that was delivered.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ProofpointTAP\",\"dataTypes\":[\"ProofPointTAPMessagesDelivered_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/32555639-b639-4c2b-afda-c0ae0abefa55\",\"name\":\"32555639-b639-4c2b-afda-c0ae0abefa55\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nAWSCloudTrail\\n| where TimeGenerated > ago(timeframe)\\n|
+ where EventName =~ \\\"GetCallerIdentity\\\" and UserIdentityType =~ \\\"AssumedRole\\\"
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by SourceIpAddress, EventName, EventTypeName, UserIdentityType, UserIdentityAccountId,
+ UserIdentityPrincipalid, \\nUserAgent, UserIdentityUserName, SessionMfaAuthenticated,AWSRegion,
+ EventSource, AdditionalEventData, ResponseElements\\n| extend timestamp =
+ StartTimeUtc, AccountCustomEntity = UserIdentityUserName, IPCustomEntity =
+ SourceIpAddress\\n| sort by EndTimeUtc desc nulls last\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Monitor
+ AWS Credential abuse or hijacking\",\"description\":\"Looking for GetCallerIdentity
+ Events where the UserID Type is AssumedRole \\nAn attacker who has assumed
+ the role of a legitimate account can call the GetCallerIdentity function to
+ determine what account they are using.\\nA legitimate user using legitimate
+ credentials would not need to call GetCallerIdentity since they should already
+ know what account they are using.\\nMore Information: https://duo.com/decipher/trailblazer-hunts-compromised-credentials-in-aws\\nAWS
+ STS GetCallerIdentity API: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
+ \",\"tactics\":[\"Discovery\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/57e56fc9-417a-4f41-a579-5475aea7b8ce\",\"name\":\"57e56fc9-417a-4f41-a579-5475aea7b8ce\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1h;\\nlet threshold = 1000;\\nInfobloxNIOS\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where ProcessName =~ \\\"dhcpd\\\" and Log_Type =~ \\\"DHCPREQUEST\\\"\\n|
+ summarize count() by ServerIP, bin(TimeGenerated,5m)\\n| where count_ > threshold\\n|
+ join kind=inner (InfobloxNIOS\\n | where ProcessName =~ \\\"dhcpd\\\" and
+ Log_Type =~ \\\"DHCPREQUEST\\\"\\n | where TimeGenerated >= ago(timeframe)\\n
+ \ ) on ServerIP\\n| extend timestamp = TimeGenerated, IPCustomEntity = ServerIP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Potential
+ DHCP Starvation Attack\",\"description\":\"This creates an incident in the
+ event that an excessive amount of DHCPREQUEST have been recieved by a DHCP
+ Server and could potentially be an indication of a DHCP Starvation Attack.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"InfobloxNIOS\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0d76e9cf-788d-4a69-ac7d-f234826b5bed\",\"name\":\"0d76e9cf-788d-4a69-ac7d-f234826b5bed\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nDnsEvents\\n| where TimeGenerated > ago(timeframe)\\n| where
+ Name contains \\\".\\\"\\n| where Name has_any (\\\"monerohash.com\\\", \\\"do-dear.com\\\",
+ \\\"xmrminerpro.com\\\", \\\"secumine.net\\\", \\\"xmrpool.com\\\", \\\"minexmr.org\\\",
+ \\\"hashanywhere.com\\\", \\n\\\"xmrget.com\\\", \\\"mininglottery.eu\\\",
+ \\\"minergate.com\\\", \\\"moriaxmr.com\\\", \\\"multipooler.com\\\", \\\"moneropools.com\\\",
+ \\\"xmrpool.eu\\\", \\\"coolmining.club\\\", \\n\\\"supportxmr.com\\\", \\\"minexmr.com\\\",
+ \\\"hashvault.pro\\\", \\\"xmrpool.net\\\", \\\"crypto-pool.fr\\\", \\\"xmr.pt\\\",
+ \\\"miner.rocks\\\", \\\"walpool.com\\\", \\\"herominers.com\\\", \\n\\\"gntl.co.uk\\\",
+ \\\"semipool.com\\\", \\\"coinfoundry.org\\\", \\\"cryptoknight.cc\\\", \\\"fairhash.org\\\",
+ \\\"baikalmine.com\\\", \\\"tubepool.xyz\\\", \\\"fairpool.xyz\\\", \\\"asiapool.io\\\",
+ \\n\\\"coinpoolit.webhop.me\\\", \\\"nanopool.org\\\", \\\"moneropool.com\\\",
+ \\\"miner.center\\\", \\\"prohash.net\\\", \\\"poolto.be\\\", \\\"cryptoescrow.eu\\\",
+ \\\"monerominers.net\\\", \\\"cryptonotepool.org\\\", \\n\\\"extrmepool.org\\\",
+ \\\"webcoin.me\\\", \\\"kippo.eu\\\", \\\"hashinvest.ws\\\", \\\"monero.farm\\\",
+ \\\"supportxmr.com\\\", \\\"xmrpool.eu\\\", \\\"linux-repository-updates.com\\\",
+ \\\"1gh.com\\\", \\n\\\"dwarfpool.com\\\", \\\"hash-to-coins.com\\\", \\\"hashvault.pro\\\",
+ \\\"pool-proxy.com\\\", \\\"hashfor.cash\\\", \\\"fairpool.cloud\\\", \\\"litecoinpool.org\\\",
+ \\\"mineshaft.ml\\\", \\\"abcxyz.stream\\\", \\n\\\"moneropool.ru\\\", \\\"cryptonotepool.org.uk\\\",
+ \\\"extremepool.org\\\", \\\"extremehash.com\\\", \\\"hashinvest.net\\\",
+ \\\"unipool.pro\\\", \\\"crypto-pools.org\\\", \\\"monero.net\\\", \\n\\\"backup-pool.com\\\",
+ \\\"mooo.com\\\", \\\"freeyy.me\\\", \\\"cryptonight.net\\\", \\\"shscrypto.net\\\")\\n|
+ extend timestamp = TimeGenerated, IPCustomEntity = ClientIP, HostCustomEntity
+ = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"DNS
+ events related to mining pools\",\"description\":\"Identifies IP addresses
+ that may be performing DNS lookups associated with common currency mining
+ pools.\",\"tactics\":[\"Execution\",\"Impact\"],\"createdDateUTC\":\"2019-02-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/30fa312c-31eb-43d8-b0cc-bcbdfb360822\",\"name\":\"30fa312c-31eb-43d8-b0cc-bcbdfb360822\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n SigninLogs | where TimeGenerated
+ >= ago(dt_lookBack) and isnotempty(UserPrincipalName)\\n //Normalizing
+ the column to lower case for exact match with EmailRecipient column\\n |
+ extend UserPrincipalName = tolower(UserPrincipalName)\\n | where UserPrincipalName
+ matches regex emailregex\\n | extend StatusCode = tostring(Status.errorCode),
+ StatusDetails = tostring(Status.additionalDetails)\\n | extend Region =
+ tostring(LocationDetails[\\\"countryOrRegion\\\"]), State = tostring(LocationDetails[\\\"state\\\"]),
+ City = tostring(LocationDetails[\\\"city\\\"])\\n // renaming timestamp
+ column so it is clear the log this came from SigninLogs table\\n | extend
+ SigninLogs_TimeGenerated = TimeGenerated\\n)\\non $left.EmailRecipient ==
+ $right.UserPrincipalName\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, SigninLogs_TimeGenerated,\\nEmailSenderName,
+ EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType,
+ IPAddress, UserPrincipalName, AppDisplayName,\\nStatusCode, StatusDetails,
+ NetworkIP, NetworkDestinationIP, NetworkSourceIP\\n| extend timestamp = SigninLogs_TimeGenerated,
+ AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress, URLCustomEntity
+ = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to SigninLogs\",\"description\":\"Identifies a match in
+ SigninLogs table from any Email IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f30a47c1-65fb-42b1-a7f4-00941c12550b\",\"name\":\"f30a47c1-65fb-42b1-a7f4-00941c12550b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(Url)\\n| join (\\n SecurityAlert\\n | where
+ TimeGenerated >= ago(dt_lookBack)\\n // Extract URL from JSON data\\n |
+ extend Url = extract(\\\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\\\\\(\\\\\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)\\\",
+ 1,Entities)\\n // We only want alerts that actually contain URL data\\n |
+ where isnotempty(Url)\\n // Extract hostname from JSON data for entity mapping\\n
+ \ | extend Compromised_Host = tostring(parse_json(ExtendedProperties).[\\\"Compromised
+ Host\\\"])\\n | extend Alert_TimeGenerated = TimeGenerated\\n) on Url\\n|
+ summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n|
+ project LatestIndicatorTime, ActivityGroupNames, IndicatorId, ThreatType,
+ ExpirationDateTime, ConfidenceScore, Alert_TimeGenerated,\\nAlertName, AlertSeverity,
+ Description, Url, Compromised_Host\\n| extend timestamp = Alert_TimeGenerated,
+ HostCustomEntity = Compromised_Host, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map URL entity to SecurityAlert data\",\"description\":\"Identifies a match
+ in SecurityAlert data from any URL IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"MicrosoftCloudAppSecurity\",\"dataTypes\":[\"SecurityAlert\"]},{\"connectorId\":\"AzureSecurityCenter\",\"dataTypes\":[\"SecurityAlert\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/e1ce0eab-10d1-4aae-863f-9a383345ba88\",\"name\":\"e1ce0eab-10d1-4aae-863f-9a383345ba88\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet threshold = 15;\\nSyslog\\n| where TimeGenerated >=
+ ago(timeframe)\\n| where SyslogMessage contains \\\"Failed password for invalid
+ user\\\"\\n| where ProcessName =~ \\\"sshd\\\" \\n| parse kind=relaxed SyslogMessage
+ with * \\\"invalid user\\\" user \\\" from \\\" ip \\\" port\\\" port \\\"
+ ssh2\\\"\\n| project user, ip, port, SyslogMessage, EventTime\\n| summarize
+ EventTimes = make_list(EventTime), PerHourCount = count() by ip, bin(EventTime,
+ 4h), user\\n| where PerHourCount > threshold\\n| mvexpand EventTimes\\n| extend
+ EventTimes = tostring(EventTimes) \\n| summarize StartTimeUtc = min(EventTimes),
+ EndTimeUtc = max(EventTimes), UserList = makeset(user), sum(PerHourCount)
+ by IPAddress = ip\\n| extend UserList = tostring(UserList) \\n| extend timestamp
+ = StartTimeUtc, IPCustomEntity = IPAddress, AccountCustomEntity = UserList\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"SSH
+ - Potential Brute Force\",\"description\":\"Identifies an IP address that
+ had 15 failed attempts to sign in via SSH in a 4 hour block during a 24 hour
+ time period.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ca67c83e-7fff-4127-a3e3-1af66d6d4cad\",\"name\":\"ca67c83e-7fff-4127-a3e3-1af66d6d4cad\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet ProcessCreationEvents=() {\\nlet processEvents=SecurityEvent\\n|
+ where EventID==4688\\n| where isnotempty(CommandLine)\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer,
+ Account = SubjectUserName, AccountDomain = SubjectDomainName,\\nFileName =
+ Process, CommandLine, ParentProcessName;\\nprocessEvents};\\nProcessCreationEvents\\n|
+ where CommandLine contains \\\"TVqQAAMAAAAEAAA\\\"\\n| where StartTimeUtc
+ >= ago(timeframe)\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Account, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Base64
+ encoded Windows process command-lines\",\"description\":\"Identifies instances
+ of a base64 encoded PE file header seen in the process command line parameter.\",\"tactics\":[\"Execution\",\"DefenseEvasion\"],\"createdDateUTC\":\"2018-09-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/5d33fc63-b83b-4913-b95e-94d13f0d379f\",\"name\":\"5d33fc63-b83b-4913-b95e-94d13f0d379f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet fileHashIndicators = ThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n| where isnotempty(FileHashValue);\\n// Handle matches
+ against both lower case and uppercase versions of the hash:\\n( fileHashIndicators
+ | extend FileHashValue = tolower(FileHashValue)\\n |union (fileHashIndicators
+ | extend FileHashValue = toupper(FileHashValue)))\\n| join (\\n CommonSecurityLog
+ | where TimeGenerated >= ago(dt_lookBack)\\n | where isnotempty(FileHash)\\n
+ \ | extend CommonSecurityLog_TimeGenerated = TimeGenerated\\n)\\non $left.FileHashValue
+ == $right.FileHash\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\\nCommonSecurityLog_TimeGenerated,
+ SourceIP, SourcePort, DestinationIP, DestinationPort, SourceUserID, SourceUserName,
+ DeviceName, DeviceAction,\\nRequestURL, DestinationUserName, DestinationUserID,
+ ApplicationProtocol, Activity\\n| extend timestamp = CommonSecurityLog_TimeGenerated,
+ IPCustomEntity = SourceIP, HostCustomEntity = DeviceName, AccountCustomEntity
+ = SourceUserName, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map File Hash to CommonSecurityLog Event\",\"description\":\"Identifies
+ a match in CommonSecurityLog Event data from any FileHash IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-30T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f948a32f-226c-4116-bddd-d95e91d97eb9\",\"name\":\"f948a32f-226c-4116-bddd-d95e91d97eb9\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ detectionTime = 1d;\\nlet joinLookback = 14d;\\nAuditLogs\\n| where TimeGenerated
+ > ago(detectionTime)\\n| where LoggedByService =~ \\\"Core Directory\\\"\\n|
+ where Category =~ \\\"ApplicationManagement\\\"\\n| where OperationName =~
+ \\\"Consent to application\\\"\\n| where TargetResources has \\\"mailboxsettings\\\"\\n|
+ extend AppDisplayName = TargetResources.[0].displayName\\n| extend AppClientId
+ = tolower(TargetResources.[0].id)\\n| where AppClientId !in ((externaldata(knownAppClientId:string,
+ knownAppDisplayName:string)[@\\\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.OAuth.KnownApplications.csv\\\"]
+ with (format=\\\"csv\\\")))\\n| extend ConsentFull = TargetResources[0].modifiedProperties[4].newValue\\n|
+ parse ConsentFull with * \\\"ConsentType: \\\" GrantConsentType \\\", Scope:
+ \\\" GrantScope1 \\\"]\\\" *\\n| where ConsentFull contains \\\"contacts.read\\\"
+ and ConsentFull contains \\\"user.read\\\" and ConsentFull contains \\\"mail.read\\\"
+ and ConsentFull contains \\\"notes.read.all\\\" and ConsentFull contains \\\"mailboxsettings.readwrite\\\"
+ and ConsentFull contains \\\"Files.ReadWrite.All\\\"\\n| where GrantConsentType
+ != \\\"AllPrincipals\\\" // NOTE: we are ignoring if OAuth application was
+ granted to all users via an admin - but admin due diligence should be audited
+ occasionally\\n| extend GrantIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress),
+ InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)\\n| extend GrantInitiatedBy
+ = iff(isnotempty(InitiatedBy.user.userPrincipalName),InitiatedBy.user.userPrincipalName,
+ InitiatedBy.app.displayName)\\n| extend GrantUserAgent = iff(AdditionalDetails[0].key
+ =~ \\\"User-Agent\\\", AdditionalDetails[0].value, \\\"\\\")\\n| project TimeGenerated,
+ GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName, GrantIpAddress,
+ GrantUserAgent, AppClientId, OperationName, ConsentFull, CorrelationId\\n|
+ join kind = leftouter (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add service principal\\\"\\n| extend AppClientId
+ = tolower(TargetResources[0].id)\\n| extend AppReplyURLs = iff(TargetResources[0].modifiedProperties[1].newValue
+ has \\\"AddressType\\\", TargetResources[0].modifiedProperties[1].newValue,
+ \\\"\\\")\\n| distinct AppClientId, tostring(AppReplyURLs)\\n)\\non AppClientId\\n|
+ join kind = innerunique (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add OAuth2PermissionGrant\\\" or OperationName
+ =~ \\\"Add delegated permission grant\\\"\\n| extend GrantAuthentication =
+ tostring(TargetResources[0].displayName)\\n| extend GrantOperation = OperationName\\n|
+ project GrantAuthentication, GrantOperation, CorrelationId\\n) on CorrelationId\\n|
+ project TimeGenerated, GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName,
+ AppReplyURLs, GrantIpAddress, GrantUserAgent, AppClientId, GrantAuthentication,
+ OperationName, GrantOperation, CorrelationId, ConsentFull\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ application consent similar to O365 Attack Toolkit\",\"description\":\"This
+ will alert when a user consents to provide a previously-unknown Azure application
+ with the same OAuth permissions used by the MDSec O365 Attack Toolkit (https://github.com/mdsecactivebreach/o365-attack-toolkit).\\nThe
+ default permissions/scope for the MDSec O365 Attack toolkit are contacts.read,
+ user.read, mail.read, notes.read.all, mailboxsettings.readwrite, and files.readwrite.all.\\nConsent
+ to applications with these permissions should be rare, especially as the knownApplications
+ list is expanded, especially as the knownApplications list is expanded. Public
+ contributions to expand this filter are welcome!\\nFor further information
+ on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.\",\"tactics\":[\"CredentialAccess\",\"DefenseEvasion\"],\"createdDateUTC\":\"2020-06-26T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/9f86885f-f31f-4e66-a39d-352771ee789e\",\"name\":\"9f86885f-f31f-4e66-a39d-352771ee789e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nCarbonBlackEvents_CL\\n| where TimeGenerated > timeframe\\n|
+ extend eventTime = datetime(1970-01-01) + tolong(eventTime_d/1000) * 1sec\\n|
+ where targetApp_effectiveReputation_s =~ \\\"KNOWN_MALWARE\\\"\\n| summarize
+ StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), count() by eventTime,
+ deviceDetails_deviceName_s, deviceDetails_deviceIpAddress_s, processDetails_fullUserName_s,
+ processDetails_targetName_s\\n| extend timestamp = StartTime, AccountCustomEntity
+ = processDetails_fullUserName_s, HostCustomEntity = deviceDetails_deviceName_s,
+ IPCustomEntity = deviceDetails_deviceIpAddress_s\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ Malware Detected\",\"description\":\"This creates an incident when a known
+ Malware is detected on a endpoint managed by a Carbon Black.\",\"tactics\":[\"Execution\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"VMwareCarbonBlack\",\"dataTypes\":[\"CarbonBlackEvents_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a357535e-f722-4afe-b375-cff362b2b376\",\"name\":\"a357535e-f722-4afe-b375-cff362b2b376\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ endtime = 1d;\\n(union isfuzzy=true\\n(OfficeActivity | where TimeGenerated
+ >= ago(endtime) | where UserAgent != \\\"\\\"),\\n(OfficeActivity\\n| where
+ TimeGenerated >= ago(endtime)\\n| where RecordType in (\\\"AzureActiveDirectoryAccountLogon\\\",
+ \\\"AzureActiveDirectoryStsLogon\\\")\\n| extend OperationName = Operation,
+ UserAgent = extractjson(\\\"$[0].Value\\\", ExtendedProperties, typeof(string))),\\n(AzureDiagnostics\\n|
+ where TimeGenerated >= ago(endtime)\\n| where ResourceType =~ \\\"APPLICATIONGATEWAYS\\\"
+ \\n| where OperationName =~ \\\"ApplicationGatewayAccess\\\" \\n| extend ClientIP
+ = columnifexists(\\\"clientIP_s\\\", \\\"None\\\"), UserAgent = columnifexists(\\\"userAgent_s\\\",
+ \\\"None\\\")))\\n// Likely artefact of hardcoding\\n| where UserAgent startswith
+ \\\"User\\\" or UserAgent startswith \\\"\\\\\\\"\\\"\\n// Incorrect casing\\nor
+ (UserAgent startswith \\\"Mozilla\\\" and not(UserAgent containscs \\\"Mozilla\\\"))\\n//
+ Incorrect casing\\nor UserAgent containscs \\\"(Compatible;\\\"\\n// Missing
+ MSIE version\\nor UserAgent matches regex @\\\"MSIE\\\\s?;\\\"\\n// Incorrect
+ spacing around MSIE version\\nor UserAgent matches regex @\\\"MSIE(?:\\\\d|.{1,5}?\\\\d\\\\s;)\\\"\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ OperationNames = makeset(OperationName), UserAgentCount = dcount(UserAgent),
+ \\nUserAgentList = makeset(UserAgent), RecordTypes = makeset(RecordType) by
+ UserId, ClientIP\\n| extend timestamp = StartTimeUtc, IPCustomEntity = ClientIP,
+ AccountCustomEntity = UserId\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malformed
+ user agent\",\"description\":\"Malware authors will sometimes hardcode user
+ agent string values when writing the network communication component of their
+ malware.\\nMalformed user agents can be an indication of such malware.\",\"tactics\":[\"InitialAccess\",\"CommandAndControl\",\"Execution\"],\"createdDateUTC\":\"2019-01-25T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"WAF\",\"dataTypes\":[\"AzureDiagnostics\"]},{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/155f40c6-610d-497d-85fc-3cf06ec13256\",\"name\":\"155f40c6-610d-497d-85fc-3cf06ec13256\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = dynamic([\\\"yahoo-verification.org\\\",\\\"support-servics.com\\\",\\\"verification-live.com\\\",\\\"com-mailbox.com\\\",\\\"com-myaccuants.com\\\",\\\"notification-accountservice.com\\\",\\n\\\"accounts-web-mail.com\\\",\\\"customer-certificate.com\\\",\\\"session-users-activities.com\\\",\\\"user-profile-credentials.com\\\",\\\"verify-linke.com\\\",\\\"support-servics.net\\\",\\\"verify-linkedin.net\\\",
+ \\n\\\"yahoo-verification.net\\\",\\\"yahoo-verify.net\\\",\\\"outlook-verify.net\\\",\\\"com-users.net\\\",\\\"verifiy-account.net\\\",\\\"te1egram.net\\\",\\\"account-verifiy.net\\\",\\\"myaccount-services.net\\\",\\n\\\"com-identifier-servicelog.name\\\",\\\"microsoft-update.bid\\\",\\\"outlook-livecom.bid\\\",\\\"update-microsoft.bid\\\",\\\"documentsfilesharing.cloud\\\",\\\"com-microsoftonline.club\\\",\\n\\\"confirm-session-identifier.info\\\",\\\"session-management.info\\\",\\\"confirmation-service.info\\\",\\\"document-share.info\\\",\\\"broadcast-news.info\\\",\\\"customize-identity.info\\\",\\\"webemail.info\\\",\\n\\\"com-identifier-servicelog.info\\\",\\\"documentsharing.info\\\",\\\"notification-accountservice.info\\\",\\\"identifier-activities.info\\\",\\\"documentofficupdate.info\\\",\\\"recoveryusercustomer.info\\\",\\n\\\"serverbroadcast.info\\\",\\\"account-profile-users.info\\\",\\\"account-service-management.info\\\",\\\"accounts-manager.info\\\",\\\"activity-confirmation-service.info\\\",\\\"com-accountidentifier.info\\\",\\n\\\"com-privacy-help.info\\\",\\\"com-sessionidentifier.info\\\",\\\"com-useraccount.info\\\",\\\"confirmation-users-service.info\\\",\\\"confirm-identity.info\\\",\\\"confirm-session-identification.info\\\",\\n\\\"continue-session-identifier.info\\\",\\\"customer-recovery.info\\\",\\\"customers-activities.info\\\",\\\"elitemaildelivery.info\\\",\\\"email-delivery.info\\\",\\\"identify-user-session.info\\\",\\n\\\"message-serviceprovider.info\\\",\\\"notificationapp.info\\\",\\\"notification-manager.info\\\",\\\"recognized-activity.info\\\",\\\"recover-customers-service.info\\\",\\\"recovery-session-change.info\\\",\\n\\\"service-recovery-session.info\\\",\\\"service-session-continue.info\\\",\\\"session-mail-customers.info\\\",\\\"session-managment.info\\\",\\\"session-verify-user.info\\\",\\\"shop-sellwear.info\\\",\\n\\\"supportmailservice.info\\\",\\\"terms-service-notification.info\\\",\\\"user-activity-issues.info\\\",\\\"useridentity-confirm.info\\\",\\\"users-issue-services.info\\\",\\\"verify-user-session.info\\\",\\n\\\"login-gov.info\\\",\\\"notification-signal-agnecy.info\\\",\\\"notifications-center.info\\\",\\\"identifier-services-sessions.info\\\",\\\"customers-manager.info\\\",\\\"session-manager.info\\\",\\n\\\"customer-managers.info\\\",\\\"confirmation-recovery-options.info\\\",\\\"service-session-confirm.info\\\",\\\"session-recovery-options.info\\\",\\\"services-session-confirmation.info\\\",\\n\\\"notification-managers.info\\\",\\\"activities-services-notification.info\\\",\\\"activities-recovery-options.info\\\",\\\"activity-session-recovery.info\\\",\\\"customers-services.info\\\",\\n\\\"sessions-notification.info\\\",\\\"download-teamspeak.info\\\",\\\"services-issue-notification.info\\\",\\\"microsoft-upgrade.mobi\\\",\\\"broadcastnews.pro\\\",\\\"mobile-messengerplus.network\\\"]);\\nlet
+ IPList = dynamic([\\\"51.91.200.147\\\"]);\\nlet IPRegex = '[0-9]{1,3}\\\\\\\\.[0-9]{1,3}\\\\\\\\.[0-9]{1,3}\\\\\\\\.[0-9]{1,3}';\\n(union
+ isfuzzy=true\\n(CommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)\\n|
+ parse Message with * '(' DNSName ')' * \\n| extend MessageIP = extract(IPRegex,
+ 0, Message)\\n| extend RequestURLIP = extract(IPRegex, 0, Message)\\n| where
+ (isnotempty(SourceIP) and SourceIP in (IPList)) or (isnotempty(DestinationIP)
+ and DestinationIP in (IPList)) \\nor (isnotempty(DNSName) and DNSName in~
+ (DomainNames)) or (isnotempty(DestinationHostName) and DestinationHostName
+ in~ (DomainNames)) or (isnotempty(RequestURL) and (RequestURL has_any (DomainNames)
+ or RequestURLIP in (IPList))) \\nor (isnotempty(Message) and MessageIP in
+ (IPList))\\n| extend IPMatch = case(SourceIP in (IPList), \\\"SourceIP\\\",
+ DestinationIP in (IPList), \\\"DestinationIP\\\", MessageIP in (IPList), \\\"Message\\\",
+ RequestURLIP in (IPList), \\\"RequestUrl\\\", \\\"NoMatch\\\") \\n| extend
+ timestamp = TimeGenerated , IPCustomEntity = case(IPMatch == \\\"SourceIP\\\",
+ SourceIP, IPMatch == \\\"DestinationIP\\\", DestinationIP,IPMatch == \\\"Message\\\",
+ MessageIP,\\nIPMatch == \\\"RequestUrl\\\", RequestURLIP,\\\"NoMatch\\\"),
+ Account = SourceUserID, Host = DeviceName\\n),\\n(DnsEvents \\n| where TimeGenerated
+ >= ago(timeframe) \\n| extend DestinationIPAddress = IPAddresses, DNSName
+ = Name, Host = Computer\\n| where DestinationIPAddress in (IPList) or DNSName
+ in~ (DomainNames) \\n| extend timestamp = TimeGenerated, IPCustomEntity =
+ DestinationIPAddress, HostCustomEntity = Host),\\n(VMConnection \\n| where
+ TimeGenerated >= ago(timeframe) \\n| parse RemoteDnsCanonicalNames with *
+ '[\\\"' DNSName '\\\"]' *\\n| where isnotempty(SourceIP) or isnotempty(DestinationIP)
+ or isnotempty(DNSName)\\n| where SourceIP in (IPList) or DestinationIP in
+ (IPList) or DNSName in~ (DomainNames)\\n| extend IPMatch = case( SourceIP
+ in (IPList), \\\"SourceIP\\\", DestinationIP in (IPList), \\\"DestinationIP\\\",
+ \\\"None\\\") \\n| extend timestamp = TimeGenerated , IPCustomEntity = case(IPMatch
+ == \\\"SourceIP\\\", SourceIP, IPMatch == \\\"DestinationIP\\\", DestinationIP,
+ \\\"None\\\"), Host = Computer),\\n(OfficeActivity\\n| where TimeGenerated
+ >= ago(timeframe)\\n| extend SourceIPAddress = ClientIP, Account = UserId\\n|
+ where SourceIPAddress in (IPList)\\n| extend timestamp = TimeGenerated ,
+ IPCustomEntity = SourceIPAddress , AccountCustomEntity = Account )\\n)\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ Phosphorus group domains/IP\",\"description\":\"Matches domain name IOCs related
+ to Phosphorus group activity with CommonSecurityLog, DnsEvents, OfficeActivity
+ and VMConnection dataTypes.\\nReferences: https://blogs.microsoft.com/on-the-issues/2019/03/27/new-steps-to-protect-customers-from-hacking/.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-10-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/c7bfadd4-34a6-4fa5-82f8-3691a32261e8\",\"name\":\"c7bfadd4-34a6-4fa5-82f8-3691a32261e8\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet EventNameList = dynamic([\\\"ApplySecurityGroupsToLoadBalancer\\\",
+ \\\"SetSecurityGroups\\\"]);\\nAWSCloudTrail\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where EventName in~ (EventNameList)\\n| extend User = iif(isnotempty(UserIdentityUserName),
+ UserIdentityUserName, SessionIssuerUserName)\\n| summarize EventCount=count(),
+ StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) \\nby EventSource,
+ EventName, UserIdentityType, User, SourceIpAddress, UserAgent, SessionMfaAuthenticated,
+ AWSRegion,\\nAdditionalEventData, UserIdentityAccountId, UserIdentityPrincipalid,
+ ResponseElements\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = User , IPCustomEntity = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Changes
+ to AWS Elastic Load Balancer security groups\",\"description\":\"Elastic Load
+ Balancer distributes incoming traffic across multiple instances in multiple
+ availability Zones. This increases the fault tolerance of your applications.
+ \\n Unwanted changes to Elastic Load Balancer specific security groups could
+ open your environment to attack and hence needs monitoring.\\n More information:
+ https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255
+ \\n and https://aws.amazon.com/elasticloadbalancing/.\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a22740ec-fc1e-4c91-8de6-c29c6450ad00\",\"name\":\"a22740ec-fc1e-4c91-8de6-c29c6450ad00\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"SigninLogs\\n|
+ where ResultType == 500121\\n| where Status has \\\"MFA Denied; user declined
+ the authentication\\\"\\n| extend AccountCustomEntity = AlternateSignInName\\n|
+ extend IPCustomEntity = IPAddress\\n| extend URLCustomEntity = ClientAppUsed\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Explicit
+ MFA Deny\",\"description\":\"User explicitly denies MFA push, indicating that
+ login was not expected and the account's password may be compromised.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-10-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3af9285d-bb98-4a35-ad29-5ea39ba0c628\",\"name\":\"3af9285d-bb98-4a35-ad29-5ea39ba0c628\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeRange = ago(1d);\\nlet threshold = 1;\\nSigninLogs\\n| where TimeGenerated
+ >= timeRange\\n| where ConditionalAccessStatus == 1 or ConditionalAccessStatus
+ =~ \\\"failure\\\"\\n| extend OS = DeviceDetail.operatingSystem, Browser =
+ DeviceDetail.browser \\n| extend StatusCode = tostring(Status.errorCode),
+ StatusDetails = tostring(Status.additionalDetails)\\n| extend ConditionalAccessPol0Name
+ = tostring(ConditionalAccessPolicies[0].displayName)\\n| extend ConditionalAccessPol1Name
+ = tostring(ConditionalAccessPolicies[1].displayName)\\n| extend ConditionalAccessPol2Name
+ = tostring(ConditionalAccessPolicies[2].displayName)\\n| extend Status = strcat(StatusCode,
+ \\\": \\\", ResultDescription) \\n| summarize StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated), Status = makelist(Status), StatusDetails
+ = makelist(StatusDetails), IPAddresses = makelist(IPAddress), IPAddressCount
+ = dcount(IPAddress) , CorrelationIds = makelist(CorrelationId) by UserPrincipalName,
+ AppDisplayName, tostring(Browser), tostring(OS), Location, ConditionalAccessPol0Name,
+ ConditionalAccessPol1Name, ConditionalAccessPol2Name\\n| where IPAddressCount
+ > threshold and StatusDetails !has \\\"MFA successfully completed\\\"\\n|
+ mvexpand IPAddresses, Status, StatusDetails, CorrelationIds\\n| extend Status
+ = strcat(Status, \\\" \\\", StatusDetails)\\n| summarize IPAddresses = makeset(IPAddresses),
+ Status = makeset(Status), CorrelationIds = makeset(CorrelationIds) by StartTimeUtc,
+ EndTimeUtc, UserPrincipalName, AppDisplayName, tostring(Browser), tostring(OS),
+ Location, ConditionalAccessPol0Name, ConditionalAccessPol1Name, ConditionalAccessPol2Name,
+ IPAddressCount\\n| extend timestamp = StartTimeUtc, AccountCustomEntity =
+ UserPrincipalName, IPCustomEntity = tostring(IPAddresses)\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Attempt
+ to bypass conditional access rule in Azure AD\",\"description\":\"Identifies
+ an attempt to Bypass conditional access rule(s) in Azure Active Directory.\\nThe
+ ConditionalAccessStatus column value details if there was an attempt to bypass
+ Conditional Access\\nor if the Conditional access rule was not satisfied (ConditionalAccessStatus
+ == 1).\\nReferences: \\nhttps://docs.microsoft.com/azure/active-directory/conditional-access/overview\\nhttps://docs.microsoft.com/azure/active-directory/reports-monitoring/concept-sign-ins\\nhttps://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes\\nConditionalAccessStatus
+ == 0 // Success\\nConditionalAccessStatus == 1 // Failure\\nConditionalAccessStatus
+ == 2 // Not Applied\\nConditionalAccessStatus == 3 // unknown\",\"tactics\":[\"InitialAccess\",\"Persistence\"],\"createdDateUTC\":\"2019-02-11T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/173f8699-6af5-484a-8b06-8c47ba89b380\",\"name\":\"173f8699-6af5-484a-8b06-8c47ba89b380\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"//
+ Adjust this value to change how many Teams should be deleted before including\\nlet
+ max_delete_count = 3;\\n// Adjust this value to change the timewindow the
+ query runs over\\n OfficeActivity\\n| where OfficeWorkload =~ \\\"MicrosoftTeams\\\"
+ \\n| where Operation =~ \\\"TeamDeleted\\\"\\n| summarize StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated), DeletedTeams = make_set(TeamName) by UserId\\n|
+ where array_length(DeletedTeams) > max_delete_count\\n| extend timestamp =
+ StartTime, AccountCustomEntity = UserId\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Multiple
+ Teams deleted by a single user\",\"description\":\"This detection flags the
+ occurrences of deleting multiple teams within an hour.\\nThis data is a part
+ of Office 365 Connector in Azure Sentinel.\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2020-09-13T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity
+ (Teams)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a83ef0f4-dace-4767-bce3-ebd32599d2a0\",\"name\":\"a83ef0f4-dace-4767-bce3-ebd32599d2a0\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nDnsEvents\\n| where TimeGenerated > ago(timeframe)\\n| where
+ Name contains \\\".\\\"\\n| where Name has_any (\\\"tor2web.org\\\", \\\"tor2web.com\\\",
+ \\\"torlink.co\\\", \\\"onion.to\\\", \\\"onion.ink\\\", \\\"onion.cab\\\",
+ \\\"onion.nu\\\", \\\"onion.link\\\", \\n\\\"onion.it\\\", \\\"onion.city\\\",
+ \\\"onion.direct\\\", \\\"onion.top\\\", \\\"onion.casa\\\", \\\"onion.plus\\\",
+ \\\"onion.rip\\\", \\\"onion.dog\\\", \\\"tor2web.fi\\\", \\n\\\"tor2web.blutmagie.de\\\",
+ \\\"onion.sh\\\", \\\"onion.lu\\\", \\\"onion.pet\\\", \\\"t2w.pw\\\", \\\"tor2web.ae.org\\\",
+ \\\"tor2web.io\\\", \\\"tor2web.xyz\\\", \\\"onion.lt\\\", \\n\\\"s1.tor-gateways.de\\\",
+ \\\"s2.tor-gateways.de\\\", \\\"s3.tor-gateways.de\\\", \\\"s4.tor-gateways.de\\\",
+ \\\"s5.tor-gateways.de\\\", \\\"hiddenservice.net\\\")\\n| extend timestamp
+ = TimeGenerated, IPCustomEntity = ClientIP, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"DNS
+ events related to ToR proxies\",\"description\":\"Identifies IP addresses
+ performing DNS lookups associated with common ToR proxies.\",\"tactics\":[\"Exfiltration\"],\"createdDateUTC\":\"2019-02-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a2e36ce0-da4d-4b6e-88c6-4e40161c5bfc\",\"name\":\"a2e36ce0-da4d-4b6e-88c6-4e40161c5bfc\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n SecurityAlert | where TimeGenerated
+ >= ago(dt_lookBack)\\n // Converting Entities into dynamic data type and
+ use mv-expand to unpack the array\\n | extend EntitiesDynamicArray = parse_json(Entities)
+ | mv-expand EntitiesDynamicArray\\n // Parsing relevant entity column to
+ filter type account and creating new column by combining account and UPNSuffix\\n
+ \ | extend Entitytype = tostring(parse_json(EntitiesDynamicArray).Type),
+ EntityName = tostring(parse_json(EntitiesDynamicArray).Name),\\n EntityUPNSuffix
+ = tostring(parse_json(EntitiesDynamicArray).UPNSuffix)\\n | where Entitytype
+ =~ \\\"account\\\"\\n | extend EntityEmail = tolower(strcat(EntityName,
+ \\\"@\\\", EntityUPNSuffix))\\n | where EntityEmail matches regex emailregex\\n
+ \ | extend SecurityAlert_TimeGenerated = TimeGenerated\\n)\\non $left.EmailRecipient
+ == $right.EntityEmail\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, SecurityAlert_TimeGenerated,\\nEmailSenderName,
+ EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType,
+ EntityEmail, AlertName, AlertType,\\nAlertSeverity, Entities, ProviderName,
+ VendorName\\n| extend timestamp = SecurityAlert_TimeGenerated, AccountCustomEntity
+ = EntityEmail, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to SecurityAlert\",\"description\":\"Identifies a match
+ in SecurityAlert table from any Email IOC from TI which will extend coverage
+ to datatypes such as MCAS, StorageThreatProtection and many others\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureSecurityCenter\",\"dataTypes\":[\"SecurityAlert\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/fa118b98-de46-4e94-87f9-8e6d5060b60b\",\"name\":\"fa118b98-de46-4e94-87f9-8e6d5060b60b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MLBehaviorAnalytics\",\"properties\":{\"severity\":\"Medium\",\"displayName\":\"(Preview)
+ Anomalous SSH Login Detection\",\"description\":\"This detection uses machine
+ learning (ML) to identify anomalous Secure Shell (SSH) login activity, based
+ on syslog data. Scenarios include:\\n\\n*\\tUnusual IP - This IP address has
+ not or has rarely been seen in last 30 days.\\n*\\tUnusual Geo - The IP address,
+ city, country and ASN have not (or rarely) been seen in last 30 days.\\n*\\tNew
+ user - A new user logs in from an IP address and geo location, both or either
+ of which are not expected to be seen in the last 30 days.\\n\\nAllow 7 days
+ after this alert is enabled for Azure Sentinel to build a profile of normal
+ activity for your environment.\\n\\nThis detection requires a specific configuration
+ of the data source. [Learn more](https://docs.microsoft.com/en-us/azure/sentinel/connect-syslog#configure-the-syslog-connector-for-anomalous-ssh-login-detection)\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-08-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a0907abe-6925-4d90-af2b-c7e89dc201a6\",\"name\":\"a0907abe-6925-4d90-af2b-c7e89dc201a6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 10d;\\nlet endtime = 1d;\\nlet threshold = 100;\\nlet nxDomainDnsEvents
+ = DnsEvents \\n| where ResultCode == 3 \\n| where QueryType in (\\\"A\\\",
+ \\\"AAAA\\\")\\n| where ipv4_is_match(\\\"127.0.0.1\\\", ClientIP) == False\\n|
+ where Name !contains \\\"/\\\"\\n| where Name contains \\\".\\\";\\nnxDomainDnsEvents\\n|
+ where TimeGenerated > ago(endtime)\\n| extend sld = tostring(split(Name, \\\".\\\")[-2])\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ dcount(sld) by ClientIP\\n| where dcount_sld > threshold\\n// Filter out previously
+ seen IPs\\n| join kind=leftanti (nxDomainDnsEvents\\n | where TimeGenerated
+ between(ago(starttime)..ago(endtime))\\n | extend sld = tostring(split(Name,
+ \\\".\\\")[-2])\\n | summarize dcount(sld) by ClientIP\\n | where dcount_sld
+ > threshold ) on ClientIP\\n// Pull out sample NXDomain responses for those
+ remaining potentially infected IPs\\n| join kind = inner (nxDomainDnsEvents
+ | summarize by Name, ClientIP) on ClientIP\\n| summarize StartTimeUtc = min(StartTimeUtc),
+ EndTimeUtc = max(EndTimeUtc), sampleNXDomainList=make_list(Name, 100) by
+ ClientIP, dcount_sld\\n| extend timestamp = StartTimeUtc, IPCustomEntity =
+ ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P10D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Potential
+ DGA detected\",\"description\":\"Identifies clients with a high NXDomain count
+ which could be indicative of a DGA (cycling through possible C2 domains\\nwhere
+ most C2s are not live). Alert is generated when a new IP address is seen (based
+ on not being seen associated with \\nNXDomain records in prior 10-day baseline
+ period).\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-02-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/79f29feb-6a9d-4cdf-baaa-2daf480a5da1\",\"name\":\"79f29feb-6a9d-4cdf-baaa-2daf480a5da1\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1h;\\nlet last1h = CommonSecurityLog \\n| where TimeGenerated
+ >= ago(timeframe)\\n| where isempty(CommunicationDirection) \\n| where DeviceEventClassID
+ == \\\"733100\\\"\\n| extend SourceOfDropRateCount = tostring(split(tostring(split(Message,
+ \\\"]\\\")[0]),\\\"[ \\\")[1])\\n| extend splitMessage = split(Message, \\\".\\\")\\n|
+ extend DropRate = tostring(split(tostring(splitMessage[0]),\\\"] \\\")[1])\\n|
+ extend CurrentBurstRate = split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[0]),\\\"is \\\")\\n| extend CurrentBurstRatePerSec = toint(split(tostring(CurrentBurstRate[1]),\\\"
+ \\\")[0])\\n| extend MaxConfiguredBurstRate = toint(CurrentBurstRate[2])\\n|
+ extend CurrentAvgRate = split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[1]),\\\"is \\\")\\n| extend CurrentAvgRatePerSec = toint(split(tostring(CurrentAvgRate[1]),\\\"
+ \\\")[0])\\n| extend MaxConfiguredAvgRate = toint(CurrentAvgRate[2])\\n| extend
+ CumulativeTotal = toint(split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[2]),\\\"is \\\")[1])\\n| summarize last1hCumTotal = sum(CumulativeTotal),
+ last1hAvgRatePerSec = avg(CurrentAvgRatePerSec), last1hAvgBurstRatePerSec
+ = avg(CurrentBurstRatePerSec) by DeviceName, DeviceEventClassID, SourceIP,
+ SourceOfDropRateCount, DropRate;\\nlet prev6h = CommonSecurityLog \\n| where
+ TimeGenerated between (ago(6h) .. ago(1h))\\n| where isempty(CommunicationDirection)
+ \\n| where DeviceEventClassID == \\\"733100\\\"\\n| extend SourceOfDropRateCount
+ = tostring(split(tostring(split(Message, \\\"]\\\")[0]),\\\"[ \\\")[1])\\n|
+ extend splitMessage = split(Message, \\\".\\\")\\n| extend DropRate = tostring(split(tostring(splitMessage[0]),\\\"]
+ \\\")[1])\\n| extend CurrentBurstRate = split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[0]),\\\"is \\\")\\n| extend prevCurrentBurstRatePerSec = toint(split(tostring(CurrentBurstRate[1]),\\\"
+ \\\")[0])\\n| extend prevMaxConfiguredBurstRate = toint(CurrentBurstRate[2])\\n|
+ extend CurrentAvgRate = split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[1]),\\\"is \\\")\\n| extend prevCurrentAvgRatePerSec = toint(split(tostring(CurrentAvgRate[1]),\\\"
+ \\\")[0])\\n| extend prevMaxConfiguredAvgRate = toint(CurrentAvgRate[2])\\n|
+ extend prevCumulativeTotal = toint(split(tostring(split(tostring(splitMessage[1]),\\\"
+ \ \\\")[2]),\\\"is \\\")[1])\\n| summarize StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated), prev6hCumTotal = sum(prevCumulativeTotal),
+ prev6hAvgRatePerSec = avg(prevCurrentAvgRatePerSec), prev6hAvgBurstRatePerSec
+ = avg(prevCurrentBurstRatePerSec) \\nby DeviceName, DeviceEventClassID, SourceIP,
+ SourceOfDropRateCount, DropRate;\\nlast1h | join (\\n prev6h \\n) on DeviceName,
+ DeviceEventClassID, SourceIP, SourceOfDropRateCount, DropRate\\n| project
+ StartTimeUtc, EndTimeUtc, DeviceName, DeviceEventClassID, SourceIP, SourceOfDropRateCount,
+ DropRate, last1hCumTotal, prev6hCumTotal, prev6hAvgCumTotal = prev6hCumTotal/6,
+ last1hAvgRatePerSec, prev6hAvgRatePerSec, last1hAvgBurstRatePerSec, prev6hAvgBurstRatePerSec\\n//
+ Select only events that indicate a doubling of the expected rate in the last
+ hour over the previous 6 hours\\n| where last1hCumTotal > 2*prev6hAvgCumTotal
+ or last1hAvgRatePerSec > 2*prev6hAvgRatePerSec or last1hAvgBurstRatePerSec
+ > 2*prev6hAvgBurstRatePerSec\\n| extend timestamp = StartTimeUtc, IPCustomEntity
+ = SourceIP, HostCustomEntity = DeviceName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT6H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Cisco
+ ASA - average attack detection rate increase\",\"description\":\"This will
+ help you determine if Cisco ASA devices are under heavier attack than normal
+ over the last hour versus the previous 6 hours based on DeviceEventClassID
+ 733100\\nReferences: https://www.cisco.com/c/en/us/td/docs/security/asa/syslog/b_syslog/syslogs9.html\\nDetails
+ on how to further troubleshoot/investigate: https://www.cisco.com/c/en/us/support/docs/security/asa-5500-x-series-next-generation-firewalls/113685-asa-threat-detection.html\",\"tactics\":[\"Discovery\",\"Impact\"],\"createdDateUTC\":\"2019-02-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/500415fb-bba7-4227-a08a-9857fb61b6a7\",\"name\":\"500415fb-bba7-4227-a08a-9857fb61b6a7\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nOfficeActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where OfficeWorkload == \\\"Exchange\\\"\\n| where Operation in~ (\\\"New-TransportRule\\\",
+ \\\"Set-TransportRule\\\")\\n| extend p = parse_json(Parameters)\\n| extend
+ RuleName = case(\\n Operation =~ \\\"Set-TransportRule\\\", tostring(OfficeObjectId),\\n
+ \ Operation =~ \\\"New-TransportRule\\\", tostring(p[1].Value),\\n \\\"Unknown\\\"\\n
+ \ ) \\n| mvexpand p\\n| where (p.Name =~ \\\"BlindCopyTo\\\" or p.Name =~
+ \\\"RedirectMessageTo\\\") and isnotempty(p.Value)\\n| extend RedirectTo =
+ p.Value\\n| extend ClientIPOnly = case( \\n ClientIP has \\\".\\\" and ClientIP
+ has \\\":\\\", tostring(split(ClientIP,\\\":\\\")[0]), \\n ClientIP has \\\".\\\"
+ and ClientIP has \\\"-\\\", tostring(split(ClientIP,\\\"-\\\")[0]), \\n ClientIP
+ has \\\"[\\\", tostring(trim_start(@'[[]',tostring(split(ClientIP,\\\"]\\\")[0]))),\\n
+ \ ClientIP\\n ) \\n| extend Port = case(\\n ClientIP has \\\".\\\" and
+ ClientIP has \\\":\\\", (split(ClientIP,\\\":\\\")[1]),\\n ClientIP has \\\".\\\"
+ and ClientIP has \\\"-\\\", (split(ClientIP,\\\"-\\\")[1]),\\n ClientIP has
+ \\\"[\\\" and ClientIP has \\\":\\\", tostring(split(ClientIP,\\\"]:\\\")[1]),\\n
+ \ ClientIP has \\\"[\\\" and ClientIP has \\\"-\\\", tostring(split(ClientIP,\\\"]-\\\")[1]),\\n
+ \ ClientIP\\n )\\n| extend ClientIP = ClientIPOnly\\n| project TimeGenerated,
+ RedirectTo, ClientIP, Port, UserId, Operation, RuleName\\n| extend timestamp
+ = TimeGenerated, AccountCustomEntity = UserId, IPCustomEntity = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Mail
+ redirect via ExO transport rule\",\"description\":\"Identifies when Exchange
+ Online transport rule configured to forward emails.\\nThis could be an adversary
+ mailbox configured to collect mail from multiple user accounts.\",\"tactics\":[\"Collection\",\"Exfiltration\"],\"createdDateUTC\":\"2020-05-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7ee72a9e-2e54-459c-bc8a-8c08a6532a63\",\"name\":\"7ee72a9e-2e54-459c-bc8a-8c08a6532a63\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet IPList = dynamic([\\\"154.223.45.38\\\",\\\"185.141.207.140\\\",\\\"185.234.73.19\\\",\\\"216.245.210.106\\\",\\\"51.91.48.210\\\",\\\"46.255.230.229\\\"]);\\n(union
+ isfuzzy=true\\n(CommonSecurityLog\\n| where TimeGenerated >= ago(timeframe)
+ \\n| where isnotempty(SourceIP) or isnotempty(DestinationIP)\\n| where SourceIP
+ in (IPList) or DestinationIP in (IPList) or Message has_any (IPList)\\n| extend
+ IPMatch = case(SourceIP in (IPList), \\\"SourceIP\\\", DestinationIP in (IPList),
+ \\\"DestinationIP\\\", \\\"Message\\\") \\n| summarize StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated) by SourceIP, DestinationIP, DeviceProduct,
+ DeviceAction, Message, Protocol, SourcePort, DestinationPort, DeviceAddress,
+ DeviceName, IPMatch\\n| extend timestamp = StartTimeUtc, IPCustomEntity =
+ case(IPMatch == \\\"SourceIP\\\", SourceIP, IPMatch == \\\"DestinationIP\\\",
+ DestinationIP, \\\"IP in Message Field\\\") \\n),\\n(OfficeActivity\\n| where
+ TimeGenerated >= ago(timeframe) \\n|extend SourceIPAddress = ClientIP, Account
+ = UserId\\n| where SourceIPAddress in (IPList)\\n| extend timestamp = TimeGenerated
+ , IPCustomEntity = SourceIPAddress , AccountCustomEntity = Account\\n),\\n(DnsEvents
+ \\n| where TimeGenerated >= ago(timeframe) \\n| extend DestinationIPAddress
+ = IPAddresses, Host = Computer\\n| where DestinationIPAddress has_any (IPList)
+ \\n| extend timestamp = TimeGenerated, IPCustomEntity = DestinationIPAddress,
+ HostCustomEntity = Host\\n),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe)
+ \\n| where isnotempty(SourceIp) or isnotempty(DestinationIp) \\n| where SourceIp
+ in (IPList) or DestinationIp in (IPList) \\n| extend IPMatch = case( SourceIp
+ in (IPList), \\\"SourceIP\\\", DestinationIp in (IPList), \\\"DestinationIP\\\",
+ \\\"None\\\") \\n| extend timestamp = TimeGenerated , IPCustomEntity = case(IPMatch
+ == \\\"SourceIP\\\", SourceIp, IPMatch == \\\"DestinationIP\\\", DestinationIp,
+ \\\"None\\\"), Host = Computer\\n),\\n(Event\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where Source == \\\"Microsoft-Windows-Sysmon\\\"\\n| where EventID == 3\\n|
+ extend EvData = parse_xml(EventData)\\n| extend EventDetail = EvData.DataItem.EventData.Data\\n|
+ extend SourceIP = EventDetail.[9].[\\\"#text\\\"], DestinationIP = EventDetail.[14].[\\\"#text\\\"]\\n|
+ where SourceIP in (IPList) or DestinationIP in (IPList) \\n| extend IPMatch
+ = case( SourceIP in (IPList), \\\"SourceIP\\\", DestinationIP in (IPList),
+ \\\"DestinationIP\\\", \\\"None\\\") \\n| extend timestamp = TimeGenerated,
+ AccountCustomEntity = UserName, HostCustomEntity = Computer , IPCustomEntity
+ = case(IPMatch == \\\"SourceIP\\\", SourceIP, IPMatch == \\\"DestinationIP\\\",
+ DestinationIP, \\\"None\\\")\\n), \\n(WireData \\n| where TimeGenerated >=
+ ago(timeframe)\\n| where isnotempty(RemoteIP)\\n| where RemoteIP in (IPList)\\n|
+ extend timestamp = TimeGenerated, IPCustomEntity = RemoteIP, HostCustomEntity
+ = Computer\\n),\\n(SigninLogs\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where isnotempty(IPAddress)\\n| where IPAddress in (IPList)\\n| extend timestamp
+ = TimeGenerated, AccountCustomEntity = UserPrincipalName, IPCustomEntity =
+ IPAddress\\n),\\n(W3CIISLog \\n| where TimeGenerated >= ago(timeframe)\\n|
+ where isnotempty(cIP)\\n| where cIP in (IPList)\\n| extend timestamp = TimeGenerated,
+ IPCustomEntity = cIP, HostCustomEntity = Computer, AccountCustomEntity = csUserName\\n),\\n(AzureActivity
+ \\n| where TimeGenerated >= ago(timeframe)\\n| where isnotempty(CallerIpAddress)\\n|
+ where CallerIpAddress in (IPList)\\n| extend timestamp = TimeGenerated, IPCustomEntity
+ = CallerIpAddress, AccountCustomEntity = Caller\\n),\\n(\\nAWSCloudTrail\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where isnotempty(SourceIpAddress)\\n|
+ where SourceIpAddress in (IPList)\\n| extend timestamp = TimeGenerated, IPCustomEntity
+ = SourceIpAddress, AccountCustomEntity = UserIdentityUserName\\n)\\n)\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ IRIDIUM IP\",\"description\":\"IRIDIUM command and control IP. Identifies
+ a match across various data feeds for IP IOCs related to the IRIDIUM activity
+ group.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-12-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]},{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]},{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"AzureMonitor(WireData)\",\"dataTypes\":[\"WireData\"]},{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]},{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]},{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a4025a76-6490-4e6b-bb69-d02be4b03f07\",\"name\":\"a4025a76-6490-4e6b-bb69-d02be4b03f07\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n AzureNetworkAnalytics_CL\\n
+ \ | where TimeGenerated >= ago(dt_lookBack)\\n // renaming time column
+ so it is clear the log this came from\\n | extend AzureNetworkAnalytics_CL_TimeGenerated
+ = TimeGenerated\\n // NSG Flow Logs have additional information concat
+ with Public IP, removing onlp Public IP\\n | extend PIPs = split(PublicIPs_s,
+ '|', 0)\\n | extend PIP = tostring(PIPs[0])\\n)\\non $left.TI_ipEntity
+ == $right.PIP\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *)
+ by IndicatorId\\n// Set to alert on Allowed NSG Flows from TI Public IP IOC\\n|
+ where FlowStatus_s == \\\"A\\\"\\n| project LatestIndicatorTime, Description,
+ ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
+ AzureNetworkAnalytics_CL_TimeGenerated,\\nTI_ipEntity, Computer, FlowDirection_s,
+ FlowStatus_s, FlowType_s, SrcPublicIPs_s, DestPublicIPs_s, PublicIPs_s, L7Protocol_s,
+ DestPort_d, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n|
+ extend timestamp = AzureNetworkAnalytics_CL_TimeGenerated, IPCustomEntity
+ = TI_ipEntity, HostCustomEntity = Computer, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to AzureNetworkAnalytics_CL (NSG Flow Logs)\",\"description\":\"Identifies
+ a match in AzureNetworkAnalytics_CL (NSG Flow Logs) from any IP IOC from TI
+ that was Allowed\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureNetworkAnalytics_CL(NSG
+ Flow Logs)\",\"dataTypes\":[\"AzureNetworkAnalytics_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ffcd575b-3d54-482a-a6d8-d0de13b6ac63\",\"name\":\"ffcd575b-3d54-482a-a6d8-d0de13b6ac63\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n CommonSecurityLog | where TimeGenerated
+ >= ago(dt_lookBack) and isnotempty(DestinationUserID)\\n // Filtering PAN
+ Logs for specific event type to match relevant email entities\\n | where
+ DeviceVendor == \\\"Palo Alto Networks\\\" and DeviceEventClassID == \\\"wildfire\\\"
+ and ApplicationProtocol in (\\\"smtp\\\",\\\"pop3\\\")\\n | extend DestinationUserID
+ = tolower(DestinationUserID)\\n | where DestinationUserID matches regex
+ emailregex\\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\\n)\\non
+ $left.EmailRecipient == $right.DestinationUserID\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime,
+ ConfidenceScore, CommonSecurityLog_TimeGenerated,\\nEmailSenderName, EmailSourceDomain,
+ EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, DestinationUserID,
+ DeviceEventClassID, LogSeverity, DeviceAction,\\nSourceIP, SourcePort, DestinationIP,
+ DestinationPort, Protocol, ApplicationProtocol\\n| extend timestamp = CommonSecurityLog_TimeGenerated,
+ AccountCustomEntity = DestinationUserID, IPCustomEntity = SourceIP, URLCustomEntity
+ = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to CommonSecurityLog\",\"description\":\"Identifies a
+ match in CommonSecurityLog table from any Email IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/d6190dde-8fd2-456a-ac5b-0a32400b0464\",\"name\":\"d6190dde-8fd2-456a-ac5b-0a32400b0464\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet ProcessCreationEvents=() {\\nlet processEvents=SecurityEvent\\n|
+ where EventID==4688\\n| where isnotempty(CommandLine)\\n| project TimeGenerated,
+ Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, FileName
+ = Process, CommandLine, ParentProcessName;\\nprocessEvents;\\n};\\nProcessCreationEvents
+ \\n| where TimeGenerated > ago(timeframe) \\n| where CommandLine contains
+ \\\".decode('base64')\\\"\\n or CommandLine contains \\\"base64 --decode\\\"\\n
+ \ or CommandLine contains \\\".decode64(\\\" \\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), CountToday = count()
+ by Computer, Account, AccountDomain, FileName, CommandLine, ParentProcessName
+ \\n| extend timestamp = StartTimeUtc, AccountCustomEntity = Account, HostCustomEntity
+ = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Process
+ executed from binary hidden in Base64 encoded file\",\"description\":\"Encoding
+ malicious software is a technique used to obfuscate files from detection.
+ \\nThe first CommandLine component is looking for Python decoding base64.
+ \\nThe second CommandLine component is looking for Bash/sh command line base64
+ decoding.\\nThe third one is looking for Ruby decoding base64.\",\"tactics\":[\"Execution\",\"DefenseEvasion\"],\"createdDateUTC\":\"2019-01-24T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/532c1811-79ee-4d9f-8d4d-6304c840daa1\",\"name\":\"532c1811-79ee-4d9f-8d4d-6304c840daa1\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Azure
+ Active Directory Identity Protection\",\"displayName\":\"Create incidents
+ based on Azure Active Directory Identity Protection alerts\",\"description\":\"Create
+ incidents based on all alerts generated in Azure Active Directory Identity
+ Protection\",\"createdDateUTC\":\"2019-07-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectoryIdentityProtection\",\"dataTypes\":[\"SecurityAlert
+ (IPC)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2391ce61-8c8d-41ac-9723-d945b2e90720\",\"name\":\"2391ce61-8c8d-41ac-9723-d945b2e90720\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 8d;\\nlet endtime = 1d;\\nlet threshold = 0.333;\\nlet countlimit
+ = 50;\\nSecurityEvent\\n| where TimeGenerated >= ago(endtime)\\n| where EventID
+ == 4625 and AccountType =~ \\\"User\\\"\\n| where IpAddress !in (\\\"127.0.0.1\\\",
+ \\\"::1\\\")\\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated),
+ CountToday = count() by EventID, Account, LogonTypeName, SubStatus, AccountType,
+ Computer, WorkstationName, IpAddress\\n| join kind=leftouter (\\n SecurityEvent
+ \\n | where TimeGenerated between (ago(starttime) .. ago(endtime))\\n |
+ where EventID == 4625 and AccountType =~ \\\"User\\\"\\n | where IpAddress
+ !in (\\\"127.0.0.1\\\", \\\"::1\\\")\\n | summarize CountPrev7day = count()
+ by EventID, Account, LogonTypeName, SubStatus, AccountType, Computer, WorkstationName,
+ IpAddress\\n) on EventID, Account, LogonTypeName, SubStatus, AccountType,
+ Computer, WorkstationName, IpAddress\\n| where CountToday >= coalesce(CountPrev7day,0)*threshold
+ and CountToday >= countlimit\\n//SubStatus Codes are detailed here - https://docs.microsoft.com/windows/security/threat-protection/auditing/event-4625\\n|
+ extend Reason = case(\\nSubStatus =~ '0xC000005E', 'There are currently no
+ logon servers available to service the logon request.',\\nSubStatus =~ '0xC0000064',
+ 'User logon with misspelled or bad user account',\\nSubStatus =~ '0xC000006A',
+ 'User logon with misspelled or bad password', \\nSubStatus =~ '0xC000006D',
+ 'Bad user name or password',\\nSubStatus =~ '0xC000006E', 'Unknown user name
+ or bad password',\\nSubStatus =~ '0xC000006F', 'User logon outside authorized
+ hours',\\nSubStatus =~ '0xC0000070', 'User logon from unauthorized workstation',\\nSubStatus
+ =~ '0xC0000071', 'User logon with expired password',\\nSubStatus =~ '0xC0000072',
+ 'User logon to account disabled by administrator',\\nSubStatus =~ '0xC00000DC',
+ 'Indicates the Sam Server was in the wrong state to perform the desired operation',
+ \ \\nSubStatus =~ '0xC0000133', 'Clocks between DC and other computer too
+ far out of sync',\\nSubStatus =~ '0xC000015B', 'The user has not been granted
+ the requested logon type (aka logon right) at this machine',\\nSubStatus =~
+ '0xC000018C', 'The logon request failed because the trust relationship between
+ the primary domain and the trusted domain failed',\\nSubStatus =~ '0xC0000192',
+ 'An attempt was made to logon, but the Netlogon service was not started',\\nSubStatus
+ =~ '0xC0000193', 'User logon with expired account',\\nSubStatus =~ '0xC0000224',
+ 'User is required to change password at next logon',\\nSubStatus =~ '0xC0000225',
+ 'Evidently a bug in Windows and not a risk',\\nSubStatus =~ '0xC0000234',
+ 'User logon with account locked',\\nSubStatus =~ '0xC00002EE', 'Failure Reason:
+ An Error occurred during Logon',\\nSubStatus =~ '0xC0000413', 'Logon Failure:
+ The machine you are logging onto is protected by an authentication firewall.
+ The specified account is not allowed to authenticate to the machine',\\nstrcat('Unknown
+ reason substatus: ', SubStatus))\\n| extend WorkstationName = iff(WorkstationName
+ == \\\"-\\\" or isempty(WorkstationName), Computer , WorkstationName) \\n|
+ project StartTime, EndTime, EventID, Account, LogonTypeName, SubStatus, Reason,
+ AccountType, Computer, WorkstationName, IpAddress, CountToday, CountPrev7day,
+ Avg7Day = round(CountPrev7day*1.00/7,2)\\n| summarize StartTime = min(StartTime),
+ EndTime = max(EndTime), Computer = make_set(Computer,128), IpAddressList =
+ make_set(IpAddress,128), sum(CountToday), sum(CountPrev7day), avg(Avg7Day)
+ \\nby EventID, Account, LogonTypeName, SubStatus, Reason, AccountType, WorkstationName\\n|
+ order by sum_CountToday desc nulls last \\n| extend timestamp = StartTime,
+ AccountCustomEntity = Account, HostCustomEntity = WorkstationName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P8D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Excessive
+ Windows logon failures\",\"description\":\"User has over 50 Windows logon
+ failures today and at least 33% of the count of logon failures over the previous
+ 7 days.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-22T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f2dd4a3a-ebac-4994-9499-1a859938c947\",\"name\":\"f2dd4a3a-ebac-4994-9499-1a859938c947\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\nlet timeframe = 1h;\\nlet scorethreshold
+ = 5;\\nlet bytessentperhourthreshold = 10;\\nlet PrivateIPregex = @'^127\\\\.|^10\\\\.|^172\\\\.1[6-9]\\\\.|^172\\\\.2[0-9]\\\\.|^172\\\\.3[0-1]\\\\.|^192\\\\.168\\\\.';\\nlet
+ TimeSeriesData = (union isfuzzy=true\\n(\\nVMConnection\\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(ago(endtime)))\\n| where isnotempty(DestinationIP)
+ and isnotempty(SourceIP)\\n| extend DestinationIpType = iff(DestinationIp
+ matches regex PrivateIPregex,\\\"private\\\" ,\\\"public\\\" )\\n| where DestinationIpType
+ == \\\"public\\\" | extend DeviceVendor = \\\"VMConnection\\\"\\n| project
+ TimeGenerated, BytesSent, DeviceVendor\\n| make-series TotalBytesSent=sum(BytesSent)
+ on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime))
+ step timeframe by DeviceVendor\\n),\\n(\\nCommonSecurityLog \\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(ago(endtime)))\\n| where isnotempty(DestinationIP)
+ and isnotempty(SourceIP)\\n| extend DestinationIpType = iff(DestinationIP
+ matches regex PrivateIPregex,\\\"private\\\" ,\\\"public\\\" )\\n| where DestinationIpType
+ == \\\"public\\\"\\n| project TimeGenerated, SentBytes, DeviceVendor\\n| make-series
+ TotalBytesSent=sum(SentBytes) on TimeGenerated from startofday(ago(starttime))
+ to startofday(ago(endtime)) step timeframe by DeviceVendor\\n)\\n);\\n//Filter
+ anomolies against TimeSeriesData\\nlet TimeSeriesAlerts = TimeSeriesData\\n|
+ extend (anomalies, score, baseline) = series_decompose_anomalies(TotalBytesSent,
+ scorethreshold, -1, 'linefit')\\n| mv-expand TotalBytesSent to typeof(double),
+ TimeGenerated to typeof(datetime), anomalies to typeof(double),score to typeof(double),
+ baseline to typeof(long)\\n| where anomalies > 0 | extend AnomalyHour = TimeGenerated
+ \\n| extend TotalBytesSentinMBperHour = round(((TotalBytesSent / 1024)/1024),2),
+ baselinebytessentperHour = round(((baseline / 1024)/1024),2), score = round(score,2)\\n|
+ project DeviceVendor, AnomalyHour, TimeGenerated, TotalBytesSentinMBperHour,
+ baselinebytessentperHour, anomalies, score;\\n//Union of all BaseLogs aggregated
+ per hour\\nlet BaseLogs = (union isfuzzy=true\\n(\\nCommonSecurityLog \\n|
+ where isnotempty(DestinationIP) and isnotempty(SourceIP)\\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(ago(endtime))) \\n| extend
+ SentBytesinMB = ((SentBytes / 1024)/1024), ReceivedBytesinMB = ((ReceivedBytes
+ / 1024)/1024) \\n| summarize HourlyCount = count(), TimeGeneratedMax=arg_max(TimeGenerated,
+ *), DestinationIPList=make_set(DestinationIP), DestinationPortList = make_set(DestinationPort),
+ TotalSentBytesinMB = sum(SentBytesinMB), TotalReceivedBytesinMB = sum(ReceivedBytesinMB)
+ by SourceIP, DeviceVendor, TimeGeneratedHour=bin(TimeGenerated,1h)\\n| project
+ DeviceVendor, TimeGeneratedHour, TimeGeneratedMax, SourceIP, DestinationIPList,
+ DestinationPortList, TotalSentBytesinMB, TotalReceivedBytesinMB\\n| where
+ TotalSentBytesinMB > bytessentperhourthreshold\\n),\\n(\\nVMConnection \\n|
+ where isnotempty(DestinationIp) and isnotempty(SourceIp)\\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(ago(endtime))) \\n| extend
+ DeviceVendor = \\\"VMConnection\\\", SourceIP = SourceIp, DestinationIP =
+ DestinationIp\\n| extend SentBytesinMB = ((BytesSent / 1024)/1024), ReceivedBytesinMB
+ = ((BytesReceived / 1024)/1024)\\n| summarize HourlyCount = count(),TimeGeneratedMax=arg_max(TimeGenerated,
+ *), DestinationIPList=make_set(DestinationIP), DestinationPortList = make_set(DestinationPort),
+ TotalSentBytesinMB = sum(SentBytesinMB),TotalReceivedBytesinMB = sum(ReceivedBytesinMB)
+ by SourceIP, DestinationIP, DeviceVendor, TimeGeneratedHour=bin(TimeGenerated,1h)\\n|
+ project DeviceVendor, TimeGeneratedHour, TimeGeneratedMax, SourceIP, DestinationIPList,
+ DestinationPortList, TotalSentBytesinMB, TotalReceivedBytesinMB \\n| where
+ TotalSentBytesinMB > bytessentperhourthreshold\\n)\\n);\\n// Join against
+ base logs to retrive records associated with the hour of anomoly\\nTimeSeriesAlerts\\n|
+ join (\\n BaseLogs | extend AnomalyHour = TimeGeneratedHour\\n) on DeviceVendor,
+ AnomalyHour | sort by score desc \\n| project DeviceVendor, AnomalyHour,TimeGeneratedMax,
+ SourceIP, DestinationIPList, DestinationPortList, TotalSentBytesinMB, TotalReceivedBytesinMB,
+ TotalBytesSentinMBperHour, baselinebytessentperHour, score, anomalies \\n|
+ summarize EventCount = count(), StartTimeUtc= min(TimeGeneratedMax), EndTimeUtc=
+ max(TimeGeneratedMax), SourceIPMax= arg_max(SourceIP,*), TotalBytesSentinMB
+ = sum(TotalSentBytesinMB), TotalBytesReceivedinMB = sum(TotalReceivedBytesinMB),
+ SourceIPList = make_set(SourceIP), DestinationIPList = make_set(DestinationIPList)
+ by AnomalyHour,TotalBytesSentinMBperHour, baselinebytessentperHour, score,
+ anomalies\\n| project DeviceVendor, AnomalyHour, StartTimeUtc, EndTimeUtc,
+ SourceIPMax, SourceIPList, DestinationIPList, DestinationPortList, TotalBytesSentinMB,
+ TotalBytesReceivedinMB, TotalBytesSentinMBperHour, baselinebytessentperHour,
+ score, anomalies, EventCount \\n| extend timestamp =EndTimeUtc, IPCustomEntity
+ = SourceIPMax\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":1,\"displayName\":\"Time
+ series anomaly for data size transferred to public internet\",\"description\":\"Identifies
+ anomalous data transfer to public networks. The query leverages built-in KQL
+ anomaly detection algorithms that detects large deviations from a baseline
+ pattern. \\nA sudden increase in data transferred to unknown public networks
+ is an indication of data exfiltration attempts and should be investigated.
+ \\nThe higher the score, the further it is from the baseline value.\\nThe
+ output is aggregated to provide summary view of unique source IP to destination
+ IP address and port bytes sent traffic observed in the flagged anomaly hour.
+ \\nThe source IP addresses which were sending less than bytessentperhourthreshold
+ have been exluded whose value can be adjusted as needed .\\nYou may have to
+ run queries for individual source IP addresses from SourceIPlist to determine
+ if anything looks suspicious\",\"tactics\":[\"Exfiltration\"],\"createdDateUTC\":\"2019-05-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/70b12a3b-4896-42cb-910c-5ffaf8d7987d\",\"name\":\"70b12a3b-4896-42cb-910c-5ffaf8d7987d\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = dynamic([\\\"seoulhobi.biz\\\", \\\"reader.cash\\\",
+ \\\"pieceview.club\\\", \\\"app-wallet.com\\\", \\\"bigwnet.com\\\", \\\"bitwoll.com\\\",
+ \\\"cexrout.com\\\", \\\"change-pw.com\\\", \\\"checkprofie.com\\\", \\\"cloudwebappservice.com\\\",
+ \\\"ctquast.com\\\", \\\"dataviewering.com\\\", \\\"day-post.com\\\", \\\"dialy-post.com\\\",
+ \\\"documentviewingcom.com\\\", \\\"dovvn-mail.com\\\", \\\"down-error.com\\\",
+ \\\"drivecheckingcom.com\\\", \\\"drog-service.com\\\", \\\"encodingmail.com\\\",
+ \\\"filinvestment.com\\\", \\\"foldershareing.com\\\", \\\"golangapis.com\\\",
+ \\\"hotrnall.com\\\", \\\"lh-logins.com\\\", \\\"login-use.com\\\", \\\"mail-down.com\\\",
+ \\\"matmiho.com\\\", \\\"mihomat.com\\\", \\\"natwpersonal-online.com\\\",
+ \\\"nidlogin.com\\\", \\\"nid-login.com\\\", \\\"nidlogon.com\\\", \\\"pw-change.com\\\",
+ \\\"rnaii.com\\\", \\\"rnailm.com\\\", \\\"sec-live.com\\\", \\\"secrityprocessing.com\\\",
+ \\\"securitedmode.com\\\", \\\"securytingmail.com\\\", \\\"set-login.com\\\",
+ \\\"usrchecking.com\\\", \\\"com-serviceround.info\\\", \\\"mai1.info\\\",
+ \\\"reviewer.mobi\\\", \\\"files-download.net\\\", \\\"fixcool.net\\\", \\\"hanrnaii.net\\\",
+ \\\"office356-us.org\\\", \\\"smtper.org\\\"]);\\n(union isfuzzy=true\\n(CommonSecurityLog
+ \\n| where TimeGenerated >= ago(timeframe) \\n| parse Message with * '(' DNSName
+ ')' * \\n| where isnotempty(FileHash)\\n| where DNSName in~ (DomainNames)\\n|
+ extend Account = SourceUserID, Computer = DeviceName, IPAddress = SourceIP\\n),\\n(DnsEvents
+ \\n| where TimeGenerated >= ago(timeframe) \\n| extend DNSName = Name\\n|
+ where isnotempty(DNSName)\\n| where DNSName in~ (DomainNames)\\n| extend
+ IPAddress = ClientIP\\n),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse RemoteDnsCanonicalNames with * '[\\\"' DNSName '\\\"]' *\\n| where
+ isnotempty(DNSName)\\n| where DNSName in~ (DomainNames)\\n| extend IPAddress
+ = RemoteIp\\n)\\n)\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = Account, HostCustomEntity = Computer, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"THALLIUM
+ domains included in DCU takedown\",\"description\":\"THALLIUM spearphishing
+ and command and control domains included in December 2019 DCU/MSTIC takedown.
+ \\n Matches domain name IOCs related to the THALLIUM activity group with CommonSecurityLog,
+ DnsEvents, VMConnection and SecurityEvents dataTypes.\\n References: https://blogs.microsoft.com/on-the-issues/2019/12/30/microsoft-court-action-against-nation-state-cybercrime/
+ \",\"tactics\":[\"CommandAndControl\",\"CredentialAccess\"],\"createdDateUTC\":\"2020-01-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/06a9b845-6a95-4432-a78b-83919b28c375\",\"name\":\"06a9b845-6a95-4432-a78b-83919b28c375\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\nlet timeframe = 1h;\\nlet scorethreshold
+ = 5;\\nlet percentotalthreshold = 25;\\nlet TimeSeriesData = CommonSecurityLog
+ \\n| where isnotempty(DestinationIP) and isnotempty(SourceIP)\\n| where TimeGenerated
+ between (startofday(ago(starttime))..startofday(ago(endtime)))\\n| project
+ TimeGenerated,SourceIP, DestinationIP, DeviceVendor\\n| make-series Total=count()
+ on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime))
+ step timeframe by DeviceVendor;\\n//Filtering specific records associated
+ with spikes as outliers\\nlet TimeSeriesAlerts=TimeSeriesData\\n| extend (anomalies,
+ score, baseline) = series_decompose_anomalies(Total, scorethreshold, -1, 'linefit')\\n|
+ mv-expand Total to typeof(double), TimeGenerated to typeof(datetime), anomalies
+ to typeof(double),score to typeof(double), baseline to typeof(long)\\n| where
+ anomalies > 0 | extend score = round(score,2), AnomalyHour = TimeGenerated\\n|
+ project DeviceVendor,AnomalyHour, TimeGenerated, Total, baseline, anomalies,
+ score;\\n//Join anomalies with Base Data to popalate associated records for
+ investigation - Results sorted by score in descending order \\nTimeSeriesAlerts
+ \\n| join (\\n CommonSecurityLog \\n| where isnotempty(DestinationIP) and
+ isnotempty(SourceIP)\\n| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime)))\\n|
+ summarize HourlyCount = count(), TimeGeneratedMax = arg_max(TimeGenerated,
+ *), DestinationIPlist = make_set(DestinationIP), DestinationPortlist = make_set(DestinationPort)
+ by DeviceVendor, SourceIP, TimeGeneratedHour= bin(TimeGenerated, 1h)\\n| extend
+ AnomalyHour = TimeGeneratedHour\\n) on AnomalyHour, DeviceVendor \\n| extend
+ PercentTotal = round((HourlyCount / Total) * 100, 3)\\n| where PercentTotal
+ > percentotalthreshold\\n| project DeviceVendor , AnomalyHour, TimeGeneratedMax,
+ SourceIP, DestinationIPlist, DestinationPortlist, HourlyCount, PercentTotal,
+ Total, baseline, score, anomalies\\n| summarize HourlyCount=sum(HourlyCount),
+ StartTimeUtc=min(TimeGeneratedMax), EndTimeUtc=max(TimeGeneratedMax), SourceIPlist
+ = make_set(SourceIP), SourceIPMax= arg_max(SourceIP, *), DestinationIPlist
+ = make_set(DestinationIPlist), DestinationPortlist = make_set(DestinationPortlist)
+ by DeviceVendor , AnomalyHour, Total, baseline, score, anomalies\\n| project
+ DeviceVendor , AnomalyHour, EndTimeUtc, SourceIPMax ,SourceIPlist, DestinationIPlist,
+ DestinationPortlist, HourlyCount, Total, baseline, score, anomalies\\n| extend
+ timestamp= EndTimeUtc , IPCustomEntity = SourceIPMax\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":3,\"displayName\":\"Time
+ series anomaly detection for total volume of traffic\",\"description\":\"Identifies
+ anamalous spikes in network traffic logs as compared to baseline or normal
+ historical patterns. \\nThe query leverages a KQL built-in anomaly detection
+ algorithm to find large deviations from baseline patterns. \\nSudden increases
+ in network traffic volume may be an indication of data exfiltration attempts
+ and should be investigated.\\nThe higher the score, the further it is from
+ the baseline value.\\nThe output is aggregated to provide summary view of
+ unique source IP to destination IP address and port traffic observed in the
+ flagged anomaly hour. \\nThe source IP addresses which were sending less than
+ percentotalthreshold of the total traffic have been exluded whose value can
+ be adjusted as needed .\\nYou may have to run queries for individual source
+ IP addresses from SourceIPlist to determine if anything looks suspicious\",\"tactics\":[\"Exfiltration\"],\"createdDateUTC\":\"2019-05-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Barracuda\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CEF\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CheckPoint\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"F5\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"Fortinet\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3533f74c-9207-4047-96e2-0eb9383be587\",\"name\":\"3533f74c-9207-4047-96e2-0eb9383be587\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ detectionTime = 1d;\\nlet joinLookback = 14d;\\nAuditLogs\\n| where TimeGenerated
+ > ago(detectionTime)\\n| where LoggedByService =~ \\\"Core Directory\\\"\\n|
+ where Category =~ \\\"ApplicationManagement\\\"\\n| where OperationName =~
+ \\\"Consent to application\\\"\\n| where TargetResources has \\\"offline\\\"\\n|
+ extend AppDisplayName = TargetResources.[0].displayName\\n| extend AppClientId
+ = tolower(TargetResources.[0].id)\\n| where AppClientId !in ((externaldata(knownAppClientId:string,
+ knownAppDisplayName:string)[@\\\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.OAuth.KnownApplications.csv\\\"]
+ with (format=\\\"csv\\\")))\\n| extend ConsentFull = TargetResources[0].modifiedProperties[4].newValue\\n|
+ parse ConsentFull with * \\\"ConsentType: \\\" GrantConsentType \\\", Scope:
+ \\\" GrantScope1 \\\"]\\\" *\\n| where ConsentFull contains \\\"offline_access\\\"
+ and ConsentFull contains \\\"Files.Read\\\" or ConsentFull contains \\\"Mail.Read\\\"
+ or ConsentFull contains \\\"Notes.Read\\\" or ConsentFull contains \\\"ChannelMessage.Read\\\"
+ or ConsentFull contains \\\"Chat.Read\\\" or ConsentFull contains \\\"TeamsActivity.Read\\\"
+ or ConsentFull contains \\\"Group.Read\\\" or ConsentFull contains \\\"EWS.AccessAsUser.All\\\"
+ or ConsentFull contains \\\"EAS.AccessAsUser.All\\\"\\n| where GrantConsentType
+ != \\\"AllPrincipals\\\" // NOTE: we are ignoring if OAuth application was
+ granted to all users via an admin - but admin due diligence should be audited
+ occasionally\\n| extend GrantIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress),
+ InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)\\n| extend GrantInitiatedBy
+ = iff(isnotempty(InitiatedBy.user.userPrincipalName),InitiatedBy.user.userPrincipalName,
+ InitiatedBy.app.displayName)\\n| extend GrantUserAgent = iff(AdditionalDetails[0].key
+ =~ \\\"User-Agent\\\", AdditionalDetails[0].value, \\\"\\\")\\n| project TimeGenerated,
+ GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName, GrantIpAddress,
+ GrantUserAgent, AppClientId, OperationName, ConsentFull, CorrelationId\\n|
+ join kind = leftouter (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add service principal\\\"\\n| extend AppClientId
+ = tolower(TargetResources[0].id)\\n| extend AppReplyURLs = iff(TargetResources[0].modifiedProperties[1].newValue
+ has \\\"AddressType\\\", TargetResources[0].modifiedProperties[1].newValue,
+ \\\"\\\")\\n| distinct AppClientId, tostring(AppReplyURLs)\\n)\\non AppClientId\\n|
+ join kind = innerunique (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add OAuth2PermissionGrant\\\" or OperationName
+ =~ \\\"Add delegated permission grant\\\"\\n| extend GrantAuthentication =
+ tostring(TargetResources[0].displayName)\\n| extend GrantOperation = OperationName\\n|
+ project GrantAuthentication, GrantOperation, CorrelationId\\n) on CorrelationId\\n|
+ project TimeGenerated, GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName,
+ AppReplyURLs, GrantIpAddress, GrantUserAgent, AppClientId, GrantAuthentication,
+ OperationName, GrantOperation, CorrelationId, ConsentFull\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ application consent for offline access\",\"description\":\"This will alert
+ when a user consents to provide a previously-unknown Azure application with
+ offline access via OAuth.\\nOffline access will provide the Azure App with
+ access to the listed resources without requiring two-factor authentication.\\nConsent
+ to applications with offline access and read capabilities should be rare,
+ especially as the knownApplications list is expanded. Public contributions
+ to expand this filter are welcome!\\nFor further information on AuditLogs
+ please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-26T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0777f138-e5d8-4eab-bec1-e11ddfbc2be2\",\"name\":\"0777f138-e5d8-4eab-bec1-e11ddfbc2be2\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 10m;\\nlet threshold = 20;\\nSecurityEvent \\n| where TimeGenerated
+ >= ago(timeframe)\\n| where EventID == 4625\\n| where AccountType =~ \\\"User\\\"\\n|
+ where SubStatus !='0xc0000064' and Account !in ('\\\\\\\\', '-\\\\\\\\-')\\n//
+ SubStatus '0xc0000064' signifies 'Account name does not exist'\\n| extend
+ ResourceId = column_ifexists(\\\"_ResourceId\\\", _ResourceId), SourceComputerId
+ = column_ifexists(\\\"SourceComputerId\\\", SourceComputerId)\\n| extend Reason
+ = case(\\nSubStatus =~ '0xC000005E', 'There are currently no logon servers
+ available to service the logon request.',\\nSubStatus =~ '0xC0000064', 'User
+ logon with misspelled or bad user account',\\nSubStatus =~ '0xC000006A', 'User
+ logon with misspelled or bad password', \\nSubStatus =~ '0xC000006D', 'Bad
+ user name or password',\\nSubStatus =~ '0xC000006E', 'Unknown user name or
+ bad password',\\nSubStatus =~ '0xC000006F', 'User logon outside authorized
+ hours',\\nSubStatus =~ '0xC0000070', 'User logon from unauthorized workstation',\\nSubStatus
+ =~ '0xC0000071', 'User logon with expired password',\\nSubStatus =~ '0xC0000072',
+ 'User logon to account disabled by administrator',\\nSubStatus =~ '0xC00000DC',
+ 'Indicates the Sam Server was in the wrong state to perform the desired operation',
+ \\nSubStatus =~ '0xC0000133', 'Clocks between DC and other computer too far
+ out of sync',\\nSubStatus =~ '0xC000015B', 'The user has not been granted
+ the requested logon type (aka logon right) at this machine',\\nSubStatus =~
+ '0xC000018C', 'The logon request failed because the trust relationship between
+ the primary domain and the trusted domain failed',\\nSubStatus =~ '0xC0000192',
+ 'An attempt was made to logon, but the Netlogon service was not started',\\nSubStatus
+ =~ '0xC0000193', 'User logon with expired account',\\nSubStatus =~ '0xC0000224',
+ 'User is required to change password at next logon',\\nSubStatus =~ '0xC0000225',
+ 'Evidently a bug in Windows and not a risk',\\nSubStatus =~ '0xC0000234',
+ 'User logon with account locked',\\nSubStatus =~ '0xC00002EE', 'Failure Reason:
+ An Error occurred during Logon',\\nSubStatus =~ '0xC0000413', 'Logon Failure:
+ The machine you are logging onto is protected by an authentication firewall.
+ The specified account is not allowed to authenticate to the machine',\\nstrcat('Unknown
+ reason substatus: ', SubStatus))\\n| summarize StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated), FailedLogonCount = count() by EventID, \\nActivity,
+ Computer, Account, TargetAccount, TargetUserName, TargetDomainName, \\nLogonType,
+ LogonTypeName, LogonProcessName, Status, SubStatus, Reason, ResourceId, SourceComputerId,
+ WorkstationName, IpAddress\\n| where FailedLogonCount >= threshold\\n| extend
+ timestamp = StartTime, AccountCustomEntity = Account, HostCustomEntity = Computer,
+ IPCustomEntity = IpAddress\",\"queryFrequency\":\"PT10M\",\"queryPeriod\":\"PT10M\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ logon attempts by valid accounts within 10 mins\",\"description\":\"Identifies
+ when failed logon attempts are 20 or higher during a 10 minute period (2 failed
+ logons per minute minimum) from valid account.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a7427ed7-04b4-4e3b-b323-08b981b9b4bf\",\"name\":\"a7427ed7-04b4-4e3b-b323-08b981b9b4bf\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n| where isnotempty(FileHashValue)\\n| join (\\n SecurityEvent
+ | where TimeGenerated >= ago(dt_lookBack)\\n | where EventID in (\\\"8003\\\",\\\"8002\\\",\\\"8005\\\")\\n
+ \ | where isnotempty(FileHash)\\n | extend SecurityEvent_TimeGenerated
+ = TimeGenerated, Event = EventID\\n)\\non $left.FileHashValue == $right.FileHash\\n|
+ summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n|
+ project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId,
+ ThreatType, Url, ExpirationDateTime, ConfidenceScore,\\nSecurityEvent_TimeGenerated,
+ Process, FileHash, Computer, Account, Event\\n| extend timestamp = SecurityEvent_TimeGenerated,
+ AccountCustomEntity = Account, HostCustomEntity = Computer, URLCustomEntity
+ = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map File Hash to Security Event\",\"description\":\"Identifies a match
+ in Security Event data from any File Hash IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/85aca4d1-5d15-4001-abd9-acb86ca1786a\",\"name\":\"85aca4d1-5d15-4001-abd9-acb86ca1786a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\n//Create a list of TLDs in our
+ threat feed for later validation\\nlet list_tlds = ThreatIntelligenceIndicator\\n|
+ where TimeGenerated > ago(ioc_lookBack)\\n| where isnotempty(DomainName)\\n|
+ extend parts = split(DomainName, '.')\\n| extend tld = parts[(array_length(parts)-1)]\\n|
+ summarize count() by tostring(tld)\\n| summarize make_list(tld);\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(DomainName)\\n| join (\\n DnsEvents\\n |
+ where TimeGenerated > ago(dt_lookBack)\\n //Extract domain patterns from
+ syslog message\\n | where isnotempty(Name)\\n | extend parts = split(Name,
+ '.')\\n //Split out the TLD\\n | extend tld = parts[(array_length(parts)-1)]\\n
+ \ //Validate parsed domain by checking if the TLD is in the list of TLDs
+ in our threat feed\\n | where tld in~ (list_tlds)\\n | extend DNS_TimeGenerated
+ = TimeGenerated\\n) on $left.DomainName==$right.Name\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime,
+ ConfidenceScore, Url, DNS_TimeGenerated, Computer, ClientIP, Name, QueryType\\n|
+ extend timestamp = DNS_TimeGenerated, HostCustomEntity = Computer, IPCustomEntity
+ = ClientIP, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Domain entity to DnsEvent\",\"description\":\"Identifies a match in
+ DnsEvent table from any Domain IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f110287e-1358-490d-8147-ed804b328514\",\"name\":\"f110287e-1358-490d-8147-ed804b328514\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n AWSCloudTrail | where
+ TimeGenerated >= ago(dt_lookBack)\\n // renaming time column so it is clear
+ the log this came from\\n | extend AWSCloudTrail_TimeGenerated = TimeGenerated\\n)\\non
+ $left.TI_ipEntity == $right.SourceIpAddress\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime,
+ ConfidenceScore, AWSCloudTrail_TimeGenerated,\\nTI_ipEntity, EventName, EventTypeName,
+ UserIdentityAccountId, UserIdentityPrincipalid, UserIdentityUserName, SourceIpAddress,\\nNetworkIP,
+ NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp
+ = AWSCloudTrail_TimeGenerated, IPCustomEntity = SourceIpAddress, AccountCustomEntity
+ = UserIdentityUserName, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to AWSCloudTrail\",\"description\":\"Identifies a match in
+ AWSCloudTrail from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ef88eb96-861c-43a0-ab16-f3835a97c928\",\"name\":\"ef88eb96-861c-43a0-ab16-f3835a97c928\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet regexEmpire = @\\\"SetDelay|GetDelay|Set-LostLimit|Get-LostLimit|Set-Killdate|Get-Killdate|Set-WorkingHours|Get-WorkingHours|Get-Sysinfo|Add-Servers|Invoke-ShellCommand|Start-AgentJob|Update-Profile|Get-FilePart|Encrypt-Bytes|Decrypt-Bytes|Encode-Packet|Decode-Packet|Send-Message|Process-Packet|Process-Tasking|Get-Task|Start-Negotiate|Invoke-DllInjection|Invoke-ReflectivePEInjection|Invoke-Shellcode|Invoke-ShellcodeMSIL|Get-ChromeDump|Get-ClipboardContents|Get-IndexedItem|Get-Keystrokes|Invoke-Inveigh|Invoke-NetRipper|local:Invoke-PatchDll|Invoke-NinjaCopy|Get-Win32Types|Get-Win32Constants|Get-Win32Functions|Sub-SignedIntAsUnsigned|Add-SignedIntAsUnsigned|Compare-Val1GreaterThanVal2AsUInt|Convert-UIntToInt|Test-MemoryRangeValid|Write-BytesToMemory|Get-DelegateType|Get-ProcAddress|Enable-SeDebugPrivilege|Invoke-CreateRemoteThread|Get-ImageNtHeaders|Get-PEBasicInfo|Get-PEDetailedInfo|Import-DllInRemoteProcess|Get-RemoteProcAddress|Copy-Sections|Update-MemoryAddresses|Import-DllImports|Get-VirtualProtectValue|Update-MemoryProtectionFlags|Update-ExeFunctions|Copy-ArrayOfMemAddresses|Get-MemoryProcAddress|Invoke-MemoryLoadLibrary|Invoke-MemoryFreeLibrary|Out-Minidump|Get-VaultCredential|Invoke-DCSync|Translate-Name|Get-NetDomain|Get-NetForest|Get-NetForestDomain|Get-DomainSearcher|Get-NetComputer|Get-NetGroupMember|Get-NetUser|Invoke-Mimikatz|Invoke-PowerDump|Invoke-TokenManipulation|Exploit-JMXConsole|Exploit-JBoss|Invoke-Thunderstruck|Invoke-VoiceTroll|Set-WallPaper|Invoke-PsExec|Invoke-SSHCommand|Invoke-PSInject|Invoke-RunAs|Invoke-SendMail|Invoke-Rule|Get-OSVersion|Select-EmailItem|View-Email|Get-OutlookFolder|Get-EmailItems|Invoke-MailSearch|Get-SubFolders|Get-GlobalAddressList|Invoke-SearchGAL|Get-SMTPAddress|Disable-SecuritySettings|Reset-SecuritySettings|Get-OutlookInstance|New-HoneyHash|Set-MacAttribute|Invoke-PatchDll|Get-SecurityPackages|Install-SSP|Invoke-BackdoorLNK|New-ElevatedPersistenceOption|New-UserPersistenceOption|Add-Persistence|Invoke-CallbackIEX|Add-PSFirewallRules|Invoke-EventLoop|Invoke-PortBind|Invoke-DNSLoop|Invoke-PacketKnock|Invoke-CallbackLoop|Invoke-BypassUAC|Get-DecryptedCpassword|Get-GPPInnerFields|Invoke-WScriptBypassUAC|Get-ModifiableFile|Get-ServiceUnquoted|Get-ServiceFilePermission|Get-ServicePermission|Invoke-ServiceUserAdd|Invoke-ServiceCMD|Write-UserAddServiceBinary|Write-CMDServiceBinary|Write-ServiceEXE|Write-ServiceEXECMD|Restore-ServiceEXE|Invoke-ServiceStart|Invoke-ServiceStop|Invoke-ServiceEnable|Invoke-ServiceDisable|Get-ServiceDetail|Find-DLLHijack|Find-PathHijack|Write-HijackDll|Get-RegAlwaysInstallElevated|Get-RegAutoLogon|Get-VulnAutoRun|Get-VulnSchTask|Get-UnattendedInstallFile|Get-Webconfig|Get-ApplicationHost|Write-UserAddMSI|Invoke-AllChecks|Invoke-ThreadedFunction|Test-Login|Get-UserAgent|Test-Password|Get-ComputerDetails|Find-4648Logons|Find-4624Logons|Find-AppLockerLogs|Find-PSScriptsInPSAppLog|Find-RDPClientConnections|Get-SystemDNSServer|Invoke-Paranoia|Invoke-WinEnum{|Get-SPN|Invoke-ARPScan|Invoke-Portscan|Invoke-ReverseDNSLookup|Invoke-SMBScanner|New-InMemoryModule|Add-Win32Type|Export-PowerViewCSV|Get-MacAttribute|Copy-ClonedFile|Get-IPAddress|Convert-NameToSid|Convert-SidToName|Convert-NT4toCanonical|Get-Proxy|Get-PathAcl|Get-NameField|Convert-LDAPProperty|Get-NetDomainController|Add-NetUser|Add-NetGroupUser|Get-UserProperty|Find-UserField|Get-UserEvent|Get-ObjectAcl|Add-ObjectAcl|Invoke-ACLScanner|Get-GUIDMap|Get-ADObject|Set-ADObject|Get-ComputerProperty|Find-ComputerField|Get-NetOU|Get-NetSite|Get-NetSubnet|Get-DomainSID|Get-NetGroup|Get-NetFileServer|SplitPath|Get-DFSshare|Get-DFSshareV1|Get-DFSshareV2|Get-GptTmpl|Get-GroupsXML|Get-NetGPO|Get-NetGPOGroup|Find-GPOLocation|Find-GPOComputerAdmin|Get-DomainPolicy|Get-NetLocalGroup|Get-NetShare|Get-NetLoggedon|Get-NetSession|Get-NetRDPSession|Invoke-CheckLocalAdminAccess|Get-LastLoggedOn|Get-NetProcess|Find-InterestingFile|Invoke-CheckWrite|Invoke-UserHunter|Invoke-StealthUserHunter|Invoke-ProcessHunter|Invoke-EventHunter|Invoke-ShareFinder|Invoke-FileFinder|Find-LocalAdminAccess|Get-ExploitableSystem|Invoke-EnumerateLocalAdmin|Get-NetDomainTrust|Get-NetForestTrust|Find-ForeignUser|Find-ForeignGroup|Invoke-MapDomainTrust|Get-Hex|Create-RemoteThread|Get-FoxDump|Decrypt-CipherText|Get-Screenshot|Start-HTTP-Server|Local:Invoke-CreateRemoteThread|Local:Get-Win32Functions|Local:Inject-NetRipper|GetCommandLine|ElevatePrivs|Get-RegKeyClass|Get-BootKey|Get-HBootKey|Get-UserName|Get-UserHashes|DecryptHashes|DecryptSingleHash|Get-UserKeys|DumpHashes|Enable-SeAssignPrimaryTokenPrivilege|Enable-Privilege|Set-DesktopACLs|Set-DesktopACLToAllowEveryone|Get-PrimaryToken|Get-ThreadToken|Get-TokenInformation|Get-UniqueTokens|Find-GPOLocation|Find-GPOComputerAdmin|Get-DomainPolicy|Get-NetLocalGroup|Get-NetShare|Get-NetLoggedon|Get-NetSession|Get-NetRDPSession|Invoke-CheckLocalAdminAccess|Get-LastLoggedOn|Get-NetProcess|Find-InterestingFile|Invoke-CheckWrite|Invoke-UserHunter|Invoke-StealthUserHunter|Invoke-ProcessHunter|Invoke-EventHunter|Invoke-ShareFinder|Invoke-FileFinder|Find-LocalAdminAccess|Get-ExploitableSystem|Invoke-EnumerateLocalAdmin|Get-NetDomainTrust|Get-NetForestTrust|Find-ForeignUser|Find-ForeignGroup|Invoke-MapDomainTrust|Get-Hex|Create-RemoteThread|Get-FoxDump|Decrypt-CipherText|Get-Screenshot|Start-HTTP-Server|Local:Invoke-CreateRemoteThread|Local:Get-Win32Functions|Local:Inject-NetRipper|GetCommandLine|ElevatePrivs|Get-RegKeyClass|Get-BootKey|Get-HBootKey|Get-UserName|Get-UserHashes|DecryptHashes|DecryptSingleHash|Get-UserKeys|DumpHashes|Enable-SeAssignPrimaryTokenPrivilege|Enable-Privilege|Set-DesktopACLs|Set-DesktopACLToAllowEveryone|Get-PrimaryToken|Get-ThreadToken|Get-TokenInformation|Get-UniqueTokens|Invoke-ImpersonateUser|Create-ProcessWithToken|Free-AllTokens|Enum-AllTokens|Invoke-RevertToSelf|Set-Speaker(\\\\$Volume){\\\\$wshShell|Local:Get-RandomString|Local:Invoke-PsExecCmd|Get-GPPPassword|Local:Inject-BypassStuff|Local:Invoke-CopyFile\\\\(\\\\$sSource,|ind-Fruit|New-IPv4Range|New-IPv4RangeFromCIDR|Parse-Hosts|Parse-ILHosts|Exclude-Hosts|Get-TopPort|Parse-Ports|Parse-IpPorts|Remove-Ports|Write-PortscanOut|Convert-SwitchtoBool|Get-ForeignUser|Get-ForeignGroup\\\";\\nlet
+ ProcessCreationEvents=() {\\nlet processEvents=SecurityEvent\\n| where EventID==4688\\n|
+ where isnotempty(CommandLine)\\n| project TimeGenerated, Computer, Account
+ = SubjectUserName, AccountDomain = SubjectDomainName, FileName = Process,
+ CommandLine, ParentProcessName;\\nprocessEvents};\\nlet decodedPS = ProcessCreationEvents\\n|
+ where TimeGenerated >= ago(timeframe) \\n| where CommandLine contains \\\"
+ -encodedCommand\\\"\\n| parse kind=regex flags=i CommandLine with * \\\"-EncodedCommand
+ \\\" encodedCommand\\n| project StartTimeUtc = TimeGenerated, encodedCommand
+ = tostring(split(encodedCommand, ' ')[0]), CommandLine\\n// Note: currently
+ the base64_decodestring function is limited to supporting UTF8\\n| extend
+ decodedCommand = translate('\\\\0','', base64_decodestring(substring(encodedCommand,
+ 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand,
+ CommandLine , strlen(encodedCommand);\\n(decodedPS\\n| union \\n(ProcessCreationEvents\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where FileName in~ (\\\"powershell.exe\\\",\\\"powershell_ise.exe\\\")\\n|
+ where CommandLine !contains \\\"-encodedcommand\\\")\\n| extend StartTimeUtc
+ = TimeGenerated\\n)\\n| where CommandLine matches regex regexEmpire\\n| extend
+ timestamp = StartTimeUtc, AccountCustomEntity = Account, HostCustomEntity
+ = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Powershell
+ Empire cmdlets seen in command line\",\"description\":\"Identifies instances
+ of PowerShell Empire cmdlets in powershell process command line data.\",\"tactics\":[\"Execution\",\"Persistence\"],\"createdDateUTC\":\"2019-01-25T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/643c2025-9604-47c5-833f-7b4b9378a1f5\",\"name\":\"643c2025-9604-47c5-833f-7b4b9378a1f5\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"//Adjust
+ this threshold to fit your environment\\nlet signin_threshold = 5; \\n//Make
+ a list of IPs with AAD signin failures above our threshold\\nlet Suspicious_signins
+ = \\nSigninLogs\\n| where TimeGenerated >= ago(1d)\\n| where ResultType !in
+ (\\\"0\\\", \\\"50125\\\", \\\"50140\\\")\\n| where IPAddress != \\\"127.0.0.1\\\"\\n|
+ summarize count() by IPAddress\\n| where count_ > signin_threshold\\n| summarize
+ make_list(IPAddress);\\n//See if any of those IPs have sucessfully logged
+ into the AWS console\\nAWSCloudTrail\\n| where TimeGenerated > ago(1d)\\n|
+ where EventName =~ \\\"ConsoleLogin\\\"\\n| extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
+ \\n| where LoginResult =~ \\\"Success\\\"\\n| where SourceIpAddress in (Suspicious_signins)\\n|
+ extend Reason = \\\"Multiple failed AAD logins from IP address\\\"\\n| extend
+ MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed)\\n| extend User
+ = iif(isempty(UserIdentityUserName), UserIdentityType, UserIdentityUserName)
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by Reason, LoginResult, EventTypeName, UserIdentityType, User, AWSRegion,
+ SourceIpAddress, UserAgent, MFAUsed\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = User, IPCustomEntity = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ AzureAD logons but success logon to AWS Console\",\"description\":\"Identifies
+ a list of IP addresses with a minimum number(defualt of 5) of failed logon
+ attempts to Azure Active Directory.\\nUses that list to identify any successful
+ AWS Console logons from these IPs within the same timeframe.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-08-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7249500f-3038-4b83-8549-9cd8dfa2d498\",\"name\":\"7249500f-3038-4b83-8549-9cd8dfa2d498\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = dynamic([\\\"de-ma.online\\\", \\\"g20saudi.000webhostapp.com\\\",
+ \\\"ksat20.000webhostapp.com\\\"]);\\nlet EmailAddresses = dynamic([\\\"munichconference1962@gmail.com\\\",\\\"munichconference@outlook.de\\\",
+ \\\"munichconference@outlook.com\\\", \\\"t20saudiarabia@gmail.com\\\", \\\"t20saudiarabia@hotmail.com\\\",
+ \\\"t20saudiarabia@outlook.sa\\\"]);\\n(union isfuzzy=true\\n(CommonSecurityLog
+ \\n| where TimeGenerated >= ago(timeframe)\\n| parse Message with * '(' DNSName
+ ')' * \\n| extend MessageIP = extract(IPRegex, 0, Message)\\n| extend RequestURLIP
+ = extract(IPRegex, 0, Message)\\n| where (isnotempty(DNSName) and DNSName
+ has_any (DomainNames)) \\n or (isnotempty(DestinationHostName) and DestinationHostName
+ has_any (DomainNames)) \\n or (isnotempty(RequestURL) and (RequestURL has_any
+ (DomainNames)))\\n| extend timestamp = TimeGenerated , AccountCustomEntity
+ = SourceUserID, HostCustomEntity = DeviceName\\n),\\n(DnsEvents \\n| where
+ TimeGenerated >= ago(timeframe) \\n| extend DestinationIPAddress = IPAddresses,
+ DNSName = Name, Host = Computer\\n| where DNSName has_any (DomainNames) \\n|
+ extend timestamp = TimeGenerated, IPCustomEntity = DestinationIPAddress, HostCustomEntity
+ = Host),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe) \\n| parse
+ RemoteDnsCanonicalNames with * '[\\\"' DNSName '\\\"]' *\\n| where isnotempty(DNSName)\\n|
+ where DNSName has_any (DomainNames)\\n| extend timestamp = TimeGenerated ,
+ HostCustomEntity = Computer),\\n(SecurityAlert\\n| where TimeGenerated >=
+ ago(timeframe) \\n| where ProviderName =~ 'OATP'\\n| extend UPN = case(isnotempty(parse_json(Entities)[0].Upn),
+ parse_json(Entities)[0].Upn, \\n isnotempty(parse_json(Entities)[1].Upn),
+ parse_json(Entities)[1].Upn,\\n isnotempty(parse_json(Entities)[2].Upn),
+ parse_json(Entities)[2].Upn,\\n isnotempty(parse_json(Entities)[3].Upn),
+ parse_json(Entities)[3].Upn,\\n isnotempty(parse_json(Entities)[4].Upn),
+ parse_json(Entities)[4].Upn,\\n isnotempty(parse_json(Entities)[5].Upn),
+ parse_json(Entities)[5].Upn,\\n isnotempty(parse_json(Entities)[6].Upn),
+ parse_json(Entities)[6].Upn,\\n isnotempty(parse_json(Entities)[7].Upn),
+ parse_json(Entities)[7].Upn,\\n isnotempty(parse_json(Entities)[8].Upn),
+ parse_json(Entities)[8].Upn,\\n parse_json(Entities)[9].Upn)\\n|
+ where Entities has_any (EmailAddresses)\\n| extend timestamp = TimeGenerated,
+ AccountCustomEntity = tostring(UPN)),\\n(AzureDiagnostics\\n| where TimeGenerated
+ >= ago(timeframe) \\n| where ResourceType =~ \\\"AZUREFIREWALLS\\\"\\n| where
+ msg_s has_any (DomainNames)\\n| extend timestamp = TimeGenerated))\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ PHOSPHORUS group domains/IP - October 2020\",\"description\":\"Matches IOCs
+ related to PHOSPHORUS group activity published October 2020 with CommonSecurityLog,
+ DnsEvents, OfficeActivity and VMConnection dataTypes.\\nReferences: \",\"tactics\":[\"CommandAndControl\",\"InitialAccess\"],\"createdDateUTC\":\"2020-10-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog
+ (Cisco)\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog
+ (PaloAlto)\"]},{\"connectorId\":\"Zscaler\",\"dataTypes\":[\"CommonSecurityLog
+ (Zscaler)\"]},{\"connectorId\":\"Fortinet\",\"dataTypes\":[\"CommonSecurityLog
+ (Fortinet)\"]},{\"connectorId\":\"OfficeATP\",\"dataTypes\":[\"SecurityAlert
+ (OATP)\"]},{\"connectorId\":\"AzureFirewall\",\"dataTypes\":[\"AzureDiagnostics
+ (Azure Firewall)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0b9ae89d-8cad-461c-808f-0494f70ad5c4\",\"name\":\"0b9ae89d-8cad-461c-808f-0494f70ad5c4\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet PerUserThreshold = 5;\\nlet TotalThreshold = 100;\\nlet
+ action = dynamic([\\\"change\\\", \\\"changed\\\", \\\"reset\\\"]);\\nlet
+ pWord = dynamic([\\\"password\\\", \\\"credentials\\\"]);\\nlet PasswordResetMultiDataSource
+ =\\n(union isfuzzy=true\\n(//Password reset events\\n//4723: An attempt was
+ made to change an account's password\\n//4724: An attempt was made to reset
+ an accounts password\\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where EventID in (\\\"4723\\\",\\\"4724\\\")\\n| project TimeGenerated, Computer,
+ AccountType, Account, Type),\\n(//Azure Active Directory Password reset events\\nAuditLogs\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where OperationName has_any (pWord)
+ and OperationName has_any (action)\\n| extend AccountType = tostring(TargetResources[0].type),
+ Account = tostring(TargetResources[0].userPrincipalName), \\nTargetResourceName
+ = tolower(tostring(TargetResources[0].displayName))\\n| project TimeGenerated,
+ AccountType, Account, Computer = TargetResourceName, Type),\\n(//OfficeActive
+ ActiveDirectory Password reset events\\nOfficeActivity\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where OfficeWorkload == \\\"AzureActiveDirectory\\\"
+ \\n| where (ExtendedProperties has_any (pWord) or ModifiedProperties has_any
+ (pWord)) and (ExtendedProperties has_any (action) or ModifiedProperties has_any
+ (action))\\n| extend AccountType = UserType, Account = OfficeObjectId \\n|
+ project TimeGenerated, AccountType, Account, Type, Computer = \\\"\\\"),\\n(//
+ Unix syslog password reset events\\nSyslog\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where Facility in (\\\"auth\\\",\\\"authpriv\\\")\\n| where SyslogMessage
+ has_any (pWord) and SyslogMessage has_any (action)\\n| extend AccountType
+ = iif(SyslogMessage contains \\\"root\\\", \\\"Root\\\", \\\"Non-Root\\\")\\n|
+ parse SyslogMessage with * \\\"password changed for\\\" Account\\n| project
+ TimeGenerated, AccountType, Account, Computer = HostName, Type),\\n(SigninLogs\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where OperationName =~ \\\"Sign-in
+ activity\\\" and ResultType has_any (\\\"50125\\\", \\\"50133\\\")\\n| project
+ TimeGenerated, AccountType = AppDisplayName, Computer = IPAddress, Account
+ = UserPrincipalName, Type\\n)\\n);\\nlet pwrmd = PasswordResetMultiDataSource\\n|
+ project TimeGenerated, Computer, AccountType, Account, Type;\\n(union isfuzzy=true
+ \ \\n(pwrmd\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc =
+ max(TimeGenerated), Computer = makeset(Computer), AccountType = makeset(AccountType),
+ Total=count() by Account, Type\\n| where Total > PerUserThreshold\\n| extend
+ ResetPivot = \\\"PerUserReset\\\"), \\n(pwrmd\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Computer = makeset(Computer),
+ Account = tostring(makeset(Account)), AccountType = makeset(AccountType),
+ Total=count() by Type\\n| where Total > TotalThreshold\\n| extend ResetPivot
+ = \\\"TotalUserReset\\\")\\n)\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Account, HostCustomEntity = tostring(Computer)\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Multiple
+ Password Reset by user\",\"description\":\"This query will determine multiple
+ password resets by user across multiple data sources. \\nAccount manipulation
+ including password reset may aid adversaries in maintaining access to credentials
+ \\nand certain permission levels within an environment.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-09-03T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]},{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]},{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/327cd4ed-ca42-454b-887c-54e1c91363c6\",\"name\":\"327cd4ed-ca42-454b-887c-54e1c91363c6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Microsoft
+ Defender Advanced Threat Protection\",\"displayName\":\"Create incidents based
+ on Microsoft Defender Advanced Threat Protection alerts\",\"description\":\"Create
+ incidents based on all alerts generated in Microsoft Defender Advanced Threat
+ Protection\",\"createdDateUTC\":\"2019-10-24T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"MicrosoftDefenderAdvancedThreatProtection\",\"dataTypes\":[\"SecurityAlert
+ (MDATP)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/44a555d8-ecee-4a25-95ce-055879b4b14b\",\"name\":\"44a555d8-ecee-4a25-95ce-055879b4b14b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeFrame = 1d;\\nlet timeBin = 10m;\\nlet portThreshold = 30;\\nW3CIISLog\\n|
+ where TimeGenerated >= ago(timeFrame)\\n| extend scStatusFull = strcat(scStatus,
+ \\\".\\\",scSubStatus) \\n// Map common IIS codes\\n| extend scStatusFull_Friendly
+ = case(\\nscStatusFull == \\\"401.0\\\", \\\"Access denied.\\\",\\nscStatusFull
+ == \\\"401.1\\\", \\\"Logon failed.\\\",\\nscStatusFull == \\\"401.2\\\",
+ \\\"Logon failed due to server configuration.\\\",\\nscStatusFull == \\\"401.3\\\",
+ \\\"Unauthorized due to ACL on resource.\\\",\\nscStatusFull == \\\"401.4\\\",
+ \\\"Authorization failed by filter.\\\",\\nscStatusFull == \\\"401.5\\\",
+ \\\"Authorization failed by ISAPI/CGI application.\\\",\\nscStatusFull ==
+ \\\"403.0\\\", \\\"Forbidden.\\\",\\nscStatusFull == \\\"403.4\\\", \\\"SSL
+ required.\\\",\\n\\\"See - https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\\")\\n//
+ Mapping to Hex so can be mapped using website in comments above\\n| extend
+ scWin32Status_Hex = tohex(tolong(scWin32Status)) \\n// Map common win32 codes\\n|
+ extend scWin32Status_Friendly = case(\\nscWin32Status_Hex =~ \\\"775\\\",
+ \\\"The referenced account is currently locked out and cannot be logged on
+ to.\\\",\\nscWin32Status_Hex =~ \\\"52e\\\", \\\"Logon failure: Unknown user
+ name or bad password.\\\",\\nscWin32Status_Hex =~ \\\"532\\\", \\\"Logon failure:
+ The specified account password has expired.\\\",\\nscWin32Status_Hex =~ \\\"533\\\",
+ \\\"Logon failure: Account currently disabled.\\\", \\nscWin32Status_Hex =~
+ \\\"2ee2\\\", \\\"The request has timed out.\\\", \\nscWin32Status_Hex =~
+ \\\"0\\\", \\\"The operation completed successfully.\\\", \\nscWin32Status_Hex
+ =~ \\\"1\\\", \\\"Incorrect function.\\\", \\nscWin32Status_Hex =~ \\\"2\\\",
+ \\\"The system cannot find the file specified.\\\", \\nscWin32Status_Hex =~
+ \\\"3\\\", \\\"The system cannot find the path specified.\\\", \\nscWin32Status_Hex
+ =~ \\\"4\\\", \\\"The system cannot open the file.\\\", \\nscWin32Status_Hex
+ =~ \\\"5\\\", \\\"Access is denied.\\\", \\nscWin32Status_Hex =~ \\\"8009030e\\\",
+ \\\"SEC_E_NO_CREDENTIALS\\\", \\nscWin32Status_Hex =~ \\\"8009030C\\\", \\\"SEC_E_LOGON_DENIED\\\",
+ \\n\\\"See - https://msdn.microsoft.com/library/cc231199.aspx\\\")\\n// decode
+ URI when available\\n| extend decodedUriQuery = url_decode(csUriQuery)\\n//
+ Count of attempts by client IP on many ports\\n| summarize makeset(sPort),
+ makeset(decodedUriQuery), makeset(csUserName), makeset(sSiteName), makeset(sPort),
+ makeset(csUserAgent), makeset(csMethod), makeset(csUriQuery), makeset(scStatusFull),
+ makeset(scStatusFull_Friendly), makeset(scWin32Status_Hex), makeset(scWin32Status_Friendly),
+ ConnectionsCount = count() by bin(TimeGenerated, timeBin), cIP, Computer,
+ sIP\\n| extend portCount = arraylength(set_sPort)\\n| where portCount >= portThreshold\\n|
+ project TimeGenerated, cIP, set_sPort, set_csUserName, set_decodedUriQuery,
+ Computer, set_sSiteName, sIP, set_csUserAgent, set_csMethod, set_scStatusFull,
+ set_scStatusFull_Friendly, set_scWin32Status_Hex, set_scWin32Status_Friendly,
+ ConnectionsCount, portCount\\n| order by portCount\\n| extend timestamp =
+ TimeGenerated, IPCustomEntity = cIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"High
+ count of connections by client IP on many ports\",\"description\":\"Identifies
+ when 30 or more ports are used for a given client IP in 10 minutes occurring
+ on the IIS server.\\nThis could be indicative of attempted port scanning or
+ exploit attempt at internet facing web applications. \\nThis could also simply
+ indicate a misconfigured service or device.\\nReferences:\\nIIS status code
+ mapping - https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\nWin32
+ Status code mapping - https://msdn.microsoft.com/library/cc231199.aspx\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-03-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/712fab52-2a7d-401e-a08c-ff939cc7c25e\",\"name\":\"712fab52-2a7d-401e-a08c-ff939cc7c25e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(Url)\\n| join (\\n AuditLogs\\n | where TimeGenerated
+ >= ago(dt_lookBack)\\n // Extract the URL that is contained within the JSON
+ data\\n | extend Url = extract(\\\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\\\\\(\\\\\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\\\",
+ 1,tostring(TargetResources))\\n | where isnotempty(Url)\\n | extend userPrincipalName
+ = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)\\n |
+ extend TargetResourceDisplayName = tostring(TargetResources[0].displayName)\\n
+ \ | extend Audit_TimeGenerated = TimeGenerated\\n) on Url\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime,
+ ConfidenceScore,\\nAudit_TimeGenerated, OperationName, Identity, userPrincipalName,
+ TargetResourceDisplayName, Url\\n| extend timestamp = Audit_TimeGenerated,
+ AccountCustomEntity = userPrincipalName, HostCustomEntity = TargetResourceDisplayName,
+ URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map URL entity to AuditLogs\",\"description\":\"Identifies a match in AuditLogs
+ from any URL IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/361dd1e3-1c11-491e-82a3-bb2e44ac36ba\",\"name\":\"361dd1e3-1c11-491e-82a3-bb2e44ac36ba\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ szOperationNames = dynamic([\\\"Create or Update Virtual Machine\\\", \\\"Create
+ Deployment\\\"]);\\nlet starttime = 7d;\\nlet endtime = 1d;\\nAzureActivity\\n|
+ where TimeGenerated between (startofday(ago(starttime)) .. startofday(ago(endtime)))\\n|
+ where OperationName in~ (szOperationNames)\\n| summarize StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = makelist(TimeGenerated),
+ ActivityStatus = makelist(ActivityStatus), \\nOperationIds = makelist(OperationId),
+ CallerIpAddress = makelist(CallerIpAddress), CorrelationId = makelist(CorrelationId)
+ \\nby ResourceId, Caller, OperationName, Resource, ResourceGroup\\n| mvexpand
+ CallerIpAddress\\n| where isnotempty(CallerIpAddress)\\n| make-series dResourceCount=dcount(ResourceId)
+ \ default=0 on StartTimeUtc in range(startofday(ago(7d)), now(), 1d) \\nby
+ Caller, tostring(ActivityTimeStamp), tostring(ActivityStatus), tostring(OperationIds),
+ tostring(CallerIpAddress), tostring(CorrelationId), ResourceId, OperationName,
+ Resource, ResourceGroup\\n| extend (RSquare,Slope,Variance,RVariance,Interception,LineFit)=series_fit_line(dResourceCount)\\n|
+ where Slope > 0.2\\n| join kind=leftsemi (\\n// Last day's activity is anomalous\\nAzureActivity\\n|
+ where TimeGenerated >= startofday(ago(endtime))\\n| where OperationName in~
+ (szOperationNames)\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc
+ = max(TimeGenerated), ActivityTimeStamp = makelist(TimeGenerated), ActivityStatus
+ = makelist(ActivityStatus), \\nOperationIds = makelist(OperationId), CallerIpAddress
+ = makelist(CallerIpAddress), CorrelationId = makelist(CorrelationId) \\nby
+ ResourceId, Caller, OperationName, Resource, ResourceGroup\\n| mvexpand CallerIpAddress\\n|
+ where isnotempty(CallerIpAddress)\\n| make-series dResourceCount=dcount(ResourceId)
+ \ default=0 on StartTimeUtc in range(startofday(ago(1d)), now(), 1d) \\nby
+ Caller, tostring(ActivityTimeStamp), tostring(ActivityStatus), tostring(OperationIds),
+ tostring(CallerIpAddress), tostring(CorrelationId), ResourceId, OperationName,
+ Resource, ResourceGroup\\n| extend (RSquare,Slope,Variance,RVariance,Interception,LineFit)=series_fit_line(dResourceCount)\\n|
+ where Slope > 0.2 \\n) on Caller, CallerIpAddress \\n| mvexpand
+ todynamic(ActivityTimeStamp), todynamic(ActivityStatus), todynamic(OperationIds),
+ todynamic(CorrelationId)\\n| extend timestamp = ActivityTimeStamp, AccountCustomEntity
+ = Caller, IPCustomEntity = CallerIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ number of resource creation or deployment activities\",\"description\":\"Indicates
+ when an anomalous number of VM creations or deployment activities occur in
+ Azure via the AzureActivity log.\\nThe anomaly detection identifies activities
+ that have occured both since the start of the day 1 day ago and the start
+ of the day 7 days ago.\\nThe start of the day is considered 12am UTC time.\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-02-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/be52662c-3b23-435a-a6fa-f39bdfc849e6\",\"name\":\"be52662c-3b23-435a-a6fa-f39bdfc849e6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 10;\\nQualysHostDetection_CL\\n| where
+ TimeGenerated >= timeframe\\n| mv-expand todynamic(Detections_s)\\n| where
+ Detections_s.Severity == \\\"5\\\"\\n| summarize StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated), count() by NetBios_s, IPAddress\\n| where count_
+ >= threshold\\n| extend timestamp = StartTime, HostCustomEntity = NetBios_s,
+ IPCustomEntity = IPAddress\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"High
+ Number of Urgent Vulnerabilities Detected\",\"description\":\"This Creates
+ an incident when a host has a high number of Urgent, severity 5, vulnerabilities
+ detected.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"QualysVulnerabilityManagement\",\"dataTypes\":[\"QualysHostDetection_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/39198934-62a0-4781-8416-a81265c03fd6\",\"name\":\"39198934-62a0-4781-8416-a81265c03fd6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ detectionTime = 1d;\\nlet joinLookback = 14d;\\nAuditLogs\\n| where TimeGenerated
+ > ago(detectionTime)\\n| where LoggedByService =~ \\\"Core Directory\\\"\\n|
+ where Category =~ \\\"ApplicationManagement\\\"\\n| where OperationName =~
+ \\\"Consent to application\\\"\\n| where TargetResources has \\\"offline\\\"\\n|
+ extend AppDisplayName = TargetResources.[0].displayName\\n| extend AppClientId
+ = tolower(TargetResources.[0].id)\\n| where AppClientId !in ((externaldata(knownAppClientId:string,
+ knownAppDisplayName:string)[@\\\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.OAuth.KnownApplications.csv\\\"]
+ with (format=\\\"csv\\\")))\\n| extend ConsentFull = TargetResources[0].modifiedProperties[4].newValue\\n|
+ parse ConsentFull with * \\\"ConsentType: \\\" GrantConsentType \\\", Scope:
+ \\\" GrantScope1 \\\"]\\\" *\\n| where ConsentFull contains \\\"user.read\\\"
+ and ConsentFull contains \\\"offline_access\\\" and ConsentFull contains \\\"mail.readwrite\\\"
+ and ConsentFull contains \\\"mail.send\\\" and ConsentFull contains \\\"files.read.all\\\"\\n|
+ where GrantConsentType != \\\"AllPrincipals\\\" // NOTE: we are ignoring if
+ OAuth application was granted to all users via an admin - but admin due diligence
+ should be audited occasionally\\n| extend GrantIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress),
+ InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)\\n| extend GrantInitiatedBy
+ = iff(isnotempty(InitiatedBy.user.userPrincipalName),InitiatedBy.user.userPrincipalName,
+ InitiatedBy.app.displayName)\\n| extend GrantUserAgent = iff(AdditionalDetails[0].key
+ =~ \\\"User-Agent\\\", AdditionalDetails[0].value, \\\"\\\")\\n| project TimeGenerated,
+ GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName, GrantIpAddress,
+ GrantUserAgent, AppClientId, OperationName, ConsentFull, CorrelationId\\n|
+ join kind = leftouter (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add service principal\\\"\\n| extend AppClientId
+ = tolower(TargetResources[0].id)\\n| extend AppReplyURLs = iff(TargetResources[0].modifiedProperties[1].newValue
+ has \\\"AddressType\\\", TargetResources[0].modifiedProperties[1].newValue,
+ \\\"\\\")\\n| distinct AppClientId, tostring(AppReplyURLs)\\n)\\non AppClientId\\n|
+ join kind = innerunique (AuditLogs\\n| where TimeGenerated > ago(joinLookback)\\n|
+ where LoggedByService =~ \\\"Core Directory\\\"\\n| where Category =~ \\\"ApplicationManagement\\\"\\n|
+ where OperationName =~ \\\"Add OAuth2PermissionGrant\\\" or OperationName
+ =~ \\\"Add delegated permission grant\\\"\\n| extend GrantAuthentication =
+ tostring(TargetResources[0].displayName)\\n| extend GrantOperation = OperationName\\n|
+ project GrantAuthentication, GrantOperation, CorrelationId\\n) on CorrelationId\\n|
+ project TimeGenerated, GrantConsentType, GrantScope1, GrantInitiatedBy, AppDisplayName,
+ AppReplyURLs, GrantIpAddress, GrantUserAgent, AppClientId, GrantAuthentication,
+ OperationName, GrantOperation, CorrelationId, ConsentFull\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ application consent similar to PwnAuth\",\"description\":\"This will alert
+ when a user consents to provide a previously-unknown Azure application with
+ the same OAuth permissions used by the FireEye PwnAuth toolkit (https://github.com/fireeye/PwnAuth).\\nThe
+ default permissions/scope for the PwnAuth toolkit are user.read, offline_access,
+ mail.readwrite, mail.send, and files.read.all.\\nConsent to applications with
+ these permissions should be rare, especially as the knownApplications list
+ is expanded. Public contributions to expand this filter are welcome!\\nFor
+ further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.\",\"tactics\":[\"CredentialAccess\",\"DefenseEvasion\"],\"createdDateUTC\":\"2020-06-26T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f71aba3d-28fb-450b-b192-4e76a83015c8\",\"name\":\"f71aba3d-28fb-450b-b192-4e76a83015c8\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Fusion\",\"properties\":{\"severity\":\"High\",\"displayName\":\"Advanced
+ Multistage Attack Detection\",\"description\":\"Using Fusion technology based
+ on machine learning, Azure Sentinel automatically detects multistage attacks
+ by identifying combinations of anomalous behaviors and suspicious activities
+ observed at various stages of the kill chain. On the basis of these discoveries,
+ Azure Sentinel generates incidents that would otherwise be very difficult
+ to catch. By design, these incidents are low-volume, high-fidelity, and high-severity,
+ which is why this detection is turned ON by default.\\n\\nThere are a total
+ of 70 Fusion incident types detected by Azure Sentinel.\\n- 65 of these show
+ the combination of suspicious Azure Active Directory sign-in events followed
+ by anomalous Office 365 activity. Out of these 65, 30 are in public preview.
+ \\n- The remaining five incident types show the combination of anomalous signals
+ from Microsoft Defender Advanced Threat Protection and from Palo Alto Networks
+ firewalls. These five types are all in public preview.\\n\\nTo detect these
+ multistage attacks, the following data connectors must be configured:\\n-
+ Azure Active Directory Identity Protection.\\n- Microsoft Cloud App Security.\\n-
+ Microsoft Defender Advanced Threat Protection.\\n- Palo Alto Networks.\\n\\nFor
+ a full list and description of each scenario that is supported for these multistage
+ attacks, go to https://aka.ms/SentinelFusion.\",\"tactics\":[\"Collection\",\"CommandAndControl\",\"DefenseEvasion\",\"Discovery\",\"Execution\",\"Exfiltration\",\"Impact\",\"InitialAccess\",\"LateralMovement\",\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-07-25T00:00:00Z\",\"status\":\"Available\",\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3d023f64-8225-41a2-9570-2bd7c2c4535e\",\"name\":\"3d023f64-8225-41a2-9570-2bd7c2c4535e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet spanoftime = 10m;\\nlet threshold = 0;\\nSecurityEvent
+ \\n| where TimeGenerated > ago(2*timeframe) \\n// A user account was enabled\\n|
+ where EventID == 4722\\n| where AccountType =~ \\\"User\\\"\\n| project creationTime
+ = TimeGenerated, CreateEventID = EventID, Activity, Computer, TargetUserName,
+ UserPrincipalName, \\nAccountUsedToCreate = SubjectUserName, TargetSid, SubjectUserSid
+ \\n| join kind= inner (\\n SecurityEvent\\n | where TimeGenerated > ago(timeframe)
+ \\n // A user account was disabled \\n | where EventID == 4725\\n| where
+ AccountType == \\\"User\\\"\\n| project deletionTime = TimeGenerated, DeleteEventID
+ = EventID, Activity, Computer, TargetUserName, UserPrincipalName, \\nAccountUsedToDelete
+ = SubjectUserName, TargetSid, SubjectUserSid \\n) on Computer, TargetUserName\\n|
+ where deletionTime - creationTime < spanoftime\\n| extend TimeDelta = deletionTime
+ - creationTime\\n| where tolong(TimeDelta) >= threshold\\n| project TimeDelta,
+ creationTime, CreateEventID, Computer, TargetUserName, UserPrincipalName,
+ AccountUsedToCreate, \\ndeletionTime, DeleteEventID, AccountUsedToDelete\\n|
+ extend timestamp = creationTime, AccountCustomEntity = AccountUsedToCreate,
+ HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ account enabled and disabled within 10 mins\",\"description\":\"Identifies
+ when a user account is enabled and then disabled within 10 minutes. This can
+ be an indication of compromise and\\nan adversary attempting to hide in the
+ noise.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/75bf9902-0789-47c1-a5d8-f57046aa72df\",\"name\":\"75bf9902-0789-47c1-a5d8-f57046aa72df\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet procList = dynamic([\\\"cmd.exe\\\",\\\"ftp.exe\\\",\\\"schtasks.exe\\\",\\\"powershell.exe\\\",\\\"rundll32.exe\\\",\\\"regsvr32.exe\\\",\\\"msiexec.exe\\\"]);\\nlet
+ ProcessCreationEvents=() {\\nlet processEvents=SecurityEvent\\n| where EventID==4688\\n|
+ where isnotempty(CommandLine)\\n| project TimeGenerated, Computer, Account
+ = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,\\nFileName
+ = Process, CommandLine, ParentProcessName;\\nprocessEvents};\\nProcessCreationEvents
+ \\n| where TimeGenerated >= ago(timeframe)\\n| where FileName in~ (procList)\\n|
+ where CommandLine contains \\\":\\\\\\\\recycler\\\"\\n| project StartTimeUtc
+ = TimeGenerated, Computer, Account, NewProcessName, FileName, CommandLine,
+ ParentProcessName\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Account, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malware
+ in the recycle bin\",\"description\":\"Identifies malware that has been hidden
+ in the recycle bin.\\nReferences: https://azure.microsoft.com/blog/how-azure-security-center-helps-reveal-a-cyberattack/.\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2018-09-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/9736e5f1-7b6e-4bfb-a708-e53ff1d182c3\",\"name\":\"9736e5f1-7b6e-4bfb-a708-e53ff1d182c3\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet tokens = dynamic([\\\"416\\\",\\\"208\\\",\\\"128\\\",\\\"120\\\",\\\"96\\\",\\\"80\\\",\\\"72\\\",\\\"64\\\",\\\"48\\\",\\\"44\\\",\\\"40\\\",\\\"g5\\\",\\\"gs5\\\",\\\"g4\\\",\\\"gs4\\\",\\\"nc12\\\",\\\"nc24\\\",\\\"nv12\\\"]);\\nlet
+ operationList = dynamic([\\\"Create or Update Virtual Machine\\\", \\\"Create
+ Deployment\\\"]);\\nAzureActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where OperationName in (operationList)\\n| where ActivityStatus == \\\"Accepted\\\"
+ \\n| where isnotempty(Properties)\\n| extend vmSize = tolower(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).responseBody)).properties)).hardwareProfile)).vmSize))\\n|
+ where isnotempty(vmSize)\\n| where vmSize has_any (tokens) \\n| extend ComputerName
+ = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).responseBody)).properties)).osProfile)).computerName)\\n|
+ extend clientIpAddress = tostring(parse_json(HTTPRequest).clientIpAddress)\\n|
+ project TimeGenerated, OperationName, ActivityStatus, Caller, CallerIpAddress,
+ ComputerName, vmSize\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = Caller, IPCustomEntity = CallerIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":1,\"displayName\":\"Creation
+ of expensive computes in Azure\",\"description\":\"Identifies the creation
+ of large size/expensive VMs (GPU or with large no of virtual CPUs) in Azure.\\nAdversary
+ may create new or update existing virtual machines sizes to evade defenses
+ \\nor use it for cryptomining purposes.\\nFor Windows/Linux Vm Sizes - https://docs.microsoft.com/azure/virtual-machines/windows/sizes
+ \\nAzure VM Naming Conventions - https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2020-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/aac495a9-feb1-446d-b08e-a1164a539452\",\"name\":\"aac495a9-feb1-446d-b08e-a1164a539452\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"ThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(24h)\\n| where Action == true\\n// Picking up only
+ IOC's that contain the entities we want\\n| where isnotempty(NetworkIP) or
+ isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n//
+ Taking the first non-empty value based on potential IOC match availability\\n|
+ extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\\n|
+ extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP),
+ NetworkSourceIP, TI_ipEntity)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\\n|
+ join (\\n GitHubAudit\\n | where TimeGenerated >= ago(24h)\\n | extend
+ GitHubAudit_TimeGenerated = TimeGenerated\\n)\\non $left.TI_ipEntity == $right.IPaddress\\n|
+ summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n|
+ project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId,
+ ThreatType, Url, ExpirationDateTime, ConfidenceScore, GitHubAudit_TimeGenerated,
+ TI_ipEntity, IPaddress, Actor, Action, Country, OperationType, NetworkIP,
+ NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp
+ = GitHubAudit_TimeGenerated, IPCustomEntity = IPaddress, AccountCustomEntity
+ = Actor\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"TI
+ map IP entity to GitHub_CL\",\"description\":\"Identifies a match in GitHub_CL
+ table from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/34663177-8abf-4db1-b0a4-5683ab273f44\",\"name\":\"34663177-8abf-4db1-b0a4-5683ab273f44\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 20;\\nPulseConnectSecure\\n| where
+ TimeGenerated >= timeframe\\n| where Messages contains \\\"Login failed\\\"\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), count()
+ by User, Source_IP\\n| where count_ > threshold\\n| extend timestamp = StartTime,
+ AccountCustomEntity = User, IPCustomEntity = Source_IP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"PulseConnectSecure
+ - Potential Brute Force Attempts\",\"description\":\"This query identifies
+ evidence of potential brute force attack by looking at multiple failed attempts
+ to log into the VPN server\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PulseConnectSecure\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/65360bb0-8986-4ade-a89d-af3cf44d28aa\",\"name\":\"65360bb0-8986-4ade-a89d-af3cf44d28aa\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet EventNameList = dynamic([\\\"CreateNetworkAclEntry\\\",\\\"CreateRoute\\\",\\\"CreateRouteTable\\\",\\\"CreateInternetGateway\\\",\\\"CreateNatGateway\\\"]);\\nAWSCloudTrail\\n|
+ where TimeGenerated > ago(timeframe)\\n| where EventName in~ (EventNameList)\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid,
+ UserAgent, \\nUserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress,
+ AWSRegion, EventSource, AdditionalEventData, ResponseElements\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = UserIdentityUserName, IPCustomEntity
+ = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Changes
+ to Amazon VPC settings\",\"description\":\"Amazon Virtual Private Cloud (Amazon
+ VPC) lets you provision a logically isolated section of the AWS Cloud where
+ you can launch AWS resources\\nin a virtual network that you define.\\nThis
+ identifies changes to Amazon VPC (Virtual Private Cloud) settings such as
+ new ACL entries,routes, routetable or Gateways.\\nMore information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255
+ \\nand AWS VPC API Docs: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/OperationList-query-vpc.html\",\"tactics\":[\"PrivilegeEscalation\",\"LateralMovement\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/9fb57e58-3ed8-4b89-afcf-c8e786508b1c\",\"name\":\"9fb57e58-3ed8-4b89-afcf-c8e786508b1c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ szOperationNames = dynamic([\\\"Create or Update Virtual Machine\\\", \\\"Create
+ Deployment\\\"]);\\nlet starttime = 14d;\\nlet endtime = 1d;\\nlet RareCaller
+ = AzureActivity\\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\\n|
+ where OperationName in~ (szOperationNames)\\n| project ResourceGroup, Caller,
+ OperationName, CallerIpAddress\\n| join kind=rightantisemi (\\nAzureActivity\\n|
+ where TimeGenerated > ago(endtime)\\n| where OperationName in~ (szOperationNames)\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ ActivityStatus = makeset(ActivityStatus), OperationIds = makeset(OperationId),
+ CallerIpAddress = makeset(CallerIpAddress) \\nby ResourceId, Caller, OperationName,
+ Resource, ResourceGroup\\n) on Caller, ResourceGroup \\n| mvexpand CallerIpAddress\\n|
+ where isnotempty(CallerIpAddress);\\nlet Counts = RareCaller | summarize ActivityCountByCaller
+ = count() by Caller;\\nRareCaller | join kind= inner (Counts) on Caller |
+ project-away Caller1\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Caller, IPCustomEntity = tostring(CallerIpAddress)\\n| sort by ActivityCountByCaller
+ desc nulls last\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ Resource deployment\",\"description\":\"Identifies when a rare Resource and
+ ResourceGroup deployment occurs by a previously unseen Caller.\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-02-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/d722831e-88f5-4e25-b106-4ef6e29f8c13\",\"name\":\"d722831e-88f5-4e25-b106-4ef6e29f8c13\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"//
+ a threshold can be enabled, see commented line below for PrevSeenCount\\nlet
+ threshold = 2;\\nlet uploadOp = 'FileUploaded';\\n// Extensions that are interesting.
+ Add/Remove to this list as you see fit\\nlet execExt = dynamic(['exe', 'inf',
+ 'gzip', 'cmd', 'bat']);\\nlet starttime = 8d;\\nlet endtime = 1d;\\nOfficeActivity
+ | where TimeGenerated >= ago(endtime)\\n// Limited to File Uploads due to
+ potential noise, comment out the Operation statement below to include any
+ operation type\\n// Additional, but potentially noisy operation types that
+ include Uploads and Downloads can be included by adding the following - Operation
+ contains \\\"upload\\\" or Operation contains \\\"download\\\"\\n| where Operation
+ =~ uploadOp\\n| where SourceFileExtension has_any (execExt)\\n| project TimeGenerated,
+ OfficeId, OfficeWorkload, RecordType, Operation, UserType, UserKey, UserId,
+ ClientIP, UserAgent, Site_Url, SourceRelativeUrl, SourceFileName\\n| join
+ kind= leftanti (\\nOfficeActivity | where TimeGenerated between (ago(starttime)
+ .. ago(endtime))\\n| where Operation =~ uploadOp\\n| where SourceFileExtension
+ has_any (execExt)\\n| summarize SourceRelativeUrl = make_set(SourceRelativeUrl),
+ UserId = make_set(UserId) , PrevSeenCount = count() by SourceFileName\\n//
+ To exclude previous matches when only above a specific count, change threshold
+ above and uncomment the line below\\n//| where PrevSeenCount > threshold\\n|
+ mvexpand SourceRelativeUrl, UserId\\n| extend SourceRelativeUrl = tostring(SourceRelativeUrl),
+ UserId = tostring(UserId)\\n) on SourceFileName, SourceRelativeUrl, UserId
+ \\n| extend SiteUrlUserFolder = tolower(split(Site_Url, '/')[-2])\\n| extend
+ UserIdUserFolderFormat = tolower(replace('@|\\\\\\\\.', '_',UserId))\\n//
+ identify when UserId is not a match to the specific site url personal folder
+ reference\\n| extend UserIdDiffThanUserFolder = iff(Site_Url has '/personal/'
+ and SiteUrlUserFolder != UserIdUserFolderFormat, true , false ) \\n| summarize
+ TimeGenerated = make_list(TimeGenerated), StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated), \\nUserAgents = make_list(UserAgent), OfficeIds
+ = make_list(OfficeId), SourceRelativeUrls = make_list(SourceRelativeUrl),
+ FileNames = make_list(SourceFileName)\\nby OfficeWorkload, RecordType, Operation,
+ UserType, UserKey, UserId, ClientIP, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat,
+ UserIdDiffThanUserFolder\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P8D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"New
+ executable via Office FileUploaded Operation\",\"description\":\"Identifies
+ when executable file types are uploaded to Office services such as SharePoint
+ and OneDrive.\\nList currently includes 'exe', 'inf', 'gzip', 'cmd', 'bat'
+ file extensions.\\nAdditionally, identifies when a given user is uploading
+ these files to another users workspace.\\nThis may be indication of a staging
+ location for malware or other malicious activity.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4b11568b-3f5f-4ba1-80c8-7f1dc8390eb7\",\"name\":\"4b11568b-3f5f-4ba1-80c8-7f1dc8390eb7\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ threshold = 50;\\nlet szSharePointFileOperation = \\\"SharePointFileOperation\\\";\\nlet
+ szOperations = dynamic([\\\"FileDownloaded\\\", \\\"FileUploaded\\\"]);\\nlet
+ starttime = 14d;\\nlet endtime = 1d;\\nlet historicalActivity =\\nOfficeActivity\\n|
+ where TimeGenerated between(ago(starttime)..ago(endtime))\\n| where RecordType
+ =~ szSharePointFileOperation\\n| where Operation in~ (szOperations)\\n| summarize
+ historicalCount = count() by ClientIP, RecordType, Operation;\\nlet recentActivity
+ = OfficeActivity\\n| where TimeGenerated > ago(endtime)\\n| where RecordType
+ =~ szSharePointFileOperation\\n| where Operation in~ (szOperations)\\n| summarize
+ min(Start_Time), max(Start_Time), recentCount = count() by ClientIP, RecordType,
+ Operation;\\nlet RareIP = recentActivity | join kind= leftanti ( historicalActivity
+ ) on ClientIP, RecordType, Operation\\n// More than 50 downloads/uploads from
+ a new IP\\n| where recentCount > threshold;\\nOfficeActivity \\n| where TimeGenerated
+ >= ago(endtime) \\n| where RecordType =~ szSharePointFileOperation\\n| where
+ Operation in~ (szOperations)\\n| join kind= inner (RareIP) on ClientIP, RecordType,
+ Operation\\n| where Start_Time between(min_Start_Time .. max_Start_Time)\\n|
+ summarize StartTimeUtc = min(min_Start_Time), EndTimeUtc = max(max_Start_Time)
+ by RecordType, Operation, UserType, UserId, ClientIP, OfficeWorkload, Site_Url,
+ OfficeObjectId, UserAgent, IPSeenCount = recentCount\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = UserId, IPCustomEntity = ClientIP, URLCustomEntity
+ = Site_Url\\n| order by IPSeenCount desc, ClientIP asc, Operation asc, UserId
+ asc\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"SharePointFileOperation
+ via previously unseen IPs\",\"description\":\"Identifies when the volume of
+ documents uploaded to or downloaded from Sharepoint by new IP addresses\\nexceeds
+ a threshold (default is 50).\",\"tactics\":[\"Exfiltration\"],\"createdDateUTC\":\"2019-08-23T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/871ba14c-88ef-48aa-ad38-810f26760ca3\",\"name\":\"871ba14c-88ef-48aa-ad38-810f26760ca3\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 7d;\\nOfficeActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where Operation =~ \\\"Set-Mailbox\\\"\\n| where Parameters has \\\"ForwardingSmtpAddress\\\"\\n|
+ extend parsed = parse_json(Parameters)\\n| mv-expand parsed\\n| where parsed.Name
+ == \\\"ForwardingSmtpAddress\\\"\\n| extend parameterName = tostring(parsed.Name),
+ fwdingDestination = tostring(parsed.Value)\\n| where isnotempty(fwdingDestination)\\n|
+ extend ClientIPOnly = case( \\nClientIP has \\\".\\\" and ClientIP has ':',
+ tostring(split(ClientIP,\\\":\\\")[0]), \\nClientIP has \\\".\\\" and ClientIP
+ has '-', tostring(split(ClientIP,\\\"-\\\")[0]), \\nClientIP has ']-', tostring(trim_start(@'[[]',tostring(split(ClientIP,\\\"]\\\")[0]))),\\nClientIP
+ has ']:', tostring(trim_start(@'[[]',tostring(split(ClientIP,\\\"]\\\")[0]))),\\nisempty(ClientIP)
+ and ClientIP_ has \\\".\\\" and ClientIP_ has ':', tostring(split(ClientIP_,\\\":\\\")[0]),
+ \\nisempty(ClientIP) and ClientIP_ has \\\".\\\" and ClientIP_ has '-', tostring(split(ClientIP_,\\\"-\\\")[0]),
+ \\nisempty(ClientIP) and ClientIP_ has ']-', tostring(trim_start(@'[[]',tostring(split(ClientIP_,\\\"]\\\")[0]))),\\nisempty(ClientIP)
+ and ClientIP_ has ']:', tostring(trim_start(@'[[]',tostring(split(ClientIP_,\\\"]\\\")[0]))),\\nisnotempty(ClientIP),
+ ClientIP,\\nisnotempty(ClientIP_), ClientIP_,\\n\\\"IP Not Available\\\"\\n)
+ \ \\n| extend Port = case(\\nClientIP has \\\".\\\" and ClientIP has ':',
+ tostring(split(ClientIP,\\\":\\\")[1]), \\nClientIP has \\\".\\\" and ClientIP
+ has '-', tostring(split(ClientIP,\\\"-\\\")[1]), \\nClientIP has ']-', tostring(split(ClientIP,\\\"]-\\\")[1]),
+ \\nClientIP has ']:', tostring(split(ClientIP,\\\"]:\\\")[1]), \\nisempty(ClientIP)
+ and ClientIP_ has \\\".\\\" and ClientIP_ has ':', tostring(split(ClientIP_,\\\":\\\")[1]),
+ \\nisempty(ClientIP) and ClientIP_ has \\\".\\\" and ClientIP_ has '-', tostring(split(ClientIP_,\\\"-\\\")[1]),
+ \\nisempty(ClientIP) and ClientIP_ has ']-', tostring(split(ClientIP_,\\\"]-\\\")[1]),\\nisempty(ClientIP)
+ and ClientIP_ has ']:', tostring(split(ClientIP_,\\\"]:\\\")[1]),\\nisnotempty(ClientIP),
+ ClientIP,\\nisnotempty(ClientIP_), ClientIP_,\\n\\\"IP Not Available\\\"\\n)\\n|
+ extend UserId = iff(isempty(UserId), UserId_, UserId)\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), DistinctUserCount =
+ dcount(UserId), UserId = make_set(UserId), \\nPorts = make_set(Port), EventCount
+ = count() by fwdingDestination, ClientIP = ClientIPOnly \\n| where DistinctUserCount
+ > 1\\n| mv-expand UserId\\n| extend UserId = tostring(UserId), Ports = tostring(Ports)\\n|
+ distinct StartTimeUtc, EndTimeUtc, UserId, DistinctUserCount, ClientIP, Ports,
+ fwdingDestination, EventCount\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = UserId, IPCustomEntity = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Multiple
+ users email forwarded to same destination\",\"description\":\"Identifies when
+ multiple (more than one) users mailboxes are configured to forward to the
+ same destination. \\nThis could be an attacker-controlled destination mailbox
+ configured to collect mail from multiple compromised user accounts.\",\"tactics\":[\"Collection\",\"Exfiltration\"],\"createdDateUTC\":\"2019-08-23T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/427e4c9e-8cf4-4094-a684-a2d060dbca38\",\"name\":\"427e4c9e-8cf4-4094-a684-a2d060dbca38\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 50;\\nSophosXGFirewall\\n| where TimeGenerated
+ >= timeframe\\n| where Log_Type =~ \\\"Firewall\\\"\\n| where not(ipv4_is_match(\\\"10.0.0.0\\\",Src_IP,8)
+ or ipv4_is_match(\\\"172.16.0.0\\\",Src_IP,12) or ipv4_is_match(\\\"192.168.0.0\\\",Src_IP,16))\\n|
+ summarize dcount(Dst_Port) by Src_IP, bin(TimeGenerated, 5m)\\n| where dcount_Dst_Port
+ > threshold\\n| extend timestamp = TimeGenerated, IPCustomEntity = Src_IP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Port
+ Scan Detected\",\"description\":\"This alert creates an incident when a source
+ IP addresses attempt to communicate with a large amount of distinct ports
+ within a short period.\",\"tactics\":[\"Discovery\"],\"createdDateUTC\":\"2020-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SophosXGFirewall\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4b93c5af-d20b-4236-b696-a28b8c51407f\",\"name\":\"4b93c5af-d20b-4236-b696-a28b8c51407f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet spanoftime = 10m;\\nlet threshold = 0;\\nSecurityEvent
+ \\n| where TimeGenerated > ago(2*timeframe) \\n// A user account was created\\n|
+ where EventID == 4720\\n| where AccountType =~ \\\"User\\\"\\n| project creationTime
+ = TimeGenerated, CreateEventID = EventID, Activity, Computer, TargetUserName,
+ UserPrincipalName, \\nAccountUsedToCreate = SubjectUserName, TargetSid, SubjectUserSid
+ \\n| join kind= inner (\\n SecurityEvent\\n | where TimeGenerated > ago(timeframe)
+ \\n // A user account was deleted \\n | where EventID == 4726\\n| where
+ AccountType == \\\"User\\\"\\n| project deletionTime = TimeGenerated, DeleteEventID
+ = EventID, Activity, Computer, TargetUserName, UserPrincipalName, \\nAccountUsedToDelete
+ = SubjectUserName, TargetSid, SubjectUserSid \\n) on Computer, TargetUserName\\n|
+ where deletionTime - creationTime < spanoftime\\n| extend TimeDelta = deletionTime
+ - creationTime\\n| where tolong(TimeDelta) >= threshold\\n| project TimeDelta,
+ creationTime, CreateEventID, Computer, TargetUserName, UserPrincipalName,
+ AccountUsedToCreate, \\ndeletionTime, DeleteEventID, AccountUsedToDelete\\n|
+ extend timestamp = creationTime, AccountCustomEntity = AccountUsedToCreate,
+ HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ account created and deleted within 10 mins\",\"description\":\"Identifies
+ when a user account is created and then deleted within 10 minutes. This can
+ be an indication of compromise and\\nan adversary attempting to hide in the
+ noise.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3255ec41-6bd6-4f35-84b1-c032b18bbfcb\",\"name\":\"3255ec41-6bd6-4f35-84b1-c032b18bbfcb\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 1d;\\nlet TimeDeltaThresholdInSeconds = 60; // we ignore beacons
+ diffs that fall below this threshold \\nlet TotalBeaconsThreshold = 4; //
+ minimum number of beacons required in a session to surface a row\\nlet JitterTolerance
+ = 0.2; // tolerance to jitter, e.g. - 0.2 = 20% jitter is tolerated either
+ side of the periodicity\\nlet PrivateIPregex = @\\\"^127\\\\.|^10\\\\.|^172\\\\.1[6-9]\\\\.|^172\\\\.2[0-9]\\\\.|^172\\\\.3[0-1]\\\\.|^192\\\\.168\\\\.\\\";
+ // exclude destinations that fall into this category\\nCommonSecurityLog\\n|
+ where DeviceVendor == \\\"Fortinet\\\"\\n| where TimeGenerated > ago(starttime)\\n//
+ eliminate bad data\\n| where isnotempty(SourceIP) and isnotempty(DestinationIP)
+ and SourceIP != \\\"0.0.0.0\\\"\\n// filter out deny, close, rst and SNMP
+ to reduce data volume\\n| where DeviceAction !in (\\\"close\\\", \\\"client-rst\\\",
+ \\\"server-rst\\\", \\\"deny\\\") and DestinationPort != 161\\n// map input
+ fields\\n| project TimeGenerated , SourceIP, DestinationIP, DestinationPort,
+ ReceivedBytes, SentBytes, DeviceAction \\n// where destination IPs are public\\n|
+ extend DestinationIPType = iff(DestinationIP matches regex PrivateIPregex,\\\"private\\\"
+ ,\\\"public\\\" )\\n| where DestinationIPType == \\\"public\\\"\\n// sort
+ into source->destination 'sessions'\\n| sort by SourceIP asc, DestinationIP
+ asc, DestinationPort asc, TimeGenerated asc\\n| serialize\\n// time diff the
+ contact times between source and destination to get a list of deltas\\n| extend
+ nextTimeGenerated = next(TimeGenerated, 1), nextSourceIP = next(SourceIP,
+ 1), nextDestIP = next(DestinationIP, 1), nextDestPort = next(DestinationPort,
+ 1)\\n| extend TimeDeltainSeconds = datetime_diff(\\\"second\\\",nextTimeGenerated,TimeGenerated)\\n|
+ where SourceIP == nextSourceIP and DestinationIP == nextDestIP and DestinationPort
+ == nextDestPort\\n// remove small time deltas below the set threshold\\n|
+ where TimeDeltainSeconds > TimeDeltaThresholdInSeconds\\n| project TimeGenerated,
+ TimeDeltainSeconds, SourceIP, DestinationIP, DestinationPort, ReceivedBytes,
+ SentBytes, DeviceAction \\n// summarize the deltas by source->destination\\n|
+ summarize count(), StartTime=min(TimeGenerated), EndTime=max(TimeGenerated),
+ sum(ReceivedBytes), sum(SentBytes), makelist(TimeDeltainSeconds), makeset(DeviceAction)
+ by SourceIP, DestinationIP, DestinationPort\\n// get some statistical properties
+ of the delta distribution and smooth any outliers (e.g. laptop shut overnight,
+ working hours)\\n| extend series_stats(list_TimeDeltainSeconds), outliers=series_outliers(list_TimeDeltainSeconds)\\n//
+ expand the deltas and the outliers\\n| mvexpand list_TimeDeltainSeconds to
+ typeof(double), outliers to typeof(double)\\n// replace outliers with the
+ average of the distribution\\n| extend list_TimeDeltainSeconds_normalized=iff(outliers
+ > 1.5 or outliers < -1.5, series_stats_list_TimeDeltainSeconds_avg , list_TimeDeltainSeconds)\\n//
+ summarize with the smoothed distribution\\n| summarize BeaconCount=count(),
+ makelist(list_TimeDeltainSeconds), list_TimeDeltainSeconds_normalized=makelist(list_TimeDeltainSeconds_normalized),
+ makeset(set_DeviceAction) by StartTime, EndTime, SourceIP, DestinationIP,
+ DestinationPort, sum_ReceivedBytes, sum_SentBytes\\n// get stats on the smoothed
+ distribution\\n| extend series_stats(list_TimeDeltainSeconds_normalized)\\n//
+ match jitter tolerance on smoothed distrib\\n| extend MaxJitter = (series_stats_list_TimeDeltainSeconds_normalized_avg*JitterTolerance)\\n|
+ where series_stats_list_TimeDeltainSeconds_normalized_stdev < MaxJitter\\n//
+ where the minimum beacon threshold is satisfied and there was some data transfer\\n|
+ where BeaconCount > TotalBeaconsThreshold and (sum_SentBytes > 0 or sum_ReceivedBytes
+ > 0)\\n// final projection\\n| project StartTime, EndTime, SourceIP, DestinationIP,
+ DestinationPort, BeaconCount, TimeDeltasInSeconds=list_list_TimeDeltainSeconds,
+ Periodicity=series_stats_list_TimeDeltainSeconds_normalized_avg, ReceivedBytes=sum_ReceivedBytes,
+ SentBytes=sum_SentBytes, Actions=set_set_DeviceAction\\n// where periodicity
+ is order of magnitude larger than time delta threshold (eliminates FPs whose
+ periodicity is close to the values we ignored)\\n| where Periodicity >= (10*TimeDeltaThresholdInSeconds)\\n|
+ extend timestamp = StartTime, IPCustomEntity = DestinationIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Fortinet
+ - Beacon pattern detected\",\"description\":\"Identifies patterns in the time
+ deltas of contacts between internal and external IPs in Fortinet network data
+ that are consistent with beaconing.\\n Accounts for randomness (jitter) and
+ seasonality such as working hours that may have been introduced into the beacon
+ pattern.\\n The lookback is set to 1d, the minimum granularity in time deltas
+ is set to 60 seconds and the minimum number of beacons required to emit a\\n
+ detection is set to 4.\\n Increase the lookback period to capture beacons
+ with larger periodicities.\\n The jitter tolerance is set to 0.2 - This means
+ we account for an overall 20% deviation from the infered beacon periodicity.
+ Seasonality is dealt with\\n automatically using series_outliers.\\n Note:
+ In large environments it may be necessary to reduce the lookback period to
+ get fast query times.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-03-31T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Fortinet\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/e27dd7e5-4367-4c40-a2b7-fcd7e7a8a508\",\"name\":\"e27dd7e5-4367-4c40-a2b7-fcd7e7a8a508\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet FailureThreshold = 15;\\nlet FailedEvents = Okta_CL\\n|
+ where TimeGenerated > timeframe\\n| where eventType_s =~ \\\"user.session.start\\\"and
+ outcome_reason_s in (\\\"VERIFICATION_ERROR\\\",\\\"INVALID_CREDENTIALS\\\")\\n|
+ summarize dcount(actor_alternateId_s) by client_ipAddress_s, bin(TimeGenerated,
+ 5m)\\n| where dcount_actor_alternateId_s > FailureThreshold\\n| project client_ipAddress_s,
+ TimeGenerated;\\nOkta_CL\\n| where TimeGenerated > timeframe\\n| where eventType_s
+ =~ \\\"user.session.start\\\"and outcome_reason_s in (\\\"VERIFICATION_ERROR\\\",\\\"INVALID_CREDENTIALS\\\")\\n|
+ summarize Users = make_set(actor_alternateId_s) by client_ipAddress_s, City
+ = client_geographicalContext_city_s, Country = client_geographicalContext_country_s,
+ bin(TimeGenerated, 5m)\\n| join kind=inner (FailedEvents) on client_ipAddress_s,
+ TimeGenerated\\n| sort by TimeGenerated desc\\n| extend timestamp = TimeGenerated,
+ IPCustomEntity = client_ipAddress_s\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Potential
+ Password Spray Attack\",\"description\":\"This query searches for failed attempts
+ to log into the Okta console from more than 15 various users within a 5 minute
+ timeframe from the same source. This is a potential indication of a password
+ spray attack\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"OktaSSO\",\"dataTypes\":[\"Okta_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/bfb1c90f-8006-4325-98be-c7fffbc254d6\",\"name\":\"bfb1c90f-8006-4325-98be-c7fffbc254d6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeRange = 1d;\\nlet s_threshold = 30;\\nlet l_threshold = 3;\\nSigninLogs\\n|
+ where TimeGenerated >= ago(timeRange)\\n| where OperationName =~ \\\"Sign-in
+ activity\\\"\\n// Error codes that we want to look at as they are related
+ to the use of incorrect password.\\n| where ResultType in (\\\"50126\\\",
+ \\\"50053\\\" , \\\"50055\\\", \\\"50056\\\")\\n| extend OS = DeviceDetail.operatingSystem,
+ Browser = DeviceDetail.browser \\n| extend LocationString= strcat(tostring(LocationDetails[\\\"countryOrRegion\\\"]),
+ \\\"/\\\", tostring(LocationDetails[\\\"state\\\"]), \\\"/\\\", tostring(LocationDetails[\\\"city\\\"]))\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated),LocationCount=dcount(LocationString),
+ Location = make_set(LocationString), \\nIPAddress = make_set(IPAddress), IPAddressCount
+ = dcount(IPAddress), AppDisplayName = make_set(AppDisplayName), ResultDescription
+ = make_set(ResultDescription), \\nBrowser = make_set(Browser), OS = make_set(OS),
+ SigninCount = count() by UserPrincipalName \\n//
+ Setting a generic threshold - Can be different for different environment\\n|
+ where SigninCount > s_threshold and LocationCount >= l_threshold\\n| extend
+ tostring(Location), tostring(IPAddress), tostring(AppDisplayName), tostring(ResultDescription),
+ tostring(Browser), tostring(OS)\\n| distinct *\\n| extend timestamp = StartTime,
+ AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Distributed
+ Password cracking attempts in AzureAD\",\"description\":\"Identifies distributed
+ password cracking attempts from the Azure Active Directory SigninLogs.\\nThe
+ query looks for unusually high number of failed password attempts coming from
+ multiple locations for a user account.\\nReferences: https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes\\n50053
+ \ Account is locked because the user tried to sign in too many times with
+ an incorrect user ID or password.\\n50055 Invalid password, entered expired
+ password.\\n50056 Invalid or null password - Password does not exist in
+ store for this user.\\n50126 Invalid username or password, or invalid on-premises
+ username or password.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-11T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/36a9c9e5-3dc1-4ed9-afaa-1d13617bfc2b\",\"name\":\"36a9c9e5-3dc1-4ed9-afaa-1d13617bfc2b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(Url)\\n| join (\\n OfficeActivity\\n | where
+ TimeGenerated >= ago(dt_lookBack)\\n //Extract the Url from a number of potential
+ fields\\n | extend Url = iif(OfficeWorkload == \\\"AzureActiveDirectory\\\",extract(\\\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\\\\\(\\\\\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\\\",
+ 1,ModifiedProperties),tostring(parse_json(ModifiedProperties)[12].NewValue))\\n
+ \ | where isnotempty(Url)\\n // Ensure we get a clean URL\\n | extend Url
+ = tostring(split(Url, ';')[0])\\n | extend Office_TimeGenerated = TimeGenerated\\n
+ \ // Project a single user identity that we can use for entity mapping\\n
+ \ | extend User = iif(isnotempty(UserId), UserId, iif(isnotempty(Actor), tostring(parse_json(Actor)[0].ID),
+ tostring(parse_json(Parameters)[0].Vlaue))) \\n) on Url\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime,
+ ConfidenceScore, Operation, \\nUserType, OfficeWorkload, Parameters, Office_TimeGenerated,
+ Url, User\\n| extend timestamp = Office_TimeGenerated, AccountCustomEntity
+ = User, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map URL entity to OfficeActivity data\",\"description\":\"Identifies a
+ match in OfficeActivity data from any URL IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a35f2c18-1b97-458f-ad26-e033af18eb99\",\"name\":\"a35f2c18-1b97-458f-ad26-e033af18eb99\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\n// For AD SID mappings - https://docs.microsoft.com/windows/security/identity-protection/access-control/active-directory-security-groups\\nlet
+ WellKnownLocalSID = \\\"S-1-5-32-5[0-9][0-9]$\\\";\\nlet WellKnownGroupSID
+ = \\\"S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-498$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1000$\\\";\\nSecurityEvent
+ \\n| where TimeGenerated > ago(timeframe)\\n// When MemberName contains '-'
+ this indicates addition of a group to a group\\n| where AccountType == \\\"User\\\"
+ and MemberName != \\\"-\\\"\\n// 4728 - A member was added to a security-enabled
+ global group\\n// 4732 - A member was added to a security-enabled local group\\n//
+ 4756 - A member was added to a security-enabled universal group\\n| where
+ EventID in (4728, 4732, 4756) \\n| where TargetSid matches regex WellKnownLocalSID
+ or TargetSid matches regex WellKnownGroupSID\\n// Exclude Remote Desktop Users
+ group: S-1-5-32-555\\n| where TargetSid !in (\\\"S-1-5-32-555\\\")\\n| extend
+ SimpleMemberName = tostring(split(tostring(split(MemberName, \\\",\\\")[0]),\\\"CN=\\\")[1])\\n|
+ project StartTimeUtc = TimeGenerated, EventID, Activity, Computer, SimpleMemberName,
+ MemberName, MemberSid, TargetUserName, TargetDomainName, TargetSid, UserPrincipalName,
+ SubjectUserName, SubjectUserSid\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = SimpleMemberName, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ account added to built in domain local or global group\",\"description\":\"Identifies
+ when a user account has been added to a privileged built in domain local group
+ or global group \\nsuch as the Enterprise Admins, Cert Publishers or DnsAdmins.
+ Be sure to verify this is an expected addition.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/87890d78-3e05-43ec-9ab9-ba32f4e01250\",\"name\":\"87890d78-3e05-43ec-9ab9-ba32f4e01250\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\n//Create a list of TLDs in our
+ threat feed for later validation\\nlet list_tlds = ThreatIntelligenceIndicator\\n|
+ where TimeGenerated > ago(ioc_lookBack)\\n| where isnotempty(DomainName)\\n|
+ extend parts = split(DomainName, '.')\\n| extend tld = parts[(array_length(parts)-1)]\\n|
+ summarize count() by tostring(tld)\\n| summarize make_list(tld);\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(DomainName)\\n| join (\\n SecurityAlert\\n
+ \ | where TimeGenerated > ago(dt_lookBack)\\n //Extract domain patterns
+ from message\\n | extend domain = extract(\\\"(([a-z0-9]+(-[a-z0-9]+)*\\\\\\\\.)+[a-z]{2,})\\\",
+ 1, tolower(Entities))\\n | where isnotempty(domain)\\n | extend parts
+ = split(domain, '.')\\n //Split out the TLD\\n | extend tld = parts[(array_length(parts)-1)]\\n
+ \ //Validate parsed domain by checking if the TLD is in the list of TLDs
+ in our threat feed\\n | where tld in~ (list_tlds)\\n // Converting Entities
+ into dynamic data type and use mv-expand to unpack the array\\n | extend
+ EntitiesDynamicArray = parse_json(Entities) | mv-expand EntitiesDynamicArray\\n
+ \ // Parsing relevant entity column extract hostname and IP address\\n |
+ extend EntityType = tostring(parse_json(EntitiesDynamicArray).Type), EntityAddress
+ = tostring(EntitiesDynamicArray.Address), EntityHostName = tostring(EntitiesDynamicArray.HostName)\\n
+ \ | extend HostName = iif(EntityType == 'host', EntityHostName, '')\\n |
+ extend IP_addr = iif(EntityType == 'ip', EntityAddress, '')\\n | extend
+ Alert_TimeGenerated = TimeGenerated\\n | extend Alert_Description = Description\\n)
+ on $left.DomainName==$right.domain\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Alert_TimeGenerated,
+ AlertName, Alert_Description, ProviderName, AlertSeverity, ConfidenceLevel,
+ HostName, IP_addr, Url\\n| extend timestamp = Alert_TimeGenerated, HostCustomEntity
+ = HostName, IPCustomEntity = IP_addr, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Domain entity to SecurityAlert\",\"description\":\"Identifies a match
+ in SecurityAlert table from any Domain IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"MicrosoftCloudAppSecurity\",\"dataTypes\":[\"SecurityAlert\"]},{\"connectorId\":\"AzureSecurityCenter\",\"dataTypes\":[\"SecurityAlert\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/90d3f6ec-80fb-48e0-9937-2c70c9df9bad\",\"name\":\"90d3f6ec-80fb-48e0-9937-2c70c9df9bad\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainList = dynamic([\\\"tor2web.org\\\", \\\"tor2web.com\\\",
+ \\\"torlink.co\\\", \\\"onion.to\\\", \\\"onion.ink\\\", \\\"onion.cab\\\",
+ \\\"onion.nu\\\", \\\"onion.link\\\", \\n\\\"onion.it\\\", \\\"onion.city\\\",
+ \\\"onion.direct\\\", \\\"onion.top\\\", \\\"onion.casa\\\", \\\"onion.plus\\\",
+ \\\"onion.rip\\\", \\\"onion.dog\\\", \\\"tor2web.fi\\\", \\n\\\"tor2web.blutmagie.de\\\",
+ \\\"onion.sh\\\", \\\"onion.lu\\\", \\\"onion.pet\\\", \\\"t2w.pw\\\", \\\"tor2web.ae.org\\\",
+ \\\"tor2web.io\\\", \\\"tor2web.xyz\\\", \\\"onion.lt\\\", \\n\\\"s1.tor-gateways.de\\\",
+ \\\"s2.tor-gateways.de\\\", \\\"s3.tor-gateways.de\\\", \\\"s4.tor-gateways.de\\\",
+ \\\"s5.tor-gateways.de\\\", \\\"hiddenservice.net\\\"]);\\nSyslog\\n| where
+ TimeGenerated >= ago(timeframe)\\n| where ProcessName contains \\\"squid\\\"\\n|
+ extend URL = extract(\\\"(([A-Z]+ [a-z]{4,5}:\\\\\\\\/\\\\\\\\/)|[A-Z]+ )([^
+ :]*)\\\",3,SyslogMessage), \\n SourceIP = extract(\\\"([0-9]+ )(([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3}))\\\",2,SyslogMessage),
+ \\n Status = extract(\\\"(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))\\\",1,SyslogMessage),
+ \\n HTTP_Status_Code = extract(\\\"(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))/([0-9]{3})\\\",8,SyslogMessage),\\n
+ \ User = extract(\\\"(CONNECT |GET )([^ ]* )([^ ]+)\\\",3,SyslogMessage),\\n
+ \ RemotePort = extract(\\\"(CONNECT |GET )([^ ]*)(:)([0-9]*)\\\",4,SyslogMessage),\\n
+ \ Domain = extract(\\\"(([A-Z]+ [a-z]{4,5}:\\\\\\\\/\\\\\\\\/)|[A-Z]+
+ )([^ :\\\\\\\\/]*)\\\",3,SyslogMessage),\\n Bytes = toint(extract(\\\"([A-Z]+\\\\\\\\/[0-9]{3}
+ )([0-9]+)\\\",2,SyslogMessage)),\\n contentType = extract(\\\"([a-z/]+$)\\\",1,SyslogMessage)\\n|
+ extend TLD = extract(\\\"\\\\\\\\.[a-z]*$\\\",0,Domain)\\n| where HTTP_Status_Code
+ == \\\"200\\\"\\n| where Domain contains \\\".\\\"\\n| where Domain has_any
+ (DomainList)\\n| extend timestamp = TimeGenerated, URLCustomEntity = URL,
+ IPCustomEntity = SourceIP, AccountCustomEntity = User\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Squid
+ proxy events for ToR proxies\",\"description\":\"Check for Squid proxy events
+ associated with common ToR proxies. This query presumes the default squid
+ log format is being used.\\nhttp://www.squid-cache.org/Doc/config/access_log/\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-07-12T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/97ad74c4-fdd9-4a3f-b6bf-5e28f4f71e06\",\"name\":\"97ad74c4-fdd9-4a3f-b6bf-5e28f4f71e06\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ LearningPeriod = 7d; \\nlet BinTime = 1h; \\nlet RunTime = 1h; \\nlet StartTime
+ = 1h; \\nlet NumberOfStds = 3; \\nlet MinThreshold = 10.0; \\nlet EndRunTime
+ = StartTime - RunTime; \\nlet EndLearningTime = StartTime + LearningPeriod;
+ \\nlet GitHubFailedSSOLogins = (SigninLogs \\n| where AppDisplayName == \\\"GitHub.com\\\"
+ \\n| where ResultType == 50056); \\nGitHubFailedSSOLogins \\n| where TimeGenerated
+ between (ago(EndLearningTime) .. ago(StartTime)) \\n| summarize FailedLoginsCountInBinTime
+ = count() by UserPrincipalName, bin(TimeGenerated, BinTime) \\n| summarize
+ AvgOfFailedLoginsInLearning = avg(FailedLoginsCountInBinTime), StdOfFailedLoginsInLearning
+ = stdev(FailedLoginsCountInBinTime) by UserPrincipalName, tostring(set_IPAddress)\\n|
+ extend LearningThreshold = max_of(AvgOfFailedLoginsInLearning + StdOfFailedLoginsInLearning
+ * NumberOfStds, MinThreshold) \\n| join kind=innerunique ( \\n GitHubFailedSSOLogins
+ \\n | where TimeGenerated between (ago(StartTime) .. ago(EndRunTime)) \\n
+ \ | summarize FailedLoginsCountInRunTime = count() by User = Identity \\n)
+ on UserPrincipalName \\n| where FailedLoginsCountInRunTime > LearningThreshold\\n|
+ extend AccountCustomEntity = UserPrincipalName , timestamp = TimeGenerated\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Brute
+ Force Attack against GitHub Account\",\"description\":\"Attackers who are
+ trying to guess your users' passwords or use brute-force methods to get in.
+ If your organization is using SSO with Azure Active Directory, authentication
+ logs to GitHub.com will be generated. Using the following query can help you
+ identify a sudden increase in failed logon attempt of users.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/0dd422ee-e6af-4204-b219-f59ac172e4c6\",\"name\":\"0dd422ee-e6af-4204-b219-f59ac172e4c6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"ThreatIntelligence\",\"properties\":{\"severity\":\"Medium\",\"displayName\":\"(Preview)
+ Microsoft Threat Intelligence Analytics\",\"description\":\"This rule generates
+ an alert when a Microsoft Threat Intelligence Indicator gets matched with
+ your event logs. The alerts are very high fidelity and are turned ON by default.
+ \\n\\nNote : It is advised to turn off any custom alert rules which match
+ the threat intelligence indicators with the same event logs matched by this
+ analytics to prevent duplicate alerts.\",\"tactics\":[\"Persistence\",\"LateralMovement\"],\"createdDateUTC\":\"2020-06-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CEF\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/1ce5e766-26ab-4616-b7c8-3b33ae321e80\",\"name\":\"1ce5e766-26ab-4616-b7c8-3b33ae321e80\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\n//Adjust this threshold to fit environment\\nlet signin_threshold
+ = 5; \\n//Make a list of IPs with failed Windows host logins above threshold\\nlet
+ win_fails = \\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where EventID == 4625\\n| where LogonType in (10, 7, 3)\\n| where IpAddress
+ != \\\"-\\\"\\n| summarize count() by IpAddress\\n| where count_ > signin_threshold\\n|
+ summarize make_list(IpAddress);\\n//Make a list of IPs with failed *nix host
+ logins above threshold\\nlet nix_fails = \\nSyslog\\n| where TimeGenerated
+ > ago(timeframe)\\n| where Facility contains 'auth' and ProcessName != 'sudo'\\n|
+ extend SourceIP = extract(\\\"(([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.(([0-9]{1,3})))\\\",1,SyslogMessage)\\n|
+ where SourceIP != \\\"\\\" and SourceIP != \\\"127.0.0.1\\\"\\n| summarize
+ count() by SourceIP\\n| where count_ > signin_threshold\\n| summarize make_list(SourceIP);\\n//See
+ if any of the IPs with failed host logins hve had a sucessful Azure AD login\\nSigninLogs\\n|
+ where TimeGenerated > ago(timeframe)\\n| where ResultType !in (\\\"0\\\",
+ \\\"50125\\\", \\\"50140\\\")\\n| where IPAddress in (win_fails) or IPAddress
+ in (nix_fails)\\n| extend Reason= \\\"Multiple failed host logins from IP
+ address with successful Azure AD login\\\"\\n| extend timstamp = TimeGenerated,
+ AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ host logons but success logon to AzureAD\",\"description\":\"Identifies a
+ list of IP addresses with a minimum number(default of 5) of failed logon attempts
+ to remote hosts.\\nUses that list to identify any successful logons to Azure
+ Active Directory from these IPs within the same timeframe.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-08-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]},{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/45b903c5-6f56-4969-af10-ae62ac709718\",\"name\":\"45b903c5-6f56-4969-af10-ae62ac709718\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\nSecurityEvent\\n| where TimeGenerated
+ >= ago(endtime) \\n| where EventID == 4624 and LogonType == 10\\n| summarize
+ StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount
+ = count() \\nby Account = tolower(Account), Computer = toupper(Computer),
+ IpAddress, AccountType, Activity, LogonTypeName, ProcessName\\n// use left
+ anti to exclude anything from the previous 14 days that is not rare\\n| join
+ kind=leftanti (\\nSecurityEvent\\n| where TimeGenerated between (ago(starttime)
+ .. ago(endtime))\\n| where EventID == 4624\\n| summarize by Computer = toupper(Computer),
+ IpAddress, Account = tolower(Account)\\n) on Account, Computer\\n| summarize
+ StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
+ \ \\nby Account, Computer, IpAddress, AccountType, Activity, LogonTypeName,
+ ProcessName\\n| extend timestamp = StartTime, AccountCustomEntity = Account,
+ HostCustomEntity = Computer, IPCustomEntity = IpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Rare
+ RDP Connections\",\"description\":\"Identifies when an RDP connection is new
+ or rare related to any logon type by a given account today based on comparison
+ with the previous 14 days.\\nRDP connections are indicated by the EventID
+ 4624 with LogonType = 10\",\"tactics\":[\"LateralMovement\"],\"createdDateUTC\":\"2020-01-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/1572e66b-20a7-4012-9ec4-77ec4b101bc8\",\"name\":\"1572e66b-20a7-4012-9ec4-77ec4b101bc8\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 1d;\\nlet endtime = 1h;\\nlet prev23hThreshold = 4;\\nlet prev1hThreshold
+ = 15;\\nlet Kerbevent =\\nSecurityEvent\\n| where TimeGenerated >= ago(starttime)\\n|
+ where EventID == 4769\\n| parse EventData with * 'TicketEncryptionType\\\">'
+ TicketEncryptionType \\\"<\\\" *\\n| where TicketEncryptionType == '0x17'\\n|
+ parse EventData with * 'TicketOptions\\\">' TicketOptions \\\"<\\\" *\\n|
+ where TicketOptions == '0x40810000'\\n| parse EventData with * 'Status\\\">'
+ Status \\\"<\\\" *\\n| where Status == '0x0'\\n| parse EventData with * 'ServiceName\\\">'
+ ServiceName \\\"<\\\" *\\n| where ServiceName !contains \\\"$\\\" and ServiceName
+ !contains \\\"krbtgt\\\" \\n| parse EventData with * 'TargetUserName\\\">'
+ TargetUserName \\\"<\\\" *\\n| where TargetUserName !contains \\\"$@\\\" and
+ TargetUserName !contains ServiceName\\n| parse EventData with * 'IpAddress\\\">::ffff:'
+ ClientIPAddress \\\"<\\\" *;\\nlet Kerbevent23h = Kerbevent\\n| where TimeGenerated
+ >= ago(starttime) and TimeGenerated < ago(endtime)\\n| summarize ServiceNameCountPrev23h
+ = dcount(ServiceName), ServiceNameSet23h = makeset(ServiceName) \\nby Computer,
+ TargetUserName, ClientIPAddress, TicketOptions, TicketEncryptionType, Status\\n|
+ where ServiceNameCountPrev23h < prev23hThreshold;\\nlet Kerbevent1h = \\nKerbevent\\n|
+ where TimeGenerated >= ago(endtime)\\n| summarize min(TimeGenerated), max(TimeGenerated),
+ ServiceNameCountPrev1h = dcount(ServiceName), ServiceNameSet1h = makeset(ServiceName)
+ \\nby Computer, TargetUserName, ClientIPAddress, TicketOptions, TicketEncryptionType,
+ Status;\\nKerbevent1h \\n| join kind=leftanti\\n(\\nKerbevent23h\\n) on TargetUserName\\n//
+ Threshold value set above is based on testing, this value may need to be changed
+ for your environment.\\n| where ServiceNameCountPrev1h > prev1hThreshold\\n|
+ project StartTimeUtc = min_TimeGenerated, EndTimeUtc = max_TimeGenerated,
+ TargetUserName, Computer, ClientIPAddress, TicketOptions, \\nTicketEncryptionType,
+ Status, ServiceNameCountPrev1h, ServiceNameSet1h\\n| extend timestamp = StartTimeUtc,
+ AccountCustomEntity = TargetUserName, HostCustomEntity = Computer, IPCustomEntity
+ = ClientIPAddress\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Potential
+ Kerberoasting\",\"description\":\"A service principal name (SPN) is used to
+ uniquely identify a service instance in a Windows environment. \\nEach SPN
+ is usually associated with a service account. Organizations may have used
+ service accounts with weak passwords in their environment. \\nAn attacker
+ can try requesting Kerberos ticket-granting service (TGS) service tickets
+ for any SPN from a domain controller (DC) which contains \\na hash of the
+ Service account. This can then be used for offline cracking. This hunting
+ query looks for accounts that are generating excessive \\nrequests to different
+ resources within the last hour compared with the previous 24 hours. Normal
+ users would not make an unusually large number \\nof request within a small
+ time window. This is based on 4769 events which can be very noisy so environment
+ based tweaking might be needed.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-04-01T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/532f62c1-fba6-4baa-bbb6-4a32a4ef32fa\",\"name\":\"532f62c1-fba6-4baa-bbb6-4a32a4ef32fa\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\n//Create a list of TLDs in our
+ threat feed for later validation\\nlet list_tlds = ThreatIntelligenceIndicator\\n|
+ where TimeGenerated > ago(ioc_lookBack)\\n| where isnotempty(DomainName)\\n|
+ extend parts = split(DomainName, '.')\\n| extend tld = parts[(array_length(parts)-1)]\\n|
+ summarize count() by tostring(tld)\\n| summarize make_list(tld);\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(DomainName)\\n| join (\\n Syslog\\n | where
+ TimeGenerated > ago(dt_lookBack)\\n //Extract domain patterns from syslog
+ message\\n | extend domain = extract(\\\"(([a-z0-9]+(-[a-z0-9]+)*\\\\\\\\.)+[a-z]{2,})\\\",1,
+ tolower(SyslogMessage))\\n | where isnotempty(domain)\\n | extend parts
+ = split(domain, '.')\\n //Split out the TLD\\n | extend tld = parts[(array_length(parts)-1)]\\n
+ \ //Validate parsed domain by checking if the TLD is in the list of TLDs
+ in our threat feed\\n | where tld in~ (list_tlds)\\n | extend Syslog_TimeGenerated
+ = TimeGenerated\\n) on $left.DomainName==$right.domain\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime,
+ ConfidenceScore, Syslog_TimeGenerated, SyslogMessage, Computer, ProcessName,
+ domain, HostIP, Url\\n| extend timestamp = Syslog_TimeGenerated, HostCustomEntity
+ = Computer, IPCustomEntity = HostIP, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Domain entity to Syslog\",\"description\":\"Identifies a match in Syslog
+ table from any Domain IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/5b72f527-e3f6-4a00-9908-8e4fee14da9f\",\"name\":\"5b72f527-e3f6-4a00-9908-8e4fee14da9f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1h;\\nCommonSecurityLog \\n| where TimeGenerated > ago(timeframe)
+ \\n| where isnotempty(DestinationPort) and DeviceAction !in (\\\"reset-both\\\",
+ \\\"deny\\\") \\n// filter out common usage ports. Add ports that are legitimate
+ for your environment\\n| where DestinationPort !in (\\\"443\\\", \\\"53\\\",
+ \\\"389\\\", \\\"80\\\", \\\"0\\\", \\\"880\\\", \\\"8888\\\", \\\"8080\\\")\\n|
+ where ApplicationProtocol == \\\"incomplete\\\" \\n// filter out IANA ephemeral
+ or negotiated ports as per https://en.wikipedia.org/wiki/Ephemeral_port\\n|
+ where DestinationPort !between (toint(49512) .. toint(65535)) \\n| where Computer
+ != \\\"\\\" \\n| where DestinationIP !startswith \\\"10.\\\"\\n// Filter out
+ any graceful reset reasons of AGED OUT which occurs when a TCP session closes
+ with a FIN due to aging out. \\n| where AdditionalExtensions !has \\\"reason=aged-out\\\"
+ \\n// Filter out any TCP FIN which occurs when a TCP FIN is used to gracefully
+ close half or both sides of a connection.\\n| where AdditionalExtensions !has
+ \\\"reason=tcp-fin\\\" \\n// Uncomment one of the following where clauses
+ to trigger on specific TCP reset reasons\\n// See Palo Alto article for details
+ - https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000ClUvCAK\\n//
+ TCP RST-server - Occurs when the server sends a TCP reset to the client\\n//
+ | where AdditionalExtensions has \\\"reason=tcp-rst-from-server\\\" \\n//
+ TCP RST-client - Occurs when the client sends a TCP reset to the server\\n//
+ | where AdditionalExtensions has \\\"reason=tcp-rst-from-client\\\" \\n|
+ extend reason = tostring(split(AdditionalExtensions, \\\";\\\")[3])\\n| summarize
+ StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count()
+ by DeviceName, SourceUserID, SourceIP, ApplicationProtocol, reason, DestinationPort,
+ Protocol, DeviceVendor, DeviceProduct, DeviceAction, DestinationIP\\n| where
+ count_ >= 10\\n| summarize StartTimeUtc = min(StartTimeUtc), EndTimeUtc =
+ max(EndTimeUtc), makeset(DestinationIP), totalcount = sum(count_) by DeviceName,
+ SourceUserID, SourceIP, ApplicationProtocol, reason, DestinationPort, Protocol,
+ DeviceVendor, DeviceProduct, DeviceAction\\n| extend timestamp = StartTimeUtc,
+ IPCustomEntity = SourceIP, AccountCustomEntity = SourceUserID, HostCustomEntity
+ = DeviceName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Palo
+ Alto - possible internal to external port scanning\",\"description\":\"Identifies
+ a list of internal Source IPs (10.x.x.x Hosts) that have triggered 10 or more
+ non-graceful tcp server resets from one or more Destination IPs which \\nresults
+ in an \\\"ApplicationProtocol = incomplete\\\" designation. The server resets
+ coupled with an \\\"Incomplete\\\" ApplicationProtocol designation can be
+ an indication \\nof internal to external port scanning or probing attack.
+ \\nReferences: https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000ClUvCAK
+ and\\nhttps://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000ClTaCAK\",\"tactics\":[\"Discovery\"],\"createdDateUTC\":\"2019-02-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/24f8c234-d1ff-40ec-8b73-96b17a3a9c1c\",\"name\":\"24f8c234-d1ff-40ec-8b73-96b17a3a9c1c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe =1d;\\nlet EventCountThreshold = 25;\\nlet OperationList = dynamic(\\n[\\\"SecretGet\\\",
+ \\\"KeyGet\\\", \\\"VaultGet\\\"]);\\nAzureDiagnostics\\n| where TimeGenerated
+ > ago(timeframe)\\n| extend ResultType = columnifexists(\\\"ResultType\\\",
+ \\\"None\\\"), identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ = columnifexists(\\\"identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\\\",
+ \\\"None\\\")\\n| where ResultType !~ \\\"None\\\" and isnotempty(ResultType)\\n|
+ where identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ !~ \\\"None\\\" and isnotempty(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g)\\n|
+ where ResourceType =~ \\\"VAULTS\\\" and ResultType =~ \\\"Success\\\"\\n|
+ where OperationName in (OperationList) \\n| summarize count() by identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g,
+ OperationName\\n| where count_ > EventCountThreshold \\n| join (\\nAzureDiagnostics\\n|
+ where TimeGenerated > ago(timeframe)\\n| extend ResultType = columnifexists(\\\"ResultType\\\",
+ \\\"NoResultType\\\")\\n| extend requestUri_s = columnifexists(\\\"requestUri_s\\\",
+ \\\"None\\\"), identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ = columnifexists(\\\"identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\\\",
+ \\\"None\\\")\\n| extend id_s = columnifexists(\\\"id_s\\\", \\\"None\\\"),
+ CallerIPAddress = columnifexists(\\\"CallerIPAddress\\\", \\\"None\\\"), clientInfo_s
+ = columnifexists(\\\"clientInfo_s\\\", \\\"None\\\")\\n| where ResultType
+ !~ \\\"None\\\" and isnotempty(ResultType)\\n| where identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ !~ \\\"None\\\" and isnotempty(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g)\\n|
+ where id_s !~ \\\"None\\\" and isnotempty(id_s)\\n| where CallerIPAddress
+ !~ \\\"None\\\" and isnotempty(CallerIPAddress)\\n| where clientInfo_s !~
+ \\\"None\\\" and isnotempty(clientInfo_s)\\n| where requestUri_s !~ \\\"None\\\"
+ and isnotempty(requestUri_s)\\n| where OperationName in~ (OperationList) \\n)
+ on identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ \\n| summarize EventCount=sum(count_), StartTimeUtc=min(TimeGenerated), EndTimeUtc=max(TimeGenerated),
+ TimeTriggered=makelist(TimeGenerated),OperationNameList=make_set(OperationName),
+ RequestURLList=make_set(requestUri_s), CallerIPList = make_set(CallerIPAddress),
+ \ CallerIPMax= arg_max(CallerIPAddress,*) by ResourceType, ResultType, Resource,
+ id_s, identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g,
+ clientInfo_s\\n| extend timestamp = EndTimeUtc, IPCustomEntity = CallerIPMax,
+ AccountCustomEntity = identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Mass
+ secret retrieval from Azure Key Vault\",\"description\":\"Identifies mass
+ secret retrieval from Azure Key Vault observed by a single user. \\nMass secret
+ retrival crossing a certain threshold is an indication of credential dump
+ operations or mis-configured applications. \\nYou can tweak the EventCountThreshold
+ based on average count seen in your environment \\nand also filter any known
+ sources (IP/Account) and useragent combinations based on historical analysis
+ to further reduce noise\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-07-01T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(Keyvault)\",\"dataTypes\":[\"AzureDiagnostics\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/cca3b4d9-ac39-4109-8b93-65bb284003e6\",\"name\":\"cca3b4d9-ac39-4109-8b93-65bb284003e6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n AzureActivity | where TimeGenerated
+ >= ago(dt_lookBack) and isnotempty(Caller)\\n | extend Caller = tolower(Caller)\\n
+ \ | where Caller matches regex emailregex\\n | extend AzureActivity_TimeGenerated
+ = TimeGenerated\\n)\\non $left.EmailRecipient == $right.Caller\\n| summarize
+ LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n| project
+ LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType,
+ ExpirationDateTime, ConfidenceScore, Url, AzureActivity_TimeGenerated,\\nEmailSenderName,
+ EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType,
+ Caller, Level, CallerIpAddress, Category, OperationName,\\nOperationNameValue,
+ ActivityStatus, ResourceGroup, SubscriptionId\\n| extend timestamp = AzureActivity_TimeGenerated,
+ AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress, URLCustomEntity
+ = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to AzureActivity\",\"description\":\"Identifies a match
+ in AzureActivity table from any Email IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/910124df-913c-47e3-a7cd-29e1643fa55e\",\"name\":\"910124df-913c-47e3-a7cd-29e1643fa55e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"//Adjust
+ this threshold to fit environment\\nlet signin_threshold = 5; \\n//Make a
+ list of IPs with failed AWS console logins\\nlet aws_fails = AWSCloudTrail\\n|
+ where TimeGenerated >= ago(1d)\\n| where EventName == \\\"ConsoleLogin\\\"\\n|
+ extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin) \\n|
+ where LoginResult != \\\"Success\\\"\\n| where SourceIpAddress != \\\"127.0.0.1\\\"\\n|
+ summarize count() by SourceIpAddress\\n| where count_ > signin_threshold\\n|
+ summarize make_list(SourceIpAddress);\\n//See if any of those IPs have sucessfully
+ logged into Azure AD.\\nSigninLogs\\n| where TimeGenerated >= ago(1d)\\n|
+ where ResultType !in (\\\"0\\\", \\\"50125\\\", \\\"50140\\\")\\n| where IPAddress
+ in (aws_fails) \\n| extend Reason = \\\"Multiple failed AWS Console logins
+ from IP address\\\"\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = UserPrincipalName, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ AWS Console logons but success logon to AzureAD\",\"description\":\"Identifies
+ a list of IP addresses with a minimum numbe(default of 5) of failed logon
+ attempts to AWS Console.\\nUses that list to identify any successful Azure
+ Active Directory logons from these IPs within the same timeframe.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-08-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4a3f5ed7-8da5-4ce2-af6f-c9ada45060f2\",\"name\":\"4a3f5ed7-8da5-4ce2-af6f-c9ada45060f2\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n OfficeActivity | where TimeGenerated
+ >= ago(dt_lookBack) and isnotempty(UserId)\\n | where UserId matches regex
+ emailregex\\n | extend OfficeActivity_TimeGenerated = TimeGenerated\\n)\\non
+ $left.EmailRecipient == $right.UserId\\n| summarize LatestIndicatorTime =
+ arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime,
+ ConfidenceScore, OfficeActivity_TimeGenerated,\\nEmailSenderName, EmailSourceDomain,
+ EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, UserId, ClientIP,
+ Operation, UserType, RecordType, OfficeWorkload, Parameters\\n| extend timestamp
+ = OfficeActivity_TimeGenerated, AccountCustomEntity = UserId, IPCustomEntity
+ = ClientIP, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to OfficeActivity\",\"description\":\"Identifies a match
+ in OfficeActivity table from any Email IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7b907bf7-77d4-41d0-a208-5643ff75bf9a\",\"name\":\"7b907bf7-77d4-41d0-a208-5643ff75bf9a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet Keywords = dynamic([\\\"helpdesk\\\", \\\" alert\\\",
+ \\\" suspicious\\\", \\\"fake\\\", \\\"malicious\\\", \\\"phishing\\\", \\\"spam\\\",
+ \\\"do not click\\\", \\\"do not open\\\", \\\"hijacked\\\", \\\"Fatal\\\"]);\\nOfficeActivity\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where Operation =~ \\\"New-InboxRule\\\"\\n|
+ where Parameters has \\\"Deleted Items\\\" or Parameters has \\\"Junk Email\\\"
+ \\n| extend Events=todynamic(Parameters)\\n| parse Events with * \\\"SubjectContainsWords\\\"
+ SubjectContainsWords '}'*\\n| parse Events with * \\\"BodyContainsWords\\\"
+ BodyContainsWords '}'*\\n| parse Events with * \\\"SubjectOrBodyContainsWords\\\"
+ SubjectOrBodyContainsWords '}'*\\n| where SubjectContainsWords has_any (Keywords)\\n
+ or BodyContainsWords has_any (Keywords)\\n or SubjectOrBodyContainsWords has_any
+ (Keywords)\\n| extend ClientIPAddress = case( ClientIP has \\\".\\\", tostring(split(ClientIP,\\\":\\\")[0]),
+ ClientIP has \\\"[\\\", tostring(trim_start(@'[[]',tostring(split(ClientIP,\\\"]\\\")[0]))),
+ ClientIP )\\n| extend Keyword = iff(isnotempty(SubjectContainsWords), SubjectContainsWords,
+ (iff(isnotempty(BodyContainsWords),BodyContainsWords,SubjectOrBodyContainsWords
+ )))\\n| extend RuleDetail = case(OfficeObjectId contains '/' , tostring(split(OfficeObjectId,
+ '/')[-1]) , tostring(split(OfficeObjectId, '\\\\\\\\')[-1]))\\n| summarize
+ count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by Operation, UserId, ClientIPAddress, ResultStatus, Keyword, OriginatingServer,
+ OfficeObjectId, RuleDetail\\n| extend timestamp = StartTimeUtc, IPCustomEntity
+ = ClientIPAddress, AccountCustomEntity = UserId , HostCustomEntity = OriginatingServer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malicious
+ Inbox Rule\",\"description\":\"Often times after the initial compromise the
+ attackers create inbox rules to delete emails that contain certain keywords.
+ \\n This is done so as to limit ability to warn compromised users that they've
+ been compromised. Below is a sample query that tries to detect this.\\nReference:
+ https://www.reddit.com/r/sysadmin/comments/7kyp0a/recent_phishing_attempts_my_experience_and_what/\",\"tactics\":[\"Persistence\",\"DefenseEvasion\"],\"createdDateUTC\":\"2020-03-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f2eb15bd-8a88-4b24-9281-e133edfba315\",\"name\":\"f2eb15bd-8a88-4b24-9281-e133edfba315\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n SigninLogs | where TimeGenerated
+ >= ago(dt_lookBack)\\n | extend StatusCode = tostring(Status.errorCode),
+ StatusDetails = tostring(Status.additionalDetails)\\n | extend Region =
+ tostring(LocationDetails[\\\"countryOrRegion\\\"]), State = tostring(LocationDetails[\\\"state\\\"]),
+ City = tostring(LocationDetails[\\\"city\\\"])\\n // renaming time column
+ so it is clear the log this came from\\n | extend SigninLogs_TimeGenerated
+ = TimeGenerated\\n)\\non $left.TI_ipEntity == $right.IPAddress\\n| summarize
+ LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n| project
+ LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType,
+ Url, ExpirationDateTime, ConfidenceScore, SigninLogs_TimeGenerated,\\nTI_ipEntity,
+ IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, NetworkIP,
+ NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp
+ = SigninLogs_TimeGenerated, AccountCustomEntity = UserPrincipalName, IPCustomEntity
+ = IPAddress, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to SigninLogs\",\"description\":\"Identifies a match in SigninLogs
+ from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/b31037ea-6f68-4fbd-bab2-d0d0f44c2fcf\",\"name\":\"b31037ea-6f68-4fbd-bab2-d0d0f44c2fcf\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(Url)\\n| join (\\n Syslog\\n | where TimeGenerated
+ >= ago(dt_lookBack)\\n // Extract URL from the Syslog message but only take
+ messages that include URLs\\n | extend Url = extract(\\\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\\\\\(\\\\\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)\\\",
+ 1,SyslogMessage)\\n | where isnotempty(Url)\\n | extend Syslog_TimeGenerated
+ = TimeGenerated\\n) on Url\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Syslog_TimeGenerated,
+ SyslogMessage, Computer, ProcessName, Url, HostIP\\n| extend timestamp = Syslog_TimeGenerated,
+ HostCustomEntity = Computer, IPCustomEntity = HostIP, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map URL entity to Syslog data\",\"description\":\"Identifies a match in
+ Syslog data from any URL IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]},{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/e7ec9fa6-e7f7-41ed-a34b-b956837a3ee6\",\"name\":\"e7ec9fa6-e7f7-41ed-a34b-b956837a3ee6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ startdate = 1d;\\nlet threshold = 15;\\n// Below pulls messages from syslog-authpriv
+ logs where there was an authentication failure with an unknown user.\\n//
+ IP address of system attempting logon is also extracted from the SyslogMessage
+ field. Some of these messages\\n// are aggregated.\\nlet authfail = Syslog\\n|
+ where TimeGenerated >= ago(startdate) \\n| where Facility =~ \\\"authpriv\\\"
+ \ // looks at authpriv messages\\n| where SyslogMessage contains \\\"authentication
+ failure\\\" and SyslogMessage contains \\\" uid=0\\\"\\n| parse SyslogMessage
+ with * \\\"rhost=\\\" ExternalIP\\n| project TimeGenerated, Computer, ProcessName,
+ HostIP, ExternalIP, ProcessID; \\n// Below pulls messages from syslog-authpriv
+ logs that show each instance an unknown user tried to logon. \\nlet userfail
+ = Syslog \\n| where TimeGenerated >= ago(startdate)\\n| where Facility =~
+ \\\"authpriv\\\" \\n| where SyslogMessage contains \\\"user unknown\\\"\\n|
+ project TimeGenerated, Computer, HostIP, ProcessID;\\n// Join the two log
+ messages above\\nlet userauthfail = authfail | join (userfail) on Computer,
+ HostIP, ProcessID\\n| project TimeGenerated, Computer, HostIP, ExternalIP,
+ ProcessID ;\\n// Extract the EventTime of the first logon attempt\\nlet firstfail
+ = userauthfail\\n| summarize arg_min(TimeGenerated, *) by Computer, ExternalIP\\n|
+ project Computer, ExternalIP, FirstLogonAttempt = TimeGenerated;\\n// Extract
+ the EventTime of the last logon attempt\\nlet lastfail = userauthfail\\n|
+ summarize arg_max(TimeGenerated, *) by Computer, ExternalIP\\n| project Computer,
+ ExternalIP, LatestLogonAttempt = TimeGenerated;\\n// Join first and last logon
+ attempt data and calculate the time between them (AttemptPeriodLength).\\nlet
+ faildates = firstfail | join (lastfail) on Computer, ExternalIP\\n| project
+ ExternalIP, Computer, FirstLogonAttempt, LatestLogonAttempt, TimeBetweenLogonAttempts
+ = LatestLogonAttempt - FirstLogonAttempt;\\n// Count the number of failed
+ logon attempts by External IP and internal machine\\nlet totalfails = userauthfail\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ TotalLogonAttempts = count() by ExternalIP, Computer, HostIP\\n| project StartTimeUtc,
+ EndTimeUtc, ExternalIP, Computer, HostIP, TotalLogonAttempts;\\n// Combine
+ total attempts with timing data from above\\nlet finalfails = totalfails |
+ join (faildates) on Computer, ExternalIP\\n| project StartTimeUtc, EndTimeUtc,
+ SourceAddress = ExternalIP, DestinationHost = Computer, DestinationIP = HostIP,
+ TotalLogonAttempts, FirstLogonAttempt, LatestLogonAttempt, TimeBetweenLogonAttempts\\n|
+ order by DestinationHost asc nulls last;\\nfinalfails \\n| where TotalLogonAttempts
+ >= threshold\\n| extend timestamp = StartTimeUtc, HostCustomEntity = DestinationHost,
+ IPCustomEntity = DestinationIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ logon attempts in authpriv\",\"description\":\"Identifies failed logon attempts
+ from unknown users in Syslog authpriv logs. The unknown user means the account
+ that tried to log in \\nisn't provisioned on the machine. A few hits could
+ indicate someone attempting to access a machine they aren't authorized to
+ access. \\nIf there are many of hits, especially from outside your network,
+ it could indicate a brute force attack. \\nDefault threshold for logon attempts
+ is 15.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-02-14T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3d645a88-2724-41a7-adea-db74c439cf79\",\"name\":\"3d645a88-2724-41a7-adea-db74c439cf79\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 5000;\\nSophosXGFirewall\\n| where
+ TimeGenerated >= timeframe\\n| where Log_Type =~ \\\"Firewall\\\" and Status
+ =~ \\\"Deny\\\"\\n| summarize count() by Src_IP, bin(TimeGenerated,5m)\\n|
+ where count_ > threshold\\n| extend timestamp = TimeGenerated, IPCustomEntity
+ = Src_IP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Excessive
+ Amount of Denied Connections from a Single Source\",\"description\":\"This
+ creates an incident in the event that a single source IP address generates
+ a excessive amount of denied connections.\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2020-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SophosXGFirewall\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7a58b253-0ef2-4248-b4e5-c350f15a8346\",\"name\":\"7a58b253-0ef2-4248-b4e5-c350f15a8346\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 100;\\nSymantecProxySG \\n| where TimeGenerated
+ >= timeframe\\n| where sc_filter_result =~ \\\"DENIED\\\"\\n| summarize StartTime
+ = min(TimeGenerated), EndTime = max(TimeGenerated), count() by c_ip, cs_host\\n|
+ where count_ > threshold\\n| extend timestamp = StartTime, HostCustomEntity
+ = cs_host, IPCustomEntity = c_ip\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Excessive
+ Denied Proxy Traffic\",\"description\":\"This alert creates an incident when
+ a client generates an excessive amounts of denied proxy traffic.\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SymantecProxySG\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2954d424-f786-4677-9ffc-c24c44c6e7d5\",\"name\":\"2954d424-f786-4677-9ffc-c24c44c6e7d5\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = ago(3h);\\nlet threshold = 2;\\nOkta_CL\\n| where published_t
+ >= timeframe\\n| where eventType_s =~ \\\"user.session.start\\\"\\n| where
+ outcome_result_s =~ \\\"SUCCESS\\\"\\n| summarize StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated), NumOfCountries = dcount(client_geographicalContext_country_s)
+ by actor_alternateId_s\\n| where NumOfCountries >= threshold\\n| extend timestamp
+ = StartTime, AccountCustomEntity = actor_alternateId_s\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ Login from Different Countries within 3 hours\",\"description\":\"This query
+ searches for successful user logins to the Okta Console from different countries
+ within 3 hours\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"OktaSSO\",\"dataTypes\":[\"Okta_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/19e01883-15d8-4eb6-a7a5-3276cd668388\",\"name\":\"19e01883-15d8-4eb6-a7a5-3276cd668388\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeFrame = 1d;\\nlet timeBin = 1m;\\nlet failedThreshold = 20;\\nW3CIISLog\\n|
+ where TimeGenerated >= ago(timeFrame)\\n| where scStatus in (\\\"401\\\",\\\"403\\\")\\n|
+ where csUserName != \\\"-\\\"\\n| extend scStatusFull = strcat(scStatus, \\\".\\\",scSubStatus)
+ \\n// Map common IIS codes\\n| extend scStatusFull_Friendly = case(\\nscStatusFull
+ == \\\"401.0\\\", \\\"Access denied.\\\",\\nscStatusFull == \\\"401.1\\\",
+ \\\"Logon failed.\\\",\\nscStatusFull == \\\"401.2\\\", \\\"Logon failed due
+ to server configuration.\\\",\\nscStatusFull == \\\"401.3\\\", \\\"Unauthorized
+ due to ACL on resource.\\\",\\nscStatusFull == \\\"401.4\\\", \\\"Authorization
+ failed by filter.\\\",\\nscStatusFull == \\\"401.5\\\", \\\"Authorization
+ failed by ISAPI/CGI application.\\\",\\nscStatusFull == \\\"403.0\\\", \\\"Forbidden.\\\",\\nscStatusFull
+ == \\\"403.4\\\", \\\"SSL required.\\\",\\n\\\"See - https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\\")\\n//
+ Mapping to Hex so can be mapped using website in comments above\\n| extend
+ scWin32Status_Hex = tohex(tolong(scWin32Status)) \\n// Map common win32 codes\\n|
+ extend scWin32Status_Friendly = case(\\nscWin32Status_Hex =~ \\\"775\\\",
+ \\\"The referenced account is currently locked out and cannot be logged on
+ to.\\\",\\nscWin32Status_Hex =~ \\\"52e\\\", \\\"Logon failure: Unknown user
+ name or bad password.\\\",\\nscWin32Status_Hex =~ \\\"532\\\", \\\"Logon failure:
+ The specified account password has expired.\\\",\\nscWin32Status_Hex =~ \\\"533\\\",
+ \\\"Logon failure: Account currently disabled.\\\", \\nscWin32Status_Hex =~
+ \\\"2ee2\\\", \\\"The request has timed out.\\\", \\nscWin32Status_Hex =~
+ \\\"0\\\", \\\"The operation completed successfully.\\\", \\nscWin32Status_Hex
+ =~ \\\"1\\\", \\\"Incorrect function.\\\", \\nscWin32Status_Hex =~ \\\"2\\\",
+ \\\"The system cannot find the file specified.\\\", \\nscWin32Status_Hex =~
+ \\\"3\\\", \\\"The system cannot find the path specified.\\\", \\nscWin32Status_Hex
+ =~ \\\"4\\\", \\\"The system cannot open the file.\\\", \\nscWin32Status_Hex
+ =~ \\\"5\\\", \\\"Access is denied.\\\", \\nscWin32Status_Hex =~ \\\"8009030e\\\",
+ \\\"SEC_E_NO_CREDENTIALS\\\", \\nscWin32Status_Hex =~ \\\"8009030C\\\", \\\"SEC_E_LOGON_DENIED\\\",
+ \\n\\\"See - https://msdn.microsoft.com/library/cc231199.aspx\\\")\\n// decode
+ URI when available\\n| extend decodedUriQuery = url_decode(csUriQuery)\\n//
+ Count of failed attempts from same client IP\\n| summarize makeset(decodedUriQuery),
+ makeset(csUserName), makeset(sSiteName), makeset(sPort), makeset(csUserAgent),
+ makeset(csMethod), makeset(csUriQuery), makeset(scStatusFull), makeset(scStatusFull_Friendly),
+ makeset(scWin32Status_Hex), makeset(scWin32Status_Friendly), FailedConnectionsCount
+ = count() by bin(TimeGenerated, timeBin), cIP, Computer, sIP\\n| where FailedConnectionsCount
+ >= failedThreshold\\n| project TimeGenerated, cIP, set_csUserName, set_decodedUriQuery,
+ Computer, set_sSiteName, sIP, set_sPort, set_csUserAgent, set_csMethod, set_scStatusFull,
+ set_scStatusFull_Friendly, set_scWin32Status_Hex, set_scWin32Status_Friendly,
+ FailedConnectionsCount\\n| order by FailedConnectionsCount\\n| extend timestamp
+ = TimeGenerated, HostCustomEntity = Computer, IPCustomEntity = cIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"High
+ count of failed attempts from same client IP\",\"description\":\"Identifies
+ when 20 or more failed attempts from a given client IP in 1 minute occur on
+ the IIS server.\\nThis could be indicative of an attempted brute force. This
+ could also simply indicate a misconfigured service or device.\\nRecommendations:
+ Validate that these are expected connections from the given Client IP. If
+ the client IP is not recognized, \\npotentially block these connections at
+ the edge device.\\nIf these are expected connections, verify the credentials
+ are properly configured on the system, service, application or device \\nthat
+ is associated with the client IP.\\nReferences:\\nIIS status code mapping:
+ https://support.microsoft.com/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0\\nWin32
+ Status code mapping: https://msdn.microsoft.com/library/cc231199.aspx\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-03-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4915c713-ab38-432e-800b-8e2d46933de6\",\"name\":\"4915c713-ab38-432e-800b-8e2d46933de6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ PrivateIPregex = @'^127\\\\.|^10\\\\.|^172\\\\.1[6-9]\\\\.|^172\\\\.2[0-9]\\\\.|^172\\\\.3[0-1]\\\\.|^192\\\\.168\\\\.';
+ \\nlet avgthreshold = 0;\\nlet probabilityLimit = 0.01;\\nlet startime = 7d;\\nlet
+ ssh_logins = Syslog\\n| where TimeGenerated >= ago(startime)\\n| where Facility
+ contains \\\"auth\\\" and ProcessName =~ \\\"sshd\\\"\\n| where SyslogMessage
+ has \\\"Accepted\\\"\\n| extend SourceIP = extract(\\\"(([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.(([0-9]{1,3})))\\\",1,SyslogMessage)
+ \\n| where isnotempty(SourceIP)\\n| extend ipType = iff(SourceIP matches regex
+ PrivateIPregex,\\\"private\\\" ,\\\"public\\\");\\nssh_logins \\n| summarize
+ privatecount=countif(ipType==\\\"private\\\"), publiccount=countif(ipType==\\\"public\\\")
+ by HostName, HostIP, bin(EventTime, 1d)\\n| summarize \\npublicIPLoginHistory
+ \ = make_list(pack('IPCount', publiccount, 'logon_time', EventTime)),\\nprivateIPLoginHistory
+ = make_list(pack('IPCount', privatecount, 'logon_time', EventTime)) by HostName,
+ HostIP\\n| mv-apply publicIPLoginHistory = publicIPLoginHistory on\\n(\\n
+ \ order by todatetime(publicIPLoginHistory['logon_time']) asc\\n | summarize
+ publicIPLoginCountList=make_list(toint(publicIPLoginHistory['IPCount'])),
+ publicAverage=avg(toint(publicIPLoginHistory['IPCount'])), publicStd=stdev(toint(publicIPLoginHistory['IPCount'])),
+ maxPublicLoginCount=max(toint(publicIPLoginHistory['IPCount']))\\n)\\n| mv-apply
+ privateIPLoginHistory = privateIPLoginHistory on\\n(\\n order by todatetime(privateIPLoginHistory['logon_time'])
+ asc\\n | summarize privateIPLoginCountList=make_list(toint(privateIPLoginHistory['IPCount'])),
+ privateAverage=avg(toint(privateIPLoginHistory['IPCount'])), privateStd=stdev(toint(privateIPLoginHistory['IPCount']))\\n)\\n//
+ Some logins from private IPs\\n| where privateAverage > avgthreshold\\n//
+ There is a non-zero number of logins from public IPs\\n| where publicAverage
+ > avgthreshold\\n// Approximate probability of seeing login from a public
+ IP is < 1%\\n| extend probabilityPublic = publicAverage / (privateAverage
+ + publicAverage)\\n| where probabilityPublic < probabilityLimit\\n// Today
+ has the highest number of logins from public IPs that we've seen in the last
+ week\\n| extend publicLoginCountToday = publicIPLoginCountList[-1]\\n| where
+ publicLoginCountToday >= maxPublicLoginCount\\n| extend HostCustomEntity =
+ HostName\\n// Optionally retrieve the original raw data for those logins that
+ we've identified as potentially suspect\\n// | join kind=rightsemi (\\n//
+ \ ssh_logins\\n// | where ipType == \\\"public\\\"\\n// ) on HostName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"New
+ internet-exposed SSH endpoints\",\"description\":\"Looks for SSH endpoints
+ with a history of sign-ins only from private IP addresses are accessed from
+ a public IP address.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/500c103a-0319-4d56-8e99-3cec8d860757\",\"name\":\"500c103a-0319-4d56-8e99-3cec8d860757\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ lookBack = 1d;\\nSigninLogs \\n| where TimeGenerated >= ago(lookBack)\\n|
+ where ResultType == \\\"50057\\\" \\n| where ResultDescription == \\\"User
+ account is disabled. The account has been disabled by an administrator.\\\"
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ disabledAccountLoginAttempts = count(), \\ndisabledAccountsTargeted = dcount(UserPrincipalName),
+ applicationsTargeted = dcount(AppDisplayName), disabledAccountSet = makeset(UserPrincipalName),
+ \\napplicationSet = makeset(AppDisplayName) by IPAddress\\n| order by disabledAccountLoginAttempts
+ desc\\n| join kind= leftouter (\\n // Consider these IPs suspicious - and
+ alert any related successful sign-ins\\n SigninLogs\\n | where TimeGenerated
+ >= ago(lookBack)\\n | where ResultType == 0\\n | summarize successfulAccountSigninCount
+ = dcount(UserPrincipalName), successfulAccountSigninSet = makeset(UserPrincipalName,
+ 15) by IPAddress\\n // Assume IPs associated with sign-ins from 100+ distinct
+ user accounts are safe\\n | where successfulAccountSigninCount < 100\\n)
+ on IPAddress \\n// IPs from which attempts to authenticate as disabled user
+ accounts originated, and had a non-zero success rate for some other account\\n|
+ where successfulAccountSigninCount != 0\\n| project StartTimeUtc, EndTimeUtc,
+ IPAddress, disabledAccountLoginAttempts, disabledAccountsTargeted, disabledAccountSet,
+ applicationSet, \\nsuccessfulAccountSigninCount, successfulAccountSigninSet\\n|
+ order by disabledAccountLoginAttempts\\n| extend timestamp = StartTimeUtc,
+ IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Sign-ins
+ from IPs that attempt sign-ins to disabled accounts\",\"description\":\"Identifies
+ IPs with failed attempts to sign in to one or more disabled accounts signed
+ in successfully to another account.\\nReferences: https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes\\n50057
+ - User account is disabled. The account has been disabled by an administrator.\",\"tactics\":[\"InitialAccess\",\"Persistence\"],\"createdDateUTC\":\"2019-02-11T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/b725d62c-eb77-42ff-96f6-bdc6745fc6e0\",\"name\":\"b725d62c-eb77-42ff-96f6-bdc6745fc6e0\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\nlet UserAgentAll = \\n(union isfuzzy=true\\n(OfficeActivity\\n|
+ where TimeGenerated >= ago(starttime)\\n| where isnotempty(UserAgent)\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by
+ UserAgent, SourceIP = ClientIP, Account = UserId, Type, RecordType, Operation\\n),\\n(\\nW3CIISLog\\n|
+ where TimeGenerated >= ago(starttime)\\n| where isnotempty(csUserAgent)\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by
+ UserAgent = csUserAgent, SourceIP = cIP, Account = csUserName, Type, sSiteName,
+ csMethod, csUriStem\\n),\\n(\\nAWSCloudTrail\\n| where TimeGenerated >= ago(starttime)\\n|
+ where isnotempty(UserAgent)\\n| summarize StartTime = min(TimeGenerated),
+ EndTime = max(TimeGenerated) by UserAgent, SourceIP = SourceIpAddress, Account
+ = UserIdentityUserName, Type, EventSource, EventName\\n))\\n// remove wordSize
+ blocks of non-numeric hex characters prior to word extraction\\n| extend\_UserAgentNoHexAlphas\_=\_replace(\\\"([A-Fa-f]{4,})\\\",\_\\\"x\\\",\_UserAgent)\\n//
+ once blocks of hex chars are removed, extract wordSize blocks of a-z\\n| extend\_Tokens\_=\_extract_all(\\\"([A-Za-z]{4,})\\\",
+ UserAgentNoHexAlphas)\\n// concatenate extracted words to create a summarized
+ user agent for baseline and comparison\\n| extend\_NormalizedUserAgent\_=\_strcat_array(Tokens,\_\\\"|\\\")\\n|
+ project-away\_UserAgentNoHexAlphas, Tokens;\\nUserAgentAll\\n| where StartTime
+ >= ago(endtime)\\n| summarize StartTime = min(StartTime), EndTime = max(EndTime),
+ count() by UserAgent, NormalizedUserAgent, SourceIP, Account, Type, RecordType,
+ Operation, EventSource, EventName, sSiteName, csMethod, csUriStem\\n| join
+ kind=leftanti\\n(\\nUserAgentAll\\n| where StartTime < ago(endtime)\\n| summarize
+ by NormalizedUserAgent, SourceIP, Account, Type, RecordType, Operation, EventSource,
+ EventName, sSiteName, csMethod, csUriStem\\n)\\non NormalizedUserAgent\\n|
+ extend timestamp = StartTime, IPCustomEntity = SourceIP, AccountCustomEntity
+ = Account\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"New
+ UserAgent observed in last 24 hours\",\"description\":\"Identifies new UserAgents
+ observed in the last 24 hours versus the previous 14 days. This detection
+ \\nextracts words from user agents to build the baseline and determine rareity
+ rather than perform a \\ndirect comparison. This avoids FPs caused by version
+ numbers and other high entropy user agent components.\\nThese new UserAgents
+ could be benign. However, in normally stable environments,\\nthese new UserAgents
+ could provide a starting point for investigating malicious activity.\\nNote:
+ W3CIISLog can be noisy depending on the environment, however OfficeActivity
+ and AWSCloudTrail are\\nusually stable with low numbers of detections.\",\"tactics\":[\"InitialAccess\",\"CommandAndControl\",\"Execution\"],\"createdDateUTC\":\"2019-04-01T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]},{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]},{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/d3980830-dd9d-40a5-911f-76b44dfdce16\",\"name\":\"d3980830-dd9d-40a5-911f-76b44dfdce16\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ RunTime = 1h;\\nSigninLogs\\n| where TimeGenerated > ago(RunTime)\\n| where
+ AppDisplayName == \\\"GitHub.com\\\"\\n| where ResultType == 0\\n| summarize
+ CountOfLocations = dcount(Location), Locations = make_set(Location), BurstStartTime
+ = min(TimeGenerated), BurstEndTime = max(TimeGenerated) by UserPrincipalName\\n|
+ where CountOfLocations > 1\\n| extend timestamp = BurstStartTime, AccountCustomEntity
+ = UserPrincipalName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"GitHub
+ Signin Burst from Multiple Locations\",\"description\":\"This alerts when
+ there Signin burst from multiple locations in GitHub (AAD SSO).\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/8675dd7a-795e-4d56-a79c-fc848c5ee61c\",\"name\":\"8675dd7a-795e-4d56-a79c-fc848c5ee61c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nProofPointTAPClicksPermitted_CL\\n| where TimeGenerated
+ >= timeframe\\n| where classification_s =~ \\\"malware\\\"\\n| summarize StartTime
+ = min(TimeGenerated), EndTime = max(TimeGenerated), count() by TimeGenerated,
+ Sender = sender_s, SenderIPAddress = senderIP_s, Recipient = recipient_s,
+ TimeClicked = clickTime_t, URLClicked = url_s\\n| extend timestamp = StartTime,
+ AccountCustomEntity = Recipient, IPCustomEntity = SenderIPAddress, URLCustomEntity
+ = URLClicked\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malware
+ Link Clicked\",\"description\":\"This query identifies a user clicking on
+ an email link whose threat category is classified as a malware\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ProofpointTAP\",\"dataTypes\":[\"ProofPointTAPClicksPermitted_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2d8a60aa-c15e-442e-9ce3-ee924889d2a6\",\"name\":\"2d8a60aa-c15e-442e-9ce3-ee924889d2a6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"eset_CL\\n|
+ where event_type_s == \\\"Threat_Event\\\"\\n| extend HostCustomEntity = hostname_s,
+ AccountCustomEntity = username_s, IPCustomEntity = ipv4_s\",\"queryFrequency\":\"PT5M\",\"queryPeriod\":\"PT5M\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Threats
+ detected by Eset\",\"description\":\"Escalates threats detected by Eset.\",\"tactics\":[\"Execution\",\"CredentialAccess\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2020-07-09T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"EsetSMC\",\"dataTypes\":[\"eset_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/90586451-7ba8-4c1e-9904-7d1b7c3cc4d6\",\"name\":\"90586451-7ba8-4c1e-9904-7d1b7c3cc4d6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Azure
+ Security Center\",\"displayName\":\"Create incidents based on Azure Security
+ Center alerts\",\"description\":\"Create incidents based on all alerts generated
+ in Azure Security Center\",\"createdDateUTC\":\"2019-07-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureSecurityCenter\",\"dataTypes\":[\"SecurityAlert
+ (ASC)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/69b7723c-2889-469f-8b55-a2d355ed9c87\",\"name\":\"69b7723c-2889-469f-8b55-a2d355ed9c87\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n DnsEvents | where TimeGenerated
+ >= ago(dt_lookBack)\\n | where SubType =~ \\\"LookupQuery\\\" and isnotempty(IPAddresses)\\n
+ \ | extend SingleIP = split(IPAddresses, \\\",\\\")\\n | mvexpand SingleIP\\n
+ \ | extend SingleIP = tostring(SingleIP)\\n // renaming time column so
+ it is clear the log this came from\\n | extend DNS_TimeGenerated = TimeGenerated\\n)\\non
+ $left.TI_ipEntity == $right.SingleIP\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, DNS_TimeGenerated,\\nTI_ipEntity,
+ Computer, EventId, SubType, ClientIP, Name, IPAddresses, NetworkIP, NetworkDestinationIP,
+ NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp = DNS_TimeGenerated,
+ IPCustomEntity = ClientIP, HostCustomEntity = Computer, URLCustomEntity =
+ Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to DnsEvents\",\"description\":\"Identifies a match in DnsEvents
+ from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2be4ef67-a93f-4d8a-981a-88158cb73abd\",\"name\":\"2be4ef67-a93f-4d8a-981a-88158cb73abd\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet covidIndicators = (externaldata(TimeGenerated:datetime,
+ FileHashValue:string, FileHashType: string, TlpLevel: string, Product: string,
+ ThreatType: string, Description: string )\\n[@\\\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.Covid19.Indicators.csv\\\"]
+ with (format=\\\"csv\\\"));\\nlet fileHashIndicators = covidIndicators\\n|
+ where isnotempty(FileHashValue);\\n// Handle matches against both lower case
+ and uppercase versions of the hash:\\n( fileHashIndicators | extend FileHashValue
+ = tolower(FileHashValue)\\n | union (fileHashIndicators | extend FileHashValue
+ = toupper(FileHashValue)))\\n| join (\\n CommonSecurityLog | where TimeGenerated
+ >= ago(dt_lookBack) \\n | where isnotempty(FileHash)\\n | extend CommonSecurityLog_TimeGenerated
+ = TimeGenerated\\n)\\non $left.FileHashValue == $right.FileHash\\n| summarize
+ LatestIndicatorTime = arg_max(TimeGenerated, *) by FileHashValue\\n| project
+ LatestIndicatorTime, FileHashValue, FileHashType, Description, ThreatType,
+ \ \\nCommonSecurityLog_TimeGenerated, SourceIP, SourcePort, DestinationIP,
+ DestinationPort, SourceUserID, SourceUserName, DeviceName, DeviceAction, \\nRequestURL,
+ DestinationUserName, DestinationUserID, ApplicationProtocol, Activity\\n|
+ extend timestamp = CommonSecurityLog_TimeGenerated, IPCustomEntity = SourceIP,
+ HostCustomEntity = DeviceName, AccountCustomEntity = SourceUserName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Microsoft
+ COVID-19 file hash indicator matches\",\"description\":\"Identifies a match
+ in CommonSecurityLog Event data from any FileHash published in the Microsoft
+ COVID-19 Threat Intel Feed - as described at https://www.microsoft.com/security/blog/2020/05/14/open-sourcing-covid-threat-intelligence/\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-30T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/884be6e7-e568-418e-9c12-89229865ffde\",\"name\":\"884be6e7-e568-418e-9c12-89229865ffde\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet FailureThreshold = 15;\\nlet FailedLogins = Okta_CL\\n|
+ where TimeGenerated > timeframe\\n| where eventType_s =~ \\\"user.session.start\\\"
+ and outcome_reason_s =~ \\\"VERIFICATION_ERROR\\\"\\n| summarize count() by
+ actor_alternateId_s, client_ipAddress_s, bin(TimeGenerated, 5m)\\n| where
+ count_ > FailureThreshold\\n| project client_ipAddress_s, actor_alternateId_s;\\nOkta_CL\\n|
+ where TimeGenerated > timeframe\\n| join kind=inner (FailedLogins) on client_ipAddress_s,
+ actor_alternateId_s\\n| where eventType_s =~ \\\"user.session.start\\\" and
+ outcome_reason_s =~ \\\"VERIFICATION_ERROR\\\"\\n| summarize count() by actor_alternateId_s,
+ ClientIP = client_ipAddress_s, City = client_geographicalContext_city_s, Country
+ = client_geographicalContext_country_s, published_t\\n| sort by published_t
+ desc\\n| extend timestamp = published_t, IPCustomEntity = ClientIP, AccountCustomEntity
+ = actor_alternateId_s\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ Logins from Unknown or Invalid User\",\"description\":\"This query searches
+ for numerous login attempts to the management console with an unknown or invalid
+ user name\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"OktaSSO\",\"dataTypes\":[\"Okta_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/84ad2f8a-b64c-49bc-b669-bdb4fd3071e9\",\"name\":\"84ad2f8a-b64c-49bc-b669-bdb4fd3071e9\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"eset_CL\\n|
+ where event_type_s == 'FilteredWebsites_Event'\\n| extend AccountCustomEntity
+ = username_s, URLCustomEntity = object_uri_s, HostCustomEntity = hostname_s,
+ IPCustomEntity = ipv4_s\",\"queryFrequency\":\"PT5M\",\"queryPeriod\":\"PT5M\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Web
+ sites blocked by Eset\",\"description\":\"Create alert on web sites blocked
+ by Eset.\",\"tactics\":[\"Exfiltration\",\"CommandAndControl\",\"InitialAccess\"],\"createdDateUTC\":\"2020-07-09T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"EsetSMC\",\"dataTypes\":[\"eset_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a04cf847-a832-4c60-b687-b0b6147da219\",\"name\":\"a04cf847-a832-4c60-b687-b0b6147da219\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet IPList = dynamic([\\\"45.63.52.41\\\",\\\"140.82.17.161\\\",\\\"207.148.101.95\\\",\\\"45.32.87.51\\\",\\\"66.42.98.156\\\",\\\"45.76.144.105\\\",\\\"217.163.28.35\\\",\\\"45.32.141.174\\\",\\\"149.28.165.249\\\",\\\"209.250.225.247\\\",\\\"45.63.100.115\\\",\\\"95.179.229.230\\\",\\\"209.250.233.247\\\",\\\"45.77.121.232\\\",\\\"45.76.175.65\\\",\\\"104.238.160.237\\\",\\\"45.77.181.97\\\",\\\"95.179.192.125\\\",\\\"149.28.93.184\\\",\\\"140.82.16.81\\\",\\\"45.76.173.103\\\",\\\"45.77.255.22\\\",\\\"45.32.11.71\\\",\\\"149.28.77.26\\\",\\\"45.32.54.50\\\",\\\"104.156.233.156\\\",\\\"45.32.21.118\\\",\\\"45.63.62.109\\\",\\\"45.77.244.202\\\",\\\"149.248.11.205\\\",\\\"104.238.190.244\\\"]);\\nlet
+ IOCTerms = \\\"\\\\\\\\?lang=[/..]*/dev/cmdb/sslvpn_websession|/dana-na/jam/[/..]*home/webserver/htdocs/dana/html5acc/guacamole[/..]*etc/passwd\\\\\\\\?\\\";\\n(union
+ isfuzzy=true\\n(CommonSecurityLog\\n| where TimeGenerated >= ago(1d) \\n|
+ where isnotempty(SourceIP) or isnotempty(DestinationIP)\\n| where SourceIP
+ in (IPList) or DestinationIP in (IPList) or Message has_any (IPList)\\n| extend
+ IPMatch = case(\\nSourceIP in (IPList), \\\"SourceIP\\\", \\nDestinationIP
+ in (IPList), \\\"DestinationIP\\\",\\n\\\"Message\\\") \\n| where Message
+ matches regex IOCTerms\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc
+ = max(TimeGenerated) by SourceIP, DestinationIP, DeviceProduct, DeviceAction,
+ Message, Protocol, SourcePort, DestinationPort, DeviceAddress, DeviceName,
+ IPMatch\\n| extend timestamp = StartTimeUtc, IPCustomEntity = case(IPMatch
+ == \\\"SourceIP\\\", SourceIP, IPMatch == \\\"DestinationIP\\\", DestinationIP,
+ \\\"IP in Message Field\\\") \\n),\\n(OfficeActivity\\n| where TimeGenerated
+ >= ago(1d) \\n| where isnotempty(UserAgent) and ClientIP in (IPList)\\n| where
+ UserAgent contains \\\"ExchangeServicesClient/0.0.0.0\\\"\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by SourceIP = ClientIP,
+ Account = UserId, Type, RecordType, OfficeWorkload, UserAgent, OfficeObjectId,
+ IPMatch = \\\"ClientIP\\\"\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Account, IPCustomEntity = SourceIP\\n)\\n)\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ Manganese IP and UserAgent activity\",\"description\":\"Matches IP plus UserAgent
+ IOCs in OfficeActivity data, along with IP plus Connection string information
+ in the CommonSecurityLog data related to Manganese group activity.\\nReferences:
+ \\nhttps://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44101/\\nhttps://fortiguard.com/psirt/FG-IR-18-384\",\"tactics\":[\"InitialAccess\",\"Collection\"],\"createdDateUTC\":\"2019-10-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4d500e6d-c984-43a3-9f39-7edec8dcc04d\",\"name\":\"4d500e6d-c984-43a3-9f39-7edec8dcc04d\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeRange = 1d;\\nlet scriptExtensions = dynamic([\\\".php\\\", \\\".aspx\\\",
+ \\\".asp\\\", \\\".cfml\\\"]);\\n//The number of URI's seen to be suspicious,
+ higher = less likely to be suspicious\\nlet uriThreshold = 1;\\nCommonSecurityLog\\n|
+ where TimeGenerated >= ago(timeRange)\\n// Only look at connections that were
+ allowed through the web proxy\\n| where DeviceVendor =~ \\\"Zscaler\\\" and
+ DeviceAction =~ \\\"Allowed\\\"\\n// Only look where some data was exchanged.\\n|
+ where SentBytes > 0 and ReceivedBytes > 0\\n// Extract the Domain\\n| extend
+ Domain = iff(countof(DestinationHostName,'.') >= 2, strcat(split(DestinationHostName,'.')[-2],
+ '.',split(DestinationHostName,'.')[-1]), DestinationHostName)\\n| extend GetData=iff(RequestURL
+ == \\\"?\\\", 1, 0)\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc
+ = max(TimeGenerated), makelist(RequestURL), makelist(DestinationIP), makelist(SourceIP),
+ numOfConnections = count(), make_set(RequestMethod), max(GetData), max(RequestContext)
+ by Domain\\n// Determine the number of URIs that have been visited for the
+ domain\\n| extend destinationURI = arraylength(list_RequestURL)\\n| where
+ destinationURI <= uriThreshold\\n| where tostring(list_RequestURL) has_any(scriptExtensions)\\n//Remove
+ matches with referer\\n| where max_RequestContext == \\\"\\\"\\n//Keep requests
+ where data was trasferred either in a GET with parameters or a POST\\n| where
+ set_RequestMethod in~ (\\\"POST\\\") or max_GetData == 1\\n//Defeat email
+ click tracking, may increase FN's while decreasing FP's\\n| where list_RequestURL
+ !has \\\"click\\\" and set_RequestMethod !has \\\"GET\\\"\\n| mvexpand list_RequestURL,
+ list_DestinationIP\\n| extend RequestURL = tostring(list_RequestURL), DestinationIP
+ = tostring(list_DestinationIP), ClientIP = tostring(list_SourceIP)\\n//Extend
+ custom entitites for incidents\\n| extend timestamp = StartTimeUtc, IPCustomEntity
+ = DestinationIP\\n| project-away list_RequestURL, list_DestinationIP, list_SourceIP,
+ destinationURI, Domain, StartTimeUtc, EndTimeUtc, max_GetData, max_RequestContext\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Request
+ for single resource on domain\",\"description\":\"This will look for connections
+ to a domain where only a single file is requested, this is unusual as most
+ modern web applications require additional recources. This type of activity
+ is often assocaited with malware beaconing or tracking URL's delivered in
+ emails. Developed for Zscaler but applicable to any outbound web logging.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-03-17T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Zscaler\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/d6491be0-ab2d-439d-95d6-ad8ea39277c5\",\"name\":\"d6491be0-ab2d-439d-95d6-ad8ea39277c5\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet SensitiveOperationList = dynamic(\\n[\\\"VaultDelete\\\",
+ \\\"KeyDelete\\\", \\\"SecretDelete\\\", \\\"SecretPurge\\\", \\\"KeyPurge\\\",
+ \\\"SecretBackup\\\", \\\"KeyBackup\\\"]);\\nAzureDiagnostics\\n| where TimeGenerated
+ > ago(timeframe)\\n| extend ResultType = columnifexists(\\\"ResultType\\\",
+ \\\"NoResultType\\\")\\n| extend requestUri_s = columnifexists(\\\"requestUri_s\\\",
+ \\\"None\\\"), identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ = columnifexists(\\\"identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\\\",
+ \\\"None\\\")\\n| extend id_s = columnifexists(\\\"id_s\\\", \\\"None\\\"),
+ CallerIPAddress = columnifexists(\\\"CallerIPAddress\\\", \\\"None\\\"), clientInfo_s
+ = columnifexists(\\\"clientInfo_s\\\", \\\"None\\\")\\n| where ResultType
+ !~ \\\"None\\\" and isnotempty(ResultType)\\n| where identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g
+ !~ \\\"None\\\" and isnotempty(identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g)\\n|
+ where id_s !~ \\\"None\\\" and isnotempty(id_s)\\n| where CallerIPAddress
+ !~ \\\"None\\\" and isnotempty(CallerIPAddress)\\n| where clientInfo_s !~
+ \\\"None\\\" and isnotempty(clientInfo_s)\\n| where requestUri_s !~ \\\"None\\\"
+ and isnotempty(requestUri_s)\\n| where ResourceType =~ \\\"VAULTS\\\" and
+ ResultType =~ \\\"Success\\\" \\n| where OperationName in~ (SensitiveOperationList)
+ \ \\n| summarize EventCount=count(), StartTimeUtc=min(TimeGenerated), EndTimeUtc=max(TimeGenerated),
+ TimeTriggered=makelist(TimeGenerated),OperationNameList=make_set(OperationName),
+ RequestURLList=make_set(requestUri_s), CallerIPList = make_set(CallerIPAddress),
+ \ CallerIPMax= arg_max(CallerIPAddress,*) by ResourceType, ResultType, Resource,
+ id_s, identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g,
+ clientInfo_s\\n| extend timestamp = StartTimeUtc, IPCustomEntity = CallerIPMax,
+ AccountCustomEntity = identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Sensitive
+ Azure Key Vault operations\",\"description\":\"Identifies when sensitive Azure
+ Key Vault operations are used. This includes: VaultDelete, KeyDelete, KeyDecrypt,
+ SecretDelete, SecretPurge, KeyPurge, SecretBackup, KeyBackup. \\nAny Backup
+ operations should match with expected scheduled backup activity.\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-07-01T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(Keyvault)\",\"dataTypes\":[\"AzureDiagnostics\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/737a2ce1-70a3-4968-9e90-3e6aca836abf\",\"name\":\"737a2ce1-70a3-4968-9e90-3e6aca836abf\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MLBehaviorAnalytics\",\"properties\":{\"severity\":\"Medium\",\"displayName\":\"(Preview)
+ Anomalous RDP Login Detections\",\"description\":\"This detection uses machine
+ learning (ML) to identify anomalous Remote Desktop Protocol (RDP) login activity,
+ based on Windows Security Event data. Scenarios include:\\n\\n*\\tUnusual
+ IP - This IP address has not or has rarely been seen in last 30 days.\\n*\\tUnusual
+ Geo - The IP address, city, country and ASN have not (or rarely) been seen
+ in last 30 days.\\n*\\tNew user - A new user logs in from an IP address and
+ geo location, both or either of which are not expected to be seen in the last
+ 30 days.\\n\\nAllow 7 days after this alert is enabled for Azure Sentinel
+ to build a profile of normal activity for your environment.\\t\\n\\nThis detection
+ requires a specific configuration of the data source. [Learn more](https://docs.microsoft.com/en-us/azure/sentinel/connect-windows-security-events)\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-04-02T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/b8266f81-2715-41a6-9062-42486cbc9c73\",\"name\":\"b8266f81-2715-41a6-9062-42486cbc9c73\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1h;\\nlet threshold = 200;\\nInfobloxNIOS\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where ProcessName =~ \\\"named\\\" and Log_Type =~ \\\"client\\\"\\n|
+ where isnotempty(ResponseCode)\\n| where ResponseCode =~ \\\"NXDOMAIN\\\"\\n|
+ summarize count() by Client_IP, bin(TimeGenerated,15m)\\n| where count_ >
+ threshold\\n| join kind=inner (InfobloxNIOS\\n | where TimeGenerated >=
+ ago(timeframe)\\n | where ProcessName =~ \\\"named\\\" and Log_Type =~
+ \\\"client\\\"\\n | where isnotempty(ResponseCode)\\n | where ResponseCode
+ =~ \\\"NXDOMAIN\\\"\\n ) on Client_IP\\n| extend timestamp = TimeGenerated,
+ IPCustomEntity = Client_IP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Excessive
+ NXDOMAIN DNS Queries\",\"description\":\"This creates an incident in the event
+ a client generates excessive amounts of DNS queries for non-existent domains.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"InfobloxNIOS\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/48607a29-a26a-4abf-8078-a06dbdd174a4\",\"name\":\"48607a29-a26a-4abf-8078-a06dbdd174a4\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeRange = 3d;\\nlet lookBack = 7d;\\nlet authenticationWindow = 20m;\\nlet
+ authenticationThreshold = 5;\\nlet isGUID = \\\"[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}\\\";\\nlet
+ failureCodes = dynamic([50053, 50126, 50055]); // invalid password, account
+ is locked - too many sign ins, expired password\\nlet successCodes = dynamic([0,
+ 50055, 50057, 50155, 50105, 50133, 50005, 50076, 50079, 50173, 50158, 50072,
+ 50074, 53003, 53000, 53001, 50129]);\\n// Lookup up resolved identities from
+ last 7 days\\nlet identityLookup = SigninLogs\\n| where TimeGenerated >= ago(lookBack)\\n|
+ where not(Identity matches regex isGUID)\\n| where isnotempty(UserId)\\n|
+ summarize by UserId, lu_UserDisplayName = UserDisplayName, lu_UserPrincipalName
+ = UserPrincipalName;\\n// collect window threshold breaches\\nSigninLogs\\n|
+ where TimeGenerated > ago(timeRange)\\n| where ResultType in(failureCodes)\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), make_set(ClientAppUsed),
+ count() by bin(TimeGenerated, authenticationWindow), IPAddress, AppDisplayName,
+ UserPrincipalName\\n| summarize FailedPrincipalCount = dcount(UserPrincipalName)
+ by bin(TimeGenerated, authenticationWindow), IPAddress, AppDisplayName\\n|
+ where FailedPrincipalCount >= authenticationThreshold\\n| summarize WindowThresholdBreaches
+ = count() by IPAddress\\n| join kind= inner (\\n// where we breached a threshold,
+ join the details back on all failure data\\n SigninLogs\\n| where TimeGenerated
+ > ago(timeRange)\\n| where ResultType in(failureCodes)\\n| extend FullLocation
+ = strcat(Location,'|', LocationDetails.state, '|', LocationDetails.city)\\n|
+ summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), make_set(ClientAppUsed),
+ make_set(FullLocation), FailureCount = count() by IPAddress, AppDisplayName,
+ UserPrincipalName, UserDisplayName, Identity, UserId\\n// lookup any unresolved
+ identities\\n| extend UnresolvedUserId = iff(Identity matches regex isGUID,
+ UserId, \\\"\\\")\\n| join kind= leftouter (\\n identityLookup \\n) on $left.UnresolvedUserId==$right.UserId\\n|
+ extend UserDisplayName=iff(isempty(lu_UserDisplayName), UserDisplayName, lu_UserDisplayName)\\n|
+ extend UserPrincipalName=iff(isempty(lu_UserPrincipalName), UserPrincipalName,
+ lu_UserPrincipalName)\\n| summarize StartTime = min(StartTime), EndTime =
+ max(EndTime), make_set(UserPrincipalName), make_set(UserDisplayName), make_set(set_ClientAppUsed),
+ make_set(set_FullLocation), make_list(FailureCount) by IPAddress, AppDisplayName\\n|
+ extend FailedPrincipalCount = arraylength(set_UserPrincipalName)\\n) on IPAddress\\n|
+ project IPAddress, StartTime, EndTime, TargetedApplication=AppDisplayName,
+ FailedPrincipalCount, UserPrincipalNames=set_UserPrincipalName, UserDisplayNames=set_UserDisplayName,
+ ClientAppsUsed=set_set_ClientAppUsed, Locations=set_set_FullLocation, FailureCountByPrincipal=list_FailureCount,
+ WindowThresholdBreaches\\n| join kind= inner (\\nSigninLogs // get data on
+ success vs. failure history for each IP\\n| where TimeGenerated > ago(timeRange)\\n|
+ where ResultType in(successCodes) or ResultType in(failureCodes) // success
+ or failure types\\n| summarize GlobalSuccessPrincipalCount = dcountif(UserPrincipalName,
+ (ResultType in(successCodes))), ResultTypeSuccesses = make_set_if(ResultType,
+ (ResultType in(successCodes))), GlobalFailPrincipalCount = dcountif(UserPrincipalName,
+ (ResultType in(failureCodes))), ResultTypeFailures = make_set_if(ResultType,
+ (ResultType in(failureCodes))) by IPAddress\\n| where GlobalFailPrincipalCount
+ > GlobalSuccessPrincipalCount // where the number of failed principals is
+ greater than success - eliminates FPs from IPs who authenticate successfully
+ alot and as a side effect have alot of failures\\n) on IPAddress\\n| project-away
+ IPAddress1\\n| extend timestamp=StartTime, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Password
+ spray attack against Azure AD application\",\"description\":\"Identifies evidence
+ of password spray activity against Azure AD applications by looking for failures
+ from multiple accounts from the same\\nIP address within a time window. If
+ the number of accounts breaches the threshold just once, all failures from
+ the IP address within the time range\\nare bought into the result. Details
+ on whether there were successful authentications by the IP address within
+ the time window are also included.\\nThis can be an indicator that an attack
+ was successful.\\nThe default failure acccount threshold is 5, Default time
+ window for failures is 20m and default look back window is 3 days\\nNote:
+ Due to the number of possible accounts involved in a password spray it is
+ not possible to map identities to a custom entity.\\nReferences: https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-03-26T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a3df4a32-4805-4c6d-8699-f3c888af2f67\",\"name\":\"a3df4a32-4805-4c6d-8699-f3c888af2f67\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ TimeFrame = ago(1d);\\nlet Alert1 = \\nSecurityAlert\\n| where TimeGenerated
+ > TimeFrame\\n| where AlertName == \\\"Unfamiliar sign-in properties\\\"\\n|
+ extend UserPrincipalName = tostring(parse_json(ExtendedProperties).[\\\"User
+ Account\\\"])\\n| extend Alert1Time = TimeGenerated\\n| extend Alert1 = AlertName\\n|
+ extend Alert1Severity = AlertSeverity\\n;\\nlet Alert2 = \\nSecurityAlert\\n|
+ where TimeGenerated > TimeFrame\\n| where AlertName == \\\"Atypical travel\\\"\\n|
+ extend UserPrincipalName = tostring(parse_json(ExtendedProperties).[\\\"User
+ Account\\\"])\\n| extend Alert2Time = TimeGenerated\\n| extend Alert2 = AlertName\\n|
+ extend Alert2Severity = AlertSeverity\\n| extend CurrentLocation = strcat(tostring(parse_json(tostring(parse_json(Entities)[1].Location)).CountryCode),
+ \\\"|\\\", tostring(parse_json(tostring(parse_json(Entities)[1].Location)).State),
+ \\\"|\\\", tostring(parse_json(tostring(parse_json(Entities)[1].Location)).City))\\n|
+ extend PreviousLocation = strcat(tostring(parse_json(tostring(parse_json(Entities)[2].Location)).CountryCode),
+ \\\"|\\\", tostring(parse_json(tostring(parse_json(Entities)[2].Location)).State),
+ \\\"|\\\", tostring(parse_json(tostring(parse_json(Entities)[2].Location)).City))\\n|
+ extend CurrentIPAddress = tostring(parse_json(Entities)[1].Address)\\n| extend
+ PreviousIPAddress = tostring(parse_json(Entities)[2].Address)\\n;\\nAlert1\\n|
+ join kind=inner Alert2 on UserPrincipalName\\n| where abs(datetime_diff('minute',
+ Alert1Time, Alert2Time)) <=10\\n| extend TimeDelta = Alert1Time - Alert2Time\\n|
+ project UserPrincipalName, Alert1, Alert1Time, Alert1Severity, Alert2, Alert2Time,
+ Alert2Severity, TimeDelta, CurrentLocation, PreviousLocation, CurrentIPAddress,
+ PreviousIPAddress\\n| extend AccountCustomEntity = UserPrincipalName\\n| extend
+ IPCustomEntity = CurrentIPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Correlate
+ Unfamiliar sign-in properties and atypical travel alerts\",\"description\":\"When
+ a user has both an Unfamiliar sign-in properties alert and an Atypical travel
+ alert within 20 minutes, the alert should be handled with a higher severity\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-09-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectoryIdentityProtection\",\"dataTypes\":[\"SecurityAlert
+ (IPC)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f8dad4e9-3f19-4d70-ab7f-8f19ccd43a3e\",\"name\":\"f8dad4e9-3f19-4d70-ab7f-8f19ccd43a3e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 1;\\nAzureDiagnostics\\n | where
+ TimeGenerated >= timeframe\\n | where OperationName in (\\\"AzureFirewallApplicationRuleLog\\\",\\\"AzureFirewallNetworkRuleLog\\\")\\n
+ \ | extend msg_s_replaced0 = replace(@\\\"\\\\s\\\\s\\\",@\\\" \\\",msg_s)\\n
+ \ | extend msg_s_replaced1 = replace(@\\\"\\\\.\\\\s\\\",@\\\" \\\",msg_s_replaced0)\\n
+ \ | extend msg_a = split(msg_s_replaced1,\\\" \\\")\\n | extend srcAddr_a
+ = split(msg_a[3],\\\":\\\") , destAddr_a = split(msg_a[5],\\\":\\\")\\n |
+ extend protocol = tostring(msg_a[0]), srcIp = tostring(srcAddr_a[0]), srcPort
+ = tostring(srcAddr_a[1]), destIp = tostring(destAddr_a[0]), destPort = tostring(destAddr_a[1]),
+ action = tostring(msg_a[7])\\n | where action == \\\"Deny\\\"\\n | extend
+ url = iff(destIp matches regex \\\"\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\\\",\\\"\\\",destIp)\\n
+ \ | summarize StartTime = min(TimeGenerated), count() by srcIp, destIp,
+ url, action, protocol\\n | where count_ >= [\\\"threshold\\\"]\\n |
+ extend timestamp = StartTime, URLCustomEntity = url, IPCustomEntity = srcIp\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":1,\"displayName\":\"Several
+ deny actions registered\",\"description\":\"Identifies attack pattern when
+ attacker tries to move, or scan, from resource to resource on the network
+ and creates an incident when a source has more than 1 registered deny action
+ in Azure Firewall.\",\"tactics\":[\"Discovery\",\"LateralMovement\",\"CommandAndControl\"],\"createdDateUTC\":\"2020-10-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureFirewall\",\"dataTypes\":[\"AzureDiagnostics\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/d25b1998-a592-4bc5-8a3a-92b39eedb1bc\",\"name\":\"d25b1998-a592-4bc5-8a3a-92b39eedb1bc\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nAWSCloudTrail\\n| where TimeGenerated > ago(timeframe)\\n|
+ where EventName =~ \\\"ConsoleLogin\\\" \\n| extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed),
+ LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)\\n| where
+ MFAUsed !~ \\\"Yes\\\" and LoginResult !~ \\\"Failure\\\"\\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by EventName, EventTypeName,
+ LoginResult, MFAUsed, UserIdentityAccountId, UserIdentityPrincipalid, UserAgent,
+ \\nUserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress, AWSRegion\\n|
+ extend timestamp = StartTimeUtc, AccountCustomEntity = UserIdentityUserName,
+ IPCustomEntity = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Login
+ to AWS Management Console without MFA\",\"description\":\"Multi-Factor Authentication
+ (MFA) helps you to prevent credential compromise. This alert identifies logins
+ to the AWS Management Console without MFA.\\nYou can limit this detection
+ to trigger for adminsitrative accounts if you do not have MFA enabled on all
+ accounts.\\nThis is done by looking at the eventName ConsoleLogin and if the
+ AdditionalEventData field indicates MFA was NOT used \\nand the ResponseElements
+ field indicates NOT a Failure. Thereby indicating that a non-MFA login was
+ successful.\",\"tactics\":[\"DefenseEvasion\",\"PrivilegeEscalation\",\"Persistence\",\"InitialAccess\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/6c360107-f3ee-4b91-9f43-f4cfd90441cf\",\"name\":\"6c360107-f3ee-4b91-9f43-f4cfd90441cf\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)
+ \\n| where EventID == 4738\\n// 2089 value indicates the Don't Expire Password
+ value has been set\\n| where UserAccountControl has \\\"%%2089\\\" \\n| extend
+ Value_2089 = iff(UserAccountControl has \\\"%%2089\\\",\\\"'Don't Expire Password'
+ - Disabled\\\", \\\"Not Changed\\\")\\n// 2050 indicates that the Password
+ Not Required value is NOT set, this often shows up at the same time as a 2089
+ and is the recommended value. This value may not be in the event. \\n| extend
+ Value_2050 = iff(UserAccountControl has \\\"%%2050\\\",\\\"'Password Not Required'
+ - Disabled\\\", \\\"Not Changed\\\")\\n// If value %%2082 is present in the
+ 4738 event, this indicates the account has been configured to logon WITHOUT
+ a password. Generally you should only see this value when an account is created
+ and only in Event 4720: Account Creation Event. \\n| extend Value_2082 =
+ iff(UserAccountControl has \\\"%%2082\\\",\\\"'Password Not Required' - Enabled\\\",
+ \\\"Not Changed\\\")\\n| project StartTimeUtc = TimeGenerated, EventID, Computer,
+ TargetUserName, TargetDomainName, AccountType, UserAccountControl, Value_2089,
+ Value_2050, Value_2082\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = TargetUserName, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"AD
+ account with don't expire password - disabled\",\"description\":\"Identifies
+ whenever a user account has the setting \\\"Password Never Expires\\\" in
+ the user account properties selected.\\nThis is indicated in Security event
+ 4738 in the EventData item labeled UserAccountControl with an included value
+ of %%2089 \\n%%2089 resolves to \\\"Don't Expire Password - Disabled\\\".\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2019-01-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/7efc75ce-e2a4-400f-a8b1-283d3b0f2c60\",\"name\":\"7efc75ce-e2a4-400f-a8b1-283d3b0f2c60\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet WellKnownLocalSID = \\\"S-1-5-32-5[0-9][0-9]$\\\";\\nlet
+ WellKnownGroupSID = \\\"S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-498$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1000$\\\";\\nlet
+ AC_Add = \\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)\\n// Event
+ ID related to member addition.\\n| where EventID in (4728, 4732,4756) \\n|
+ where TargetSid matches regex WellKnownLocalSID or TargetSid matches regex
+ WellKnownGroupSID \\n| parse EventData with * '\\\"MemberName\\\">' AccountAdded
+ \\\",OU\\\" * \\n| where isnotempty(AccountAdded)\\n| extend GroupAddedTo
+ = TargetUserName, AddingAccount = Account \\n| extend AccountAdded_GroupAddedTo_AddingAccount
+ = strcat(AccountAdded, \\\"||\\\", GroupAddedTo, \\\"||\\\", AddingAccount
+ )\\n| project AccountAdded_GroupAddedTo_AddingAccount, AccountAddedTime =
+ TimeGenerated;\\nlet AC_Remove = \\nSecurityEvent\\n| where TimeGenerated
+ >= ago(timeframe)\\n// Event IDs related to member removal.\\n| where EventID
+ in (4729,4733,4757)\\n| where TargetSid matches regex WellKnownLocalSID or
+ TargetSid matches regex WellKnownGroupSID \\n| parse EventData with * '\\\"MemberName\\\">'
+ AccountRemoved \\\",OU\\\" * \\n| where isnotempty(AccountRemoved)\\n| extend
+ GroupRemovedFrom = TargetUserName, RemovingAccount = Account\\n| extend AccountRemoved_GroupRemovedFrom_RemovingAccount
+ = strcat(AccountRemoved, \\\"||\\\", GroupRemovedFrom, \\\"||\\\", RemovingAccount)\\n|
+ project AccountRemoved_GroupRemovedFrom_RemovingAccount, AccountRemovedTime
+ = TimeGenerated, Computer, RemovedAccountId = tolower(AccountRemoved), \\nRemovedByUser
+ = SubjectUserName, RemovedByUserLogonId = SubjectLogonId, GroupRemovedFrom
+ = TargetUserName, TargetDomainName; \\nAC_Add \\n| join kind= inner AC_Remove
+ on $left.AccountAdded_GroupAddedTo_AddingAccount == $right.AccountRemoved_GroupRemovedFrom_RemovingAccount
+ \\n| extend DurationinSecondAfter_Removed = datetime_diff ('second', AccountRemovedTime,
+ AccountAddedTime)\\n| where DurationinSecondAfter_Removed > 0\\n| project-away
+ AccountRemoved_GroupRemovedFrom_RemovingAccount\\n| extend timestamp = AccountAddedTime,
+ AccountCustomEntity = RemovedAccountId, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Account
+ added and removed from privileged groups\",\"description\":\"Identifies accounts
+ that are added to privileged group and then quickly removed, which could be
+ a sign of compromise.' \",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-04-03T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2ca4e7fc-c61a-49e5-9736-5da8035c47e0\",\"name\":\"2ca4e7fc-c61a-49e5-9736-5da8035c47e0\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 8;\\nCarbonBlackNotifications_CL\\n|
+ where TimeGenerated > timeframe\\n| where threatHunterInfo_score_d >= threshold\\n|
+ extend eventTime = datetime(1970-01-01) + tolong(threatHunterInfo_time_d/1000)
+ * 1sec\\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated),
+ count() by eventTime, Threat_Name = threatHunterInfo_reportName_s, Device_Name
+ = deviceInfo_deviceName_s, Internal_IP = deviceInfo_internalIpAddress_s,
+ External_IP = deviceInfo_externalIpAddress_s, Threat_Score = threatHunterInfo_score_d\\n|
+ project-away count_\\n| extend timestamp = StartTime, HostCustomEntity = Device_Name,
+ IPCustomEntity = Internal_IP\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Critical
+ Threat Detected\",\"description\":\"This creates an incident in the event
+ a critical threat was identified on a Carbon Black managed endpoint.\",\"tactics\":[\"LateralMovement\"],\"createdDateUTC\":\"2020-06-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"VMwareCarbonBlack\",\"dataTypes\":[\"CarbonBlackNotifications_CL\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/26a3b261-b997-4374-94ea-6c37f67f4f39\",\"name\":\"26a3b261-b997-4374-94ea-6c37f67f4f39\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = dynamic([\\\"asyspy256.ddns.net\\\",\\\"hotkillmail9sddcc.ddns.net\\\",\\\"rosaf112.ddns.net\\\",\\\"cvdfhjh1231.myftp.biz\\\",\\\"sz2016rose.ddns.net\\\",\\\"dffwescwer4325.myftp.biz\\\",\\\"cvdfhjh1231.ddns.net\\\"]);\\nlet
+ SHA1Hash = dynamic ([\\\"53a44c2396d15c3a03723fa5e5db54cafd527635\\\", \\\"9c5e496921e3bc882dc40694f1dcc3746a75db19\\\",
+ \\\"aeb573accfd95758550cf30bf04f389a92922844\\\", \\\"79ef78a797403a4ed1a616c68e07fff868a8650a\\\",
+ \\\"4f6f38b4cec35e895d91c052b1f5a83d665c2196\\\", \\\"1e8c2cac2e4ce7cbd33c3858eb2e24531cb8a84d\\\",
+ \\\"e841a63e47361a572db9a7334af459ddca11347a\\\", \\\"c28f606df28a9bc8df75a4d5e5837fc5522dd34d\\\",
+ \\\"2e94b305d6812a9f96e6781c888e48c7fb157b6b\\\", \\\"dd44133716b8a241957b912fa6a02efde3ce3025\\\",
+ \\\"8793bf166cb89eb55f0593404e4e933ab605e803\\\", \\\"a39b57032dbb2335499a51e13470a7cd5d86b138\\\",
+ \\\"41cc2b15c662bc001c0eb92f6cc222934f0beeea\\\", \\\"d209430d6af54792371174e70e27dd11d3def7a7\\\",
+ \\\"1c6452026c56efd2c94cea7e0f671eb55515edb0\\\", \\\"c6b41d3afdcdcaf9f442bbe772f5da871801fd5a\\\",
+ \\\"4923d460e22fbbf165bbbaba168e5a46b8157d9f\\\", \\\"f201504bd96e81d0d350c3a8332593ee1c9e09de\\\",
+ \\\"ddd2db1127632a2a52943a2fe516a2e7d05d70d2\\\"]);\\nlet SHA256Hash = dynamic
+ ([\\\"9ae7c4a4e1cfe9b505c3a47e66551eb1357affee65bfefb0109d02f4e97c06dd\\\",
+ \\\"7772d624e1aed327abcd24ce2068063da0e31bb1d5d3bf2841fc977e198c6c5b\\\",
+ \\\"657fc7e6447e0065d488a7db2caab13071e44741875044f9024ca843fe4e86b5\\\",
+ \\\"2ef157a97e28574356e1d871abf75deca7d7a1ea662f38b577a06dd039dbae29\\\",
+ \\\"52fd7b90d7144ac448af4008be639d4d45c252e51823f4311011af3207a5fc77\\\",
+ \\\"a370e47cb97b35f1ae6590d14ada7561d22b4a73be0cb6df7e851d85054b1ac3\\\",
+ \\\"5bf80b871278a29f356bd42af1e35428aead20cd90b0c7642247afcaaa95b022\\\",
+ \\\"6f690ccfd54c2b02f0c3cb89c938162c10cbeee693286e809579c540b07ed883\\\",
+ \\\"3c884f776fbd16597c072afd81029e8764dd57ee79d798829ca111f5e170bd8e\\\",
+ \\\"1922a419f57afb351b58330ed456143cc8de8b3ebcbd236d26a219b03b3464d7\\\",
+ \\\"fe0e4ef832b62d49b43433e10c47dc51072959af93963c790892efc20ec422f1\\\",
+ \\\"7ce9e1c5562c8a5c93878629a47fe6071a35d604ed57a8f918f3eadf82c11a9c\\\",
+ \\\"178d5ee8c04401d332af331087a80fb4e5e2937edfba7266f9be34a5029b6945\\\",
+ \\\"51f70956fa8c487784fd21ab795f6ba2199b5c2d346acdeef1de0318a4c729d9\\\",
+ \\\"889bca95f1a69e94aaade1e959ed0d3620531dc0fc563be9a8decf41899b4d79\\\",
+ \\\"332ddaa00e2eb862742cb8d7e24ce52a5d38ffb22f6c8bd51162bd35e84d7ddf\\\",
+ \\\"44bcf82fa536318622798504e8369e9dcdb32686b95fcb44579f0b4efa79df08\\\",
+ \\\"63552772fdd8c947712a2cff00dfe25c7a34133716784b6d486227384f8cf3ef\\\",
+ \\\"056744a3c371b5938d63c396fe094afce8fb153796a65afa5103e1bffd7ca070\\\"]);\\nlet
+ SigNames = dynamic([\\\"TrojanDropper:Win32/BlackMould.A!dha\\\", \\\"Trojan:Win32/BlackMould.B!dha\\\",
+ \\\"Trojan:Win32/QuarkBandit.A!dha\\\", \\\"Trojan:Win32/Sidelod.A!dha\\\"]);\\n(union
+ isfuzzy=true\\n(CommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse Message with * '(' DNSName ')' * \\n| where isnotempty(FileHash)\\n|
+ where FileHash in (SHA256Hash) or DNSName in~ (DomainNames)\\n| extend Account
+ = SourceUserID, Computer = DeviceName, IPAddress = SourceIP\\n),\\n(DnsEvents
+ \\n| where TimeGenerated >= ago(timeframe) \\n| extend DNSName = Name\\n|
+ where isnotempty(DNSName)\\n| where DNSName in~ (DomainNames)\\n| extend
+ IPAddress = ClientIP\\n),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse RemoteDnsCanonicalNames with * '[\\\"' DNSName '\\\"]' *\\n| where
+ isnotempty(DNSName)\\n| where DNSName in~ (DomainNames)\\n| extend IPAddress
+ = RemoteIp\\n),\\n(Event\\n//This query uses sysmon data depending on table
+ name used this may need updataing\\n| where TimeGenerated >= ago(3d)\\n| where
+ Source == \\\"Microsoft-Windows-Sysmon\\\"\\n| extend EvData = parse_xml(EventData)\\n|
+ extend EventDetail = EvData.DataItem.EventData.Data\\n| extend Hashes = EventDetail.[16].[\\\"#text\\\"]\\n|
+ parse Hashes with * 'SHA1=' SHA1 ',' * \\n| where isnotempty(Hashes)\\n| where
+ Hashes in (SHA1Hash) \\n| extend Account = UserName\\n),\\n(SecurityAlert\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where Entities has_any (SigNames)\\n|
+ extend Computer = tostring(parse_json(Entities)[0].HostName) \\n)\\n)\\n|
+ extend timestamp = TimeGenerated, AccountCustomEntity = Account, HostCustomEntity
+ = Computer, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ GALLIUM domains and hashes\",\"description\":\"GALLIUM command and control
+ domains and hash values for tools and malware used by GALLIUM. \\n Matches
+ domain name IOCs related to the GALLIUM activity group with CommonSecurityLog,
+ DnsEvents, VMConnection and SecurityEvents dataTypes.\\n References: https://www.microsoft.com/security/blog/2019/12/12/gallium-targeting-global-telecom/
+ \",\"tactics\":[\"CommandAndControl\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-12-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/15ae38a2-2e29-48f7-883f-863fb25a5a06\",\"name\":\"15ae38a2-2e29-48f7-883f-863fb25a5a06\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 8d;\\nlet endtime = 1d;\\nlet threshold = 10;\\nDnsEvents \\n|
+ where TimeGenerated > ago(endtime)\\n| where Name contains \\\"in-addr.arpa\\\"
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ dcount(Name) by ClientIP\\n| where dcount_Name > threshold\\n| project StartTimeUtc,
+ EndTimeUtc, ClientIP , dcount_Name \\n| join kind=leftanti (DnsEvents \\n
+ \ | where TimeGenerated between(ago(starttime)..ago(endtime))\\n | where
+ Name contains \\\"in-addr.arpa\\\" \\n | summarize dcount(Name) by ClientIP,
+ bin(TimeGenerated, 1d)\\n | where dcount_Name > threshold\\n | project
+ ClientIP , dcount_Name \\n) on ClientIP\\n| extend timestamp = StartTimeUtc,
+ IPCustomEntity = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P8D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Rare
+ client observed with high reverse DNS lookup count\",\"description\":\"Identifies
+ clients with a high reverse DNS counts which could be carrying out reconnaissance
+ or discovery activity.\\nAlert is generated if the IP performing such reverse
+ DNS lookups was not seen doing so in the preceding 7-day period.\",\"tactics\":[\"Discovery\"],\"createdDateUTC\":\"2019-02-07T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/b2c15736-b9eb-4dae-8b02-3016b6a45a32\",\"name\":\"b2c15736-b9eb-4dae-8b02-3016b6a45a32\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\n// The number of operations below which
+ an IP address is considered an unusual source of role assignment operations\\nlet
+ alertOperationThreshold = 5;\\nlet createRoleAssignmentActivity = AzureActivity\\n|
+ where OperationName == \\\"Create role assignment\\\";\\ncreateRoleAssignmentActivity
+ \\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\\n| summarize
+ count() by CallerIpAddress, Caller\\n| where count_ >= alertOperationThreshold\\n|
+ join kind = rightanti ( \\ncreateRoleAssignmentActivity\\n| where TimeGenerated
+ > ago(endtime)\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc
+ = max(TimeGenerated), ActivityTimeStamp = makelist(TimeGenerated), ActivityStatus
+ = makelist(ActivityStatus), \\nOperationIds = makelist(OperationId), CorrelationId
+ = makelist(CorrelationId), ActivityCountByCallerIPAddress = count() \\nby
+ ResourceId, CallerIpAddress, Caller, OperationName, Resource, ResourceGroup\\n)
+ on CallerIpAddress, Caller\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Caller, IPCustomEntity = CallerIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Suspicious
+ granting of permissions to an account\",\"description\":\"Identifies IPs from
+ which users grant access to other users on azure resources and alerts when
+ a previously unseen source IP address is used.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-05T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/194dd92e-d6e7-4249-85a5-273350a7f5ce\",\"name\":\"194dd92e-d6e7-4249-85a5-273350a7f5ce\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nOfficeActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where UserType in~ (\\\"Admin\\\",\\\"DcAdmin\\\") \\n// Only admin or global-admin
+ can disable audit logging\\n| where Operation =~ \\\"Set-AdminAuditLogConfig\\\"
+ \\n| extend AdminAuditLogEnabledValue = tostring(parse_json(tostring(parse_json(tostring(array_slice(parse_json(Parameters),3,3)))[0])).Value)\\n|
+ where AdminAuditLogEnabledValue =~ \\\"False\\\" \\n| summarize StartTimeUtc
+ = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count()
+ by Operation, UserType, UserId, ClientIP, ResultStatus, Parameters, AdminAuditLogEnabledValue\\n|
+ extend timestamp = StartTimeUtc, AccountCustomEntity = UserId, IPCustomEntity
+ = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Exchange
+ AuditLog disabled\",\"description\":\"Identifies when the exchange audit logging
+ has been disabled which may be an adversary attempt\\nto evade detection or
+ avoid other defenses.\",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2019-04-15T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/ba144bf8-75b8-406f-9420-ed74397f9479\",\"name\":\"ba144bf8-75b8-406f-9420-ed74397f9479\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\n//Set a threshold of failed AAD signins from an IP address
+ within 1 day above which we want to deem those logins suspicious.\\nlet signin_threshold
+ = 5; \\n//Make a list of IPs with AAD signin failures above our threshold.\\nlet
+ suspicious_signins = \\n SigninLogs\\n | where TimeGenerated >= ago(timeframe)\\n
+ \ //Looking for logon failure results\\n | where ResultType !in (\\\"0\\\",
+ \\\"50125\\\", \\\"50140\\\")\\n //Exclude localhost addresses to reduce
+ the chance of FPs\\n | where IPAddress != \\\"127.0.0.1\\\"\\n | summarize
+ count() by IPAddress\\n | where count_ > signin_threshold\\n | summarize
+ make_list(IPAddress);\\n//See if any of those IPs have sucessfully logged
+ into PA VPNs during the same timeperiod\\nCommonSecurityLog\\n | where
+ TimeGenerated > ago(timeframe)\\n //Select only PA VPN sucessful logons\\n
+ \ | where DeviceVendor == \\\"Palo Alto Networks\\\" and DeviceEventClassID
+ == \\\"globalprotect\\\"\\n | where Message has \\\"GlobalProtect gateway
+ user authentication succeeded\\\"\\n //Parse out the logon source IP from
+ the Message field to match on\\n | extend SourceIP = extract(\\\"Login
+ from: ([^,]+)\\\", 1, Message) \\n | where SourceIP in (suspicious_signins)\\n
+ \ | extend Reason = \\\"Multiple failed AAD logins from SourceIP\\\"\\n
+ \ //Parse out other useful information from Message field\\n | extend
+ User = extract(\\\"User name: ([^,]+)\\\", 1, Message) \\n | extend ClientOS
+ = extract(\\\"Client OS version: ([^,\\\\\\\"]+)\\\", 1, Message)\\n |
+ extend Location = extract(\\\"Source region: ([^,]{2})\\\",1, Message)\\n
+ \ | project TimeGenerated, Reason, SourceIP, User, ClientOS, Location, Message,
+ DeviceName, ReceiptTime, DeviceVendor, DeviceEventClassID, Computer, FileName\\n
+ \ | extend AccountCustomEntity = User, IPCustomEntity = SourceIP, timestamp
+ = TimeGenerated, HostCustomEntity = DeviceName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"IP
+ with multiple failed Azure AD logins successfully logs in to Palo Alto VPN\",\"description\":\"This
+ query creates a list of IP addresses with a number failed login attempts to
+ AAD \\nabove a set threshold. It then looks for any successful Palo Alto
+ VPN logins from any\\nof these IPs within the same timeframe.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-09-04T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/62085097-d113-459f-9ea7-30216f2ee6af\",\"name\":\"62085097-d113-459f-9ea7-30216f2ee6af\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 2d;\\nlet endtime = 1d;\\nSecurityEvent\\n// include yesterday
+ and not today, so we can confirm a match occurs within the next day\\n| where
+ TimeGenerated >= startofday(ago(starttime)) and TimeGenerated <= startofday(ago(endtime))
+ \ \\n// 4722: User Account Enabled\\n| where EventID == 4722 \\n// Removing
+ Machine Accounts\\n| where TargetUserName !endswith \\\"$\\\" \\n| join kind=
+ leftanti (\\n SecurityEvent\\n //verify over the last 2 days\\n | where
+ TimeGenerated >= startofday(ago(starttime))\\n // Attempt made to change
+ password\\n | where EventID == 4723\\n // Removing Machine Accounts\\n |
+ where TargetUserName !endswith \\\"$\\\"\\n) on TargetUserName, TargetDomainName\\n|
+ project StartTimeUtc = TimeGenerated, EventID, Computer, TargetUserName, TargetDomainName,
+ SubjectUserName\\n| extend timestamp = StartTimeUtc, AccountCustomEntity =
+ TargetUserName, HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P2D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"AD
+ user created password not set within 24-48 hours\",\"description\":\"Identifies
+ whenever a new account is created with a default password and password is
+ not changed within 24-48 hours.\\nSimple version, can be more precise with
+ Windowing, but not necessary if run as an alert on a daily basis.\\nEffectively,
+ there is an event 4722 indicating a user enabled and no event 4723 indicating
+ a password was changed within in that day or the next day.\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2019-01-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4acd3a04-2fad-4efc-8a4b-51476594cec4\",\"name\":\"4acd3a04-2fad-4efc-8a4b-51476594cec4\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ triThreshold = 500;\\nlet startTime = 6h;\\nlet dgaLengthThreshold = 8;\\n//
+ fetch the alexa top 1M domains\\nlet top1M = (externaldata (Position:int,
+ Domain:string) [@\\\"http://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip\\\"]
+ \ with (format=\\\"csv\\\", zipPattern=\\\"*.csv\\\"));\\n// extract tri grams
+ that are above our threshold - i.e. are common\\nlet triBaseline = top1M\\n|
+ extend Domain = tolower(extract(\\\"([^.]*).{0,7}$\\\", 1, Domain))\\n| extend
+ AllTriGrams = array_concat(extract_all(\\\"(...)\\\", Domain), extract_all(\\\"(...)\\\",
+ substring(Domain, 1)), extract_all(\\\"(...)\\\", substring(Domain, 2)))\\n|
+ mvexpand Trigram=AllTriGrams\\n| summarize triCount=count() by tostring(Trigram)\\n|
+ sort by triCount desc\\n| where triCount > triThreshold\\n| distinct Trigram;\\n//
+ collect domain information from common security log, filter and extract the
+ DGA candidate and its trigrams\\nlet allDataSummarized = CommonSecurityLog\\n|
+ where TimeGenerated > ago(startTime)\\n| where isnotempty(DestinationHostName)\\n|
+ extend Name = tolower(DestinationHostName)\\n| distinct Name\\n| where Name
+ has \\\".\\\"\\n| where Name !endswith \\\".home\\\" and Name !endswith \\\".lan\\\"\\n//
+ extract DGA candidate\\n| extend DGADomain = extract(\\\"([^.]*).{0,7}$\\\",
+ 1, Name)\\n| where strlen(DGADomain) > dgaLengthThreshold\\n// throw out domains
+ with number in them\\n| where DGADomain matches regex \\\"^[A-Za-z]{0,}$\\\"\\n//
+ extract the tri grams from summarized data\\n| extend AllTriGrams = array_concat(extract_all(\\\"(...)\\\",
+ DGADomain), extract_all(\\\"(...)\\\", substring(DGADomain, 1)), extract_all(\\\"(...)\\\",
+ substring(DGADomain, 2)));\\n// throw out domains that have repeating tri's
+ and/or >=3 repeating letters\\nlet nonRepeatingTris = allDataSummarized\\n|
+ join kind=leftanti\\n(\\n allDataSummarized\\n | mvexpand AllTriGrams\\n
+ \ | summarize count() by tostring(AllTriGrams), DGADomain\\n | where
+ count_ > 1\\n | distinct DGADomain\\n)\\non DGADomain;\\n// find domains
+ that do not have a common tri in the baseline\\nlet dataWithRareTris = nonRepeatingTris\\n|
+ join kind=leftanti\\n(\\n nonRepeatingTris\\n | mvexpand AllTriGrams\\n
+ \ | extend Trigram = tostring(AllTriGrams)\\n | distinct Trigram, DGADomain\\n
+ \ | join kind=inner\\n (\\n triBaseline\\n )\\n on Trigram\\n
+ \ | distinct DGADomain\\n)\\non DGADomain;\\ndataWithRareTris\\n// join
+ DGAs back on connection data\\n| join kind=inner\\n(\\n CommonSecurityLog\\n
+ \ | where TimeGenerated > ago(startTime)\\n | where isnotempty(DestinationHostName)\\n
+ \ | extend DestinationHostName = tolower(DestinationHostName)\\n | project-rename
+ Name=DestinationHostName, DataSource=DeviceVendor\\n | summarize StartTime=min(TimeGenerated),
+ EndTime=max(TimeGenerated) by Name, SourceIP, DestinationIP, DataSource\\n)\\non
+ Name\\n| project StartTime, EndTime, Name, DGADomain, SourceIP, DestinationIP,
+ DataSource\\n| extend timestamp=StartTime, IPCustomEntity=SourceIP\",\"queryFrequency\":\"PT6H\",\"queryPeriod\":\"PT6H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Possible
+ contact with a domain generated by a DGA\",\"description\":\"Identifies contacts
+ with domains names in CommonSecurityLog that might have been generated by
+ a Domain Generation Algorithm (DGA). DGAs can be used\\nby malware to generate
+ rendezvous points that are difficult to predict in advance. This detection
+ uses the Alexa Top 1 million domain names to build a model\\nof what normal
+ domains look like. It uses this to identify domains that may have been randomly
+ generated by an algorithm.\\nThe triThreshold is set to 500 - increase this
+ to report on domains that are less likely to have been randomly generated,
+ decrease it for more likely.\\nThe start time and end time look back over
+ 6 hours of data and the dgaLengthThreshold is set to 8 - meaning domains whose
+ length is 8 or more are reported.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2020-03-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Zscaler\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"Barracuda\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CEF\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CheckPoint\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"F5\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"Fortinet\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/8ee967a2-a645-4832-85f4-72b635bcb3a6\",\"name\":\"8ee967a2-a645-4832-85f4-72b635bcb3a6\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\n//Adjust this threshold to fit the environment\\nlet signin_threshold
+ = 5;\\n//Make a list of all IPs with failed signins to AAD above our threshold\\nlet
+ suspicious_signins =\\nSigninLogs\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where ResultType !in (\\\"0\\\", \\\"50125\\\", \\\"50140\\\")\\n| where IPAddress
+ != \\\"127.0.0.1\\\"\\n| summarize count() by IPAddress\\n| where count_ >
+ signin_threshold\\n| summarize make_list(IPAddress);\\n//See if any of these
+ IPs have sucessfully logged into *nix hosts\\nlet linux_logons =\\nSyslog\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where Facility contains \\\"auth\\\"
+ and ProcessName != \\\"sudo\\\"\\n| where SyslogMessage has \\\"Accepted\\\"\\n|
+ extend SourceIP = extract(\\\"(([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.(([0-9]{1,3})))\\\",1,SyslogMessage)\\n|
+ where SourceIP in (suspicious_signins)\\n| extend Reason = \\\"Multiple failed
+ AAD logins from IP address\\\"\\n| project TimeGenerated, Computer, HostIP,
+ IpAddress = SourceIP, SyslogMessage, Facility, ProcessName, Reason;\\n//See
+ if any of these IPs have sucessfully logged into Windows hosts\\nlet win_logons
+ =\\nSecurityEvent\\n| where TimeGenerated >= ago(timeframe)\\n| where EventID
+ == 4624\\n| where LogonType in (10, 7, 3)\\n| where IpAddress != \\\"-\\\"\\n|
+ where IpAddress in (suspicious_signins)\\n| extend Reason = \\\"Multiple failed
+ AAD logins from IP address\\\"\\n| project TimeGenerated, Account, AccountType,
+ Computer, Activity, EventID, LogonProcessName, IpAddress, LogonTypeName, TargetUserSid,
+ Reason;\\nunion isfuzzy=true linux_logons,win_logons\\n| extend timestamp
+ = TimeGenerated, AccountCustomEntity = Account, IPCustomEntity = IpAddress,
+ HostCustomEntity = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Failed
+ AzureAD logons but success logon to host\",\"description\":\"Identifies a
+ list of IP addresses with a minimum number (default of 5) of failed logon
+ attempts to Azure Active Directory.\\nUses that list to identify any successful
+ remote logons to hosts from these IPs within the same timeframe.\",\"tactics\":[\"InitialAccess\",\"CredentialAccess\"],\"createdDateUTC\":\"2019-08-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]},{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/b3cfc7c0-092c-481c-a55b-34a3979758cb\",\"name\":\"b3cfc7c0-092c-481c-a55b-34a3979758cb\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Microsoft
+ Cloud App Security\",\"displayName\":\"Create incidents based on Microsoft
+ Cloud App Security alerts\",\"description\":\"Create incidents based on all
+ alerts generated in Microsoft Cloud App Security\",\"createdDateUTC\":\"2019-07-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"MicrosoftCloudAppSecurity\",\"dataTypes\":[\"SecurityAlert
+ (MCAS)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/80733eb7-35b2-45b6-b2b8-3c51df258206\",\"name\":\"80733eb7-35b2-45b6-b2b8-3c51df258206\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainList = dynamic([\\\"monerohash.com\\\", \\\"do-dear.com\\\",
+ \\\"xmrminerpro.com\\\", \\\"secumine.net\\\", \\\"xmrpool.com\\\", \\\"minexmr.org\\\",
+ \\\"hashanywhere.com\\\", \\\"xmrget.com\\\", \\n\\\"mininglottery.eu\\\",
+ \\\"minergate.com\\\", \\\"moriaxmr.com\\\", \\\"multipooler.com\\\", \\\"moneropools.com\\\",
+ \\\"xmrpool.eu\\\", \\\"coolmining.club\\\", \\\"supportxmr.com\\\",\\n\\\"minexmr.com\\\",
+ \\\"hashvault.pro\\\", \\\"xmrpool.net\\\", \\\"crypto-pool.fr\\\", \\\"xmr.pt\\\",
+ \\\"miner.rocks\\\", \\\"walpool.com\\\", \\\"herominers.com\\\", \\\"gntl.co.uk\\\",
+ \\\"semipool.com\\\", \\n\\\"coinfoundry.org\\\", \\\"cryptoknight.cc\\\",
+ \\\"fairhash.org\\\", \\\"baikalmine.com\\\", \\\"tubepool.xyz\\\", \\\"fairpool.xyz\\\",
+ \\\"asiapool.io\\\", \\\"coinpoolit.webhop.me\\\", \\\"nanopool.org\\\", \\n\\\"moneropool.com\\\",
+ \\\"miner.center\\\", \\\"prohash.net\\\", \\\"poolto.be\\\", \\\"cryptoescrow.eu\\\",
+ \\\"monerominers.net\\\", \\\"cryptonotepool.org\\\", \\\"extrmepool.org\\\",
+ \\\"webcoin.me\\\", \\n\\\"kippo.eu\\\", \\\"hashinvest.ws\\\", \\\"monero.farm\\\",
+ \\\"supportxmr.com\\\", \\\"xmrpool.eu\\\", \\\"linux-repository-updates.com\\\",
+ \\\"1gh.com\\\", \\\"dwarfpool.com\\\", \\\"hash-to-coins.com\\\", \\n\\\"hashvault.pro\\\",
+ \\\"pool-proxy.com\\\", \\\"hashfor.cash\\\", \\\"fairpool.cloud\\\", \\\"litecoinpool.org\\\",
+ \\\"mineshaft.ml\\\", \\\"abcxyz.stream\\\", \\\"moneropool.ru\\\", \\\"cryptonotepool.org.uk\\\",\\n\\\"extremepool.org\\\",
+ \\\"extremehash.com\\\", \\\"hashinvest.net\\\", \\\"unipool.pro\\\", \\\"crypto-pools.org\\\",
+ \\\"monero.net\\\", \\\"backup-pool.com\\\", \\\"mooo.com\\\", \\\"freeyy.me\\\",
+ \\\"cryptonight.net\\\",\\n\\\"shscrypto.net\\\"]);\\nSyslog\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where ProcessName contains \\\"squid\\\"\\n| extend
+ URL = extract(\\\"(([A-Z]+ [a-z]{4,5}:\\\\\\\\/\\\\\\\\/)|[A-Z]+ )([^ :]*)\\\",3,SyslogMessage),
+ \\n SourceIP = extract(\\\"([0-9]+ )(([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3})\\\\\\\\.([0-9]{1,3}))\\\",2,SyslogMessage),
+ \\n Status = extract(\\\"(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))\\\",1,SyslogMessage),
+ \\n HTTP_Status_Code = extract(\\\"(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))/([0-9]{3})\\\",8,SyslogMessage),\\n
+ \ User = extract(\\\"(CONNECT |GET )([^ ]* )([^ ]+)\\\",3,SyslogMessage),\\n
+ \ RemotePort = extract(\\\"(CONNECT |GET )([^ ]*)(:)([0-9]*)\\\",4,SyslogMessage),\\n
+ \ Domain = extract(\\\"(([A-Z]+ [a-z]{4,5}:\\\\\\\\/\\\\\\\\/)|[A-Z]+
+ )([^ :\\\\\\\\/]*)\\\",3,SyslogMessage),\\n Bytes = toint(extract(\\\"([A-Z]+\\\\\\\\/[0-9]{3}
+ )([0-9]+)\\\",2,SyslogMessage)),\\n contentType = extract(\\\"([a-z/]+$)\\\",1,SyslogMessage)\\n|
+ extend TLD = extract(\\\"\\\\\\\\.[a-z]*$\\\",0,Domain)\\n| where HTTP_Status_Code
+ == '200'\\n| where Domain contains \\\".\\\"\\n| where Domain has_any (DomainList)\\n|
+ extend timestamp = TimeGenerated, URLCustomEntity = URL, IPCustomEntity =
+ SourceIP, AccountCustomEntity = User\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Squid
+ proxy events related to mining pools\",\"description\":\"Checks for Squid
+ proxy events in Syslog associated with common mining pools .This query presumes
+ the default Squid log format is being used. \\n http://www.squid-cache.org/Doc/config/access_log/\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-07-12T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Syslog\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/04384937-e927-4595-8f3c-89ff58ed231f\",\"name\":\"04384937-e927-4595-8f3c-89ff58ed231f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ detectionTime = 30d;\\nlet IPs = dynamic ([\\\"199.249.230.\\\",\\\"185.220.101.\\\",\\\"23.129.64.\\\",\\\"109.70.100.\\\",\\\"185.220.102.\\\"]);\\nOfficeActivity\\n|
+ where TimeGenerated > ago(detectionTime)\\n| where RecordType in (\\\"AzureActiveDirectoryAccountLogon\\\",
+ \\\"AzureActiveDirectoryStsLogon\\\") \\n| where Operation != 'UserLoggedIn'\\n|
+ extend UserAgent = iff(parse_json(ExtendedProperties)[0].Name =~ \\\"UserAgent\\\",
+ extractjson(\\\"$[0].Value\\\", ExtendedProperties, typeof(string)),\\\"\\\")\\n|
+ mv-expand parse_json(ExtendedProperties)\\n| where ExtendedProperties.Name
+ =~ \\\"RequestType\\\"\\n| extend RequestType = ExtendedProperties.Value\\n|
+ where ClientIP has_any (IPs)\\n| summarize authAttempts=dcount(TimeGenerated),
+ firstAttempt=min(TimeGenerated), lastAttempt=max(TimeGenerated), uniqueIPs=dcount(ClientIP),
+ uniqueAccounts=dcount(UserId), attemptedAccounts=make_set(UserId) by UserAgent\\n|
+ where authAttempts > 2500\\n| extend timestamp = firstAttempt\\n| sort by
+ uniqueAccounts\",\"queryFrequency\":\"P7D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Possible
+ STRONTIUM attempted credential harvesting\",\"description\":\"Surfaces potential
+ STRONTIUM group Office365 credential harvesting attempts within OfficeActivity
+ Logon events.\\nReferences: https://www.microsoft.com/security/blog/2020/09/10/strontium-detecting-new-patters-credential-harvesting/.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-09-10T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/23de46ea-c425-4a77-b456-511ae4855d69\",\"name\":\"23de46ea-c425-4a77-b456-511ae4855d69\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ starttime = 14d;\\nlet endtime = 1d;\\n// The number of operations below which
+ an IP address is considered an unusual source of role assignment operations\\nlet
+ alertOperationThreshold = 5;\\nlet SensitiveOperationList = dynamic(\\n[\\\"List
+ keys\\\", \\\"List Storage Account Keys\\\", \\\"Register Subscription\\\",
+ \\\"Create or Update Snapshot\\\", \\\"Create or Update Network Security Group\\\"]);\\nlet
+ SensitiveActivity = AzureActivity\\n| where OperationName in~ (SensitiveOperationList)\\n|
+ where ActivityStatus =~ \\\"Succeeded\\\";\\nSensitiveActivity\\n| where TimeGenerated
+ between (ago(starttime) .. ago(endtime))\\n| summarize count() by CallerIpAddress,
+ Caller\\n| where count_ >= alertOperationThreshold\\n| join kind = rightanti
+ ( \\nSensitiveActivity\\n| where TimeGenerated >= ago(endtime)\\n| summarize
+ StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp
+ = makelist(TimeGenerated), ActivityStatus = makelist(ActivityStatus), \\nOperationIds
+ = makelist(OperationId), CorrelationIds = makelist(CorrelationId), Resources
+ = makelist(Resource), ResourceGroups = makelist(ResourceGroup), ResourceIds
+ = makelist(ResourceId), ActivityCountByCallerIPAddress = count() \\nby CallerIpAddress,
+ Caller, OperationName\\n) on CallerIpAddress, Caller\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Rare
+ subscription-level operations in Azure\",\"description\":\"This query looks
+ for a few sensitive subscription-level events based on Azure Activity Logs.
+ \\n For example this monitors for the operation name 'Create or Update Snapshot'
+ which is used for creating backups but could be misused by attackers \\n to
+ dump hashes or extract sensitive information from the disk.\",\"tactics\":[\"CredentialAccess\",\"Persistence\"],\"createdDateUTC\":\"2019-08-24T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActivity\",\"dataTypes\":[\"AzureActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/074ce265-f684-41cd-af07-613c5f3e6d0d\",\"name\":\"074ce265-f684-41cd-af07-613c5f3e6d0d\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = dynamic([\\\"irf.services\\\",\\\"microsoft-onthehub.com\\\",\\\"msofficelab.com\\\",\\\"com-mailbox.com\\\",\\\"my-sharefile.com\\\",\\\"my-sharepoints.com\\\",\\n\\\"accounts-web-mail.com\\\",\\\"customer-certificate.com\\\",\\\"session-users-activities.com\\\",\\\"user-profile-credentials.com\\\",\\\"verify-linke.com\\\",\\\"support-servics.net\\\",\\n\\\"onedrive-sharedfile.com\\\",\\\"onedrv-live.com\\\",\\\"transparencyinternational-my-sharepoint.com\\\",\\\"transparencyinternational-my-sharepoints.com\\\",\\\"soros-my-sharepoint.com\\\"]);\\n(union
+ isfuzzy=true\\n(CommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse Message with * '(' DNSName ')' * \\n| extend Account = SourceUserID,
+ Host = DeviceName, IPAddress = SourceIP),\\n(DnsEvents \\n| where TimeGenerated
+ >= ago(timeframe) \\n| extend IPAddress = ClientIP, DNSName = Name, Host =
+ Computer),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe) \\n|
+ parse RemoteDnsCanonicalNames with * '[\\\"' DNSName '\\\"]' *\\n| extend
+ IPAddress = RemoteIp, Host = Computer)\\n)\\n| where isnotempty(DNSName)\\n|
+ where DNSName in~ (DomainNames)\\n| extend timestamp = TimeGenerated, IPCustomEntity
+ = IPAddress, AccountCustomEntity = Account, HostCustomEntity = Host\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ STRONTIUM group domains - July 2019\",\"description\":\"Matches domain name
+ IOCs related to Strontium group activity published July 2019 with CommonSecurityLog,
+ DnsEvents and VMConnection dataTypes.\\nReferences: https://blogs.microsoft.com/on-the-issues/2019/07/17/new-cyberthreats-require-new-ways-to-protect-democracy/.\",\"tactics\":[\"CommandAndControl\"],\"createdDateUTC\":\"2019-07-25T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/aa1eff90-29d4-49dc-a3ea-b65199f516db\",\"name\":\"aa1eff90-29d4-49dc-a3ea-b65199f516db\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nSecurityEvent\\n| where TimeGenerated > ago(timeframe) \\n|
+ where EventID == 4720\\n| where AccountType == \\\"User\\\"\\n| project CreatedUserTime
+ = TimeGenerated, CreatedUserEventID = EventID, CreatedUserActivity = Activity,
+ Computer = toupper(Computer), \\nCreatedUser = tolower(TargetUserName), Domain
+ = toupper(TargetDomainName), CreatedUserSid = TargetSid, AccountUsedToCreateUser
+ = SubjectUserName\\n|join (\\nSecurityEvent \\n| where TimeGenerated > ago(timeframe)
+ \\n| where AccountType == \\\"User\\\"\\n// 4732 - A member was added to a
+ security-enabled local group\\n| where EventID == 4732\\n//TargetSid is the
+ builin Admins group: S-1-5-32-544\\n| where TargetSid == \\\"S-1-5-32-544\\\"\\n|
+ project GroupAddTime = TimeGenerated, GroupAddEventID = EventID, GroupAddActivity
+ = Activity, Computer = toupper(Computer), GroupName = TargetUserName, \\nDomain
+ = toupper(TargetDomainName), GroupSid = TargetSid, UserAdded = SubjectUserName,
+ UserAddedSid = SubjectUserSid, CreatedUser = tolower(SubjectUserName), \\nCreatedUserSid
+ = MemberSid\\n)\\non CreatedUserSid\\n//Create User first, then the add to
+ the group.\\n| project Computer, CreatedUserTime, CreatedUserEventID, CreatedUserActivity,
+ CreatedUser, CreatedUserSid, Domain, GroupAddTime, GroupAddEventID, \\nGroupAddActivity,
+ AccountUsedToCreateUser, GroupName, GroupSid, UserAdded, UserAddedSid \\n|
+ extend timestamp = CreatedUserTime, AccountCustomEntity = CreatedUser, HostCustomEntity
+ = Computer\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"New
+ user created and added to the built-in administrators group\",\"description\":\"Identifies
+ when a user account was created and then added to the builtin Administrators
+ group in the same day.\\nThis should be monitored closely and all additions
+ reviewed.\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2019-02-22T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/1fa1528e-f746-4794-8a41-14827f4cb798\",\"name\":\"1fa1528e-f746-4794-8a41-14827f4cb798\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = ago(1h);\\nlet threshold = 100;\\nPulseConnectSecure\\n| where
+ TimeGenerated >= timeframe\\n| where Messages startswith \\\"Login failed\\\"\\n|
+ summarize dcount(User) by Computer, bin(TimeGenerated, 15m)\\n| where dcount_User
+ > threshold\\n| extend timestamp = TimeGenerated, HostCustomEntity = Computer\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"PulseConnectSecure
+ - Large Number of Distinct Failed User Logins\",\"description\":\"This query
+ identifies evidence of failed login attempts from a large number of distinct
+ users on a Pulse Connect Secure VPN server\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-06-06T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"PulseConnectSecure\",\"dataTypes\":[\"Syslog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/8c2ef238-67a0-497d-b1dd-5c8a0f533e25\",\"name\":\"8c2ef238-67a0-497d-b1dd-5c8a0f533e25\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet EventNameList = dynamic([\\\"AuthorizeDBSecurityGroupIngress\\\",\\\"CreateDBSecurityGroup\\\",\\\"DeleteDBSecurityGroup\\\",\\\"RevokeDBSecurityGroupIngress\\\"]);\\nAWSCloudTrail\\n|
+ where TimeGenerated > ago(timeframe)\\n| where EventName in~ (EventNameList)\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid,
+ UserAgent, UserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress,
+ AWSRegion, EventSource, AdditionalEventData, ResponseElements\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = UserIdentityUserName, IPCustomEntity
+ = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Changes
+ to internet facing AWS RDS Database instances\",\"description\":\"Amazon Relational
+ Database Service (RDS) is scalable relational database in the cloud. \\nIf
+ your organization have one or more AWS RDS Databases running, monitoring changes
+ to especially internet facing AWS RDS (Relational Database Service) \\nOnce
+ alerts triggered, validate if changes observed are authorized and adhere to
+ change control policy. \\nMore information: https://medium.com/@GorillaStack/the-most-important-aws-cloudtrail-security-events-to-track-a5b9873f8255\\nand
+ RDS API Reference Docs: https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_Operations.html\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/9713e3c0-1410-468d-b79e-383448434b2d\",\"name\":\"9713e3c0-1410-468d-b79e-383448434b2d\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n VMConnection\\n | where
+ TimeGenerated >= ago(dt_lookBack)\\n // renaming time column so it is clear
+ the log this came from\\n | extend VMConnection_TimeGenerated = TimeGenerated\\n)\\non
+ $left.TI_ipEntity == $right.RemoteIp\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, VMConnection_TimeGenerated,\\nTI_ipEntity,
+ Computer, Direction, ProcessName, SourceIp, DestinationIp, RemoteIp, Protocol,
+ DestinationPort, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n|
+ extend timestamp = VMConnection_TimeGenerated, IPCustomEntity = RemoteIp,
+ HostCustomEntity = Computer, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to VMConnection\",\"description\":\"Identifies a match in
+ VMConnection from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/01f64465-b1ef-41ea-a7f5-31553a11ad43\",\"name\":\"01f64465-b1ef-41ea-a7f5-31553a11ad43\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet endpointData = \\n(SecurityEvent\\n | where TimeGenerated
+ >= ago(timeframe) \\n | where EventID == 4688\\n | extend shortFileName
+ = tostring(split(NewProcessName, '\\\\\\\\')[-1])\\n );\\n// Correlate suspect
+ executables seen in TrendMicro rule updates with similar activity on endpoints\\nCommonSecurityLog\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where DeviceVendor =~ \\\"Trend
+ Micro\\\"\\n| where Activity =~ \\\"Deny List updated\\\" \\n| where RequestURL
+ endswith \\\".exe\\\"\\n| project TimeGenerated, Activity , RequestURL , SourceIP,
+ DestinationIP\\n| extend suspectExeName = tolower(tostring(split(RequestURL,
+ '/')[-1]))\\n| join (endpointData) on $left.suspectExeName == $right.shortFileName
+ \\n| extend timestamp = TimeGenerated, IPCustomEntity = DestinationIP, AccountCustomEntity
+ = TargetUserName, HostCustomEntity = Computer, URLCustomEntity = RequestURL\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Network
+ endpoint to host executable correlation\",\"description\":\"Correlates blocked
+ URLs hosting [malicious] executables with host endpoint data\\nto identify
+ potential instances of executables of the same name having been recently run.\",\"tactics\":[\"Execution\"],\"createdDateUTC\":\"2019-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"TrendMicro\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/75ea5c39-93e5-489b-b1e1-68fa6c9d2d04\",\"name\":\"75ea5c39-93e5-489b-b1e1-68fa6c9d2d04\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\nlet threshold = 3;\\nSigninLogs\\n| where TimeGenerated
+ >= ago(timeframe)\\n| where ResultType == \\\"50057\\\"\\n| where ResultDescription
+ =~ \\\"User account is disabled. The account has been disabled by an administrator.\\\"\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ count(), applicationCount = dcount(AppDisplayName), \\napplicationSet = makeset(AppDisplayName)
+ by UserPrincipalName, IPAddress\\n| where applicationCount >= threshold\\n|
+ extend timestamp = StartTimeUtc, AccountCustomEntity = UserPrincipalName,
+ IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Attempts
+ to sign in to disabled accounts\",\"description\":\"Identifies failed attempts
+ to sign in to disabled accounts across multiple Azure Applications.\\nDefault
+ threshold for Azure Applications attempted to sign in to is 3.\\nReferences:
+ https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-sign-ins-error-codes\\n50057
+ - User account is disabled. The account has been disabled by an administrator.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-02-11T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/78422ef2-62bf-48ca-9bab-72c69818a425\",\"name\":\"78422ef2-62bf-48ca-9bab-72c69818a425\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ endtime = 1d;\\nlet starttime = 8d;\\nlet threshold = 2.0;\\nSecurityEvent\\n|
+ where TimeGenerated >= ago(endtime) \\n| where EventID == 4624 and LogonType
+ == 10\\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated),
+ ComputerCountToday = dcount(Computer), ComputerSet = makeset(Computer), ProcessSet
+ = makeset(ProcessName) \\nby Account, IpAddress, AccountType, Activity, LogonTypeName\\n|
+ join kind=inner (\\nSecurityEvent\\n| where TimeGenerated >= ago(starttime)
+ and TimeGenerated < ago(endtime) \\n| where EventID == 4624 and LogonType
+ == 10\\n| summarize ComputerCountPrev7Days = dcount(Computer) by Account,
+ IpAddress\\n) on Account, IpAddress\\n| extend Ratio = ComputerCountToday/(ComputerCountPrev7Days*1.0)\\n//
+ Where the ratio of today to previous 7 days is more than double.\\n| where
+ Ratio > threshold\\n| project StartTimeUtc, EndTimeUtc, Account, IpAddress,
+ ComputerSet, ComputerCountToday, ComputerCountPrev7Days, Ratio, AccountType,
+ Activity, LogonTypeName, ProcessSet\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = Account, IPCustomEntity = IpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P8D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Multiple
+ RDP connections from Single System\",\"description\":\"Identifies when an
+ RDP connection is made to multiple systems and above the normal for the previous
+ 7 days. \\nConnections from the same system with the same account within
+ the same day.\\nRDP connections are indicated by the EventID 4624 with LogonType
+ = 10\",\"tactics\":[\"LateralMovement\"],\"createdDateUTC\":\"2019-10-21T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/40ba9493-4183-4eee-974f-87fe39c8f267\",\"name\":\"40ba9493-4183-4eee-974f-87fe39c8f267\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"MicrosoftSecurityIncidentCreation\",\"properties\":{\"productFilter\":\"Azure
+ Advanced Threat Protection\",\"displayName\":\"Create incidents based on Azure
+ Advanced Threat Protection alerts\",\"description\":\"Create incidents based
+ on all alerts generated in Azure Advanced Threat Protection\",\"createdDateUTC\":\"2019-07-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureAdvancedThreatProtection\",\"dataTypes\":[\"SecurityAlert
+ (AATP)\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/610d3850-c26f-4f20-8d86-f10fdf2425f5\",\"name\":\"610d3850-c26f-4f20-8d86-f10fdf2425f5\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nlet EventNameList = dynamic([\\\"UpdateTrail\\\",\\\"DeleteTrail\\\",\\\"StopLogging\\\",\\\"DeleteFlowLogs\\\",\\\"DeleteEventBus\\\"]);\\nAWSCloudTrail\\n|
+ where TimeGenerated > ago(timeframe)\\n| where EventName in~ (EventNameList)\\n|
+ summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid,
+ UserAgent, \\nUserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress,
+ AWSRegion, EventSource\\n| extend timestamp = StartTimeUtc, AccountCustomEntity
+ = UserIdentityUserName, IPCustomEntity = SourceIpAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Changes
+ made to AWS CloudTrail logs\",\"description\":\"Attackers often try to hide
+ their steps by deleting or stopping the collection of logs that could show
+ their activity. \\nThis alert identifies any manipulation of AWS CloudTrail,
+ Cloudwatch/EventBridge or VPC Flow logs.\\nMore Information: AWS CloudTrail
+ API: https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_Operations.html\\nAWS
+ Cloudwatch/Eventbridge API: https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_Operations.html\\nAWS
+ DelteteFlowLogs API : https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteFlowLogs.html
+ \",\"tactics\":[\"DefenseEvasion\"],\"createdDateUTC\":\"2019-02-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/c87fb346-ea3a-4c64-ba92-3dd383e0f0b5\",\"name\":\"c87fb346-ea3a-4c64-ba92-3dd383e0f0b5\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet DomainNames = \\\"miniodaum.ml\\\";\\nlet SHA256Hash
+ = dynamic ([\\\"53f5773bbfbfbee660989d135c042c9f6f69024b9a4b65bdc0dfd44771762257\\\",
+ \\\"0897c80df8b80b4c49bf1ccf876f5f782849608b830c3b5cb3ad212dc3e19eff\\\"]);\\n(union
+ isfuzzy=true\\n(CommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse Message with * '(' DNSName ')' * \\n| where isnotempty(FileHash)\\n|
+ where FileHash in (SHA256Hash) or DNSName =~ DomainNames\\n| extend Account
+ = SourceUserID, Computer = DeviceName, IPAddress = SourceIP\\n),\\n(DnsEvents
+ \\n| where TimeGenerated >= ago(timeframe) \\n| extend DNSName = Name\\n|
+ where isnotempty(DNSName)\\n| where DNSName =~ DomainNames\\n| extend IPAddress
+ = ClientIP\\n),\\n(VMConnection \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse RemoteDnsCanonicalNames with * '[\\\"' DNSName '\\\"]' *\\n| where
+ isnotempty(DNSName)\\n| where DNSName =~ DomainNames\\n| extend IPAddress
+ = RemoteIp\\n)\\n)\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = Account, HostCustomEntity = Computer, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ CERIUM domains and hashes\",\"description\":\"CERIUM malicious webserver and
+ hash values for maldocs and malware. \\n Matches domain name IOCs related
+ to the CERIUM activity group with CommonSecurityLog, DnsEvents, and VMConnection
+ dataTypes.\",\"tactics\":[\"CommandAndControl\",\"CredentialAccess\"],\"createdDateUTC\":\"2020-10-30T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"DNS\",\"dataTypes\":[\"DnsEvents\"]},{\"connectorId\":\"AzureMonitor(VMInsights)\",\"dataTypes\":[\"VMConnection\"]},{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/65c78944-930b-4cae-bd79-c3664ae30ba7\",\"name\":\"65c78944-930b-4cae-bd79-c3664ae30ba7\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1d;\\n(union isfuzzy=true\\n(AuditLogs \\n| where TimeGenerated
+ >= ago(timeframe) \\n| where OperationName =~ \\\"Disable Strong Authentication\\\"\\n|
+ extend IPAddress = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
+ \\n| extend InitiatedByUser = iff(isnotempty(tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)),
+ \\n tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName), tostring(parse_json(tostring(InitiatedBy.app)).displayName))\\n|
+ extend Targetprop = todynamic(TargetResources)\\n| extend TargetUser = tostring(Targetprop[0].userPrincipalName)
+ \\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated)
+ by User = TargetUser, InitiatedByUser , Operation = OperationName , CorrelationId,
+ IPAddress, Category, Source = SourceSystem , AADTenantId, Type\\n),\\n(AWSCloudTrail\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where EventName in~ (\\\"DeactivateMFADevice\\\",
+ \\\"DeleteVirtualMFADevice\\\") \\n| extend InstanceProfileName = tostring(parse_json(RequestParameters).InstanceProfileName)\\n|
+ extend TargetUser = tostring(parse_json(RequestParameters).userName)\\n| summarize
+ StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by User
+ = TargetUser, Source = EventSource , Operation = EventName , TenantorInstance_Detail
+ = InstanceProfileName, IPAddress = SourceIpAddress\\n)\\n)\\n| extend timestamp
+ = StartTimeUtc, AccountCustomEntity = User, IPCustomEntity = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"MFA
+ disabled for a user\",\"description\":\"Multi-Factor Authentication (MFA)
+ helps prevent credential compromise. This alert identifies when an attempt
+ has been made to diable MFA for a user \",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2019-12-16T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]},{\"connectorId\":\"AWS\",\"dataTypes\":[\"AWSCloudTrail\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/fbfbf530-506b-49a4-81ad-4030885a195c\",\"name\":\"fbfbf530-506b-49a4-81ad-4030885a195c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ alertTimeWindow = 1h;\\nlet logTimeWindow = 7d;\\n// Define script extensions
+ that suit your web application environment - a sample are provided below\\nlet
+ scriptExtensions = dynamic([\\\".php\\\", \\\".jsp\\\", \\\".js\\\", \\\".aspx\\\",
+ \\\".asmx\\\", \\\".asax\\\", \\\".cfm\\\", \\\".shtml\\\"]); \\nlet alertData
+ = materialize(SecurityAlert \\n| where TimeGenerated > ago(alertTimeWindow)
+ \\n| where ProviderName == \\\"MDATP\\\" \\n// Parse and expand the alert
+ JSON \\n| extend alertData = parse_json(Entities) \\n| mvexpand alertData);\\nlet
+ fileData = alertData\\n// Extract web script files from MDATP alerts - our
+ malicious web scripts - candidate webshells\\n| where alertData.Type =~ \\\"file\\\"
+ \\n| where alertData.Name has_any(scriptExtensions) \\n| extend FileName =
+ tostring(alertData.Name), Directory = tostring(alertData.Directory);\\nlet
+ hostData = alertData\\n// Extract server details from alerts and map to alert
+ id\\n| where alertData.Type =~ \\\"host\\\"\\n| project HostName = tostring(alertData.HostName),
+ DnsDomain = tostring(alertData.DnsDomain), SystemAlertId\\n| distinct HostName,
+ DnsDomain, SystemAlertId;\\n// Join the files on their impacted servers\\nlet
+ webshellData = fileData\\n| join kind=inner (hostData) on SystemAlertId \\n|
+ project TimeGenerated, FileName, Directory, HostName, DnsDomain;\\nwebshellData\\n|
+ join ( \\n// Find requests that were made to this file on the impacted server
+ in the W3CIISLog table \\nW3CIISLog \\n| where TimeGenerated > ago(logTimeWindow)
+ \\n// Restrict to accesses to script extensions \\n| where csUriStem has_any(scriptExtensions)\\n|
+ extend splitUriStem = split(csUriStem, \\\"/\\\") \\n| extend FileName =
+ splitUriStem[-1], HostName = sComputerName\\n// Summarize potential attacker
+ activity\\n| summarize count(), StartTime=min(TimeGenerated), EndTime=max(TimeGenerated),
+ RequestUserAgents=make_set(csUserAgent), ReqestMethods=make_set(csMethod),
+ RequestStatusCodes=make_set(scStatus), RequestCookies=make_set(csCookie),
+ RequestReferers=make_set(csReferer), RequestQueryStrings=make_set(csUriQuery)
+ by AttackerIP=cIP, SiteName=sSiteName, ShellLocation=csUriStem, tostring(FileName),
+ HostName \\n) on FileName, HostName\\n| project StartTime, EndTime, AttackerIP,
+ RequestUserAgents, HostName, SiteName, ShellLocation, ReqestMethods, RequestStatusCodes,
+ RequestCookies, RequestReferers, RequestQueryStrings, RequestCount = count_\\n//
+ Expose the attacker ip address as a custom entity\\n| extend timestamp=StartTime,
+ IPCustomEntity = AttackerIP, HostCustomEntity = HostName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P7D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Malicious
+ web application requests linked with MDATP alerts\",\"description\":\"Takes
+ MDATP alerts where web scripts are present in the evidence and correlates
+ with requests made to those scripts\\nin the WCSIISLog to surface new alerts
+ for potentially malicious web request activity.\\nThe lookback for alerts
+ is set to 1h and the lookback for W3CIISLogs is set to 7d. A sample set of
+ popular web script extensions\\nhas been provided in scriptExtensions that
+ should be tailored to your environment.\",\"tactics\":[\"Persistence\"],\"createdDateUTC\":\"2020-05-21T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"MicrosoftDefenderAdvancedThreatProtection\",\"dataTypes\":[\"SecurityAlert\"]},{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/2fc5d810-c9cc-491a-b564-841427ae0e50\",\"name\":\"2fc5d810-c9cc-491a-b564-841427ae0e50\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$';\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n//Filtering the table for Email related IOCs\\n| where
+ isnotempty(EmailRecipient)\\n| join (\\n SecurityEvent | where TimeGenerated
+ >= ago(dt_lookBack) and isnotempty(TargetUserName)\\n //Normalizing the
+ column to lower case for exact match with EmailRecipient column\\n | extend
+ TargetUserName = tolower(TargetUserName)\\n // renaming timestamp column
+ so it is clear the log this came from SecurityEvent table\\n | extend SecurityEvent_TimeGenerated
+ = TimeGenerated\\n)\\non $left.EmailRecipient == $right.TargetUserName\\n|
+ summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n|
+ project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId,
+ ThreatType, Url, ExpirationDateTime, ConfidenceScore, SecurityEvent_TimeGenerated,\\nEmailSenderName,
+ EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType,
+ Computer, EventID, TargetUserName, Activity, IpAddress, AccountType,\\nLogonTypeName,
+ LogonProcessName, Status, SubStatus\\n| extend timestamp = SecurityEvent_TimeGenerated,
+ AccountCustomEntity = TargetUserName, IPCustomEntity = IpAddress, HostCustomEntity
+ = Computer, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Email entity to SecurityEvent\",\"description\":\"Identifies a match
+ in SecurityEvent table from any Email IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/02ef8d7e-fc3a-4d86-a457-650fa571d8d2\",\"name\":\"02ef8d7e-fc3a-4d86-a457-650fa571d8d2\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeFrame = 1d;\\nlet logonDiff = 10m;\\nSigninLogs \\n| where TimeGenerated
+ >= ago(timeFrame) \\n| where ResultType == \\\"0\\\" \\n| where AppDisplayName
+ !in (\\\"Office 365 Exchange Online\\\", \\\"Skype for Business Online\\\")\\n|
+ project SuccessLogonTime = TimeGenerated, UserPrincipalName, SuccessIPAddress
+ = IPAddress, AppDisplayName, SuccessIPBlock = strcat(split(IPAddress, \\\".\\\")[0],
+ \\\".\\\", split(IPAddress, \\\".\\\")[1])\\n| join kind= inner (\\n SigninLogs
+ \\n | where TimeGenerated >= ago(timeFrame) \\n | where ResultType !in
+ (\\\"0\\\", \\\"50140\\\") \\n | where ResultDescription !~ \\\"Other\\\"
+ \ \\n | where AppDisplayName !in (\\\"Office 365 Exchange Online\\\", \\\"Skype
+ for Business Online\\\")\\n | project FailedLogonTime = TimeGenerated,
+ UserPrincipalName, FailedIPAddress = IPAddress, AppDisplayName, ResultType,
+ ResultDescription\\n) on UserPrincipalName, AppDisplayName \\n| where SuccessLogonTime
+ < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and
+ FailedIPAddress !startswith SuccessIPBlock\\n| summarize FailedLogonTime =
+ max(FailedLogonTime), SuccessLogonTime = max(SuccessLogonTime) by UserPrincipalName,
+ SuccessIPAddress, AppDisplayName, FailedIPAddress, ResultType, ResultDescription
+ \\n| extend timestamp = SuccessLogonTime, AccountCustomEntity = UserPrincipalName,
+ IPCustomEntity = SuccessIPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Successful
+ logon from IP and failure from a different IP\",\"description\":\"Identifies
+ when a user account successfully logs onto an Azure App from one IP and within
+ 10 mins failed to logon to the same App via a different IP.\\nThis may indicate
+ a malicious attempt at password guessing based on knowledge of the users account.\",\"tactics\":[\"CredentialAccess\",\"InitialAccess\"],\"createdDateUTC\":\"2019-02-19T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f845881e-2500-44dc-8ed7-b372af3e1e25\",\"name\":\"f845881e-2500-44dc-8ed7-b372af3e1e25\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeFrame = 1d;\\nlet short_uaLength = 5;\\nlet long_uaLength = 1000;\\nlet
+ c_threshold = 100;\\nW3CIISLog \\n| where TimeGenerated >= ago(timeFrame)\\n//
+ Exclude local IPs as these create noise\\n| where cIP !startswith \\\"192.168.\\\"
+ and cIP != \\\"::1\\\"\\n| where isnotempty(csUserAgent) and csUserAgent !in~
+ (\\\"-\\\", \\\"MSRPC\\\") and (string_size(csUserAgent) <= short_uaLength
+ or string_size(csUserAgent) >= long_uaLength)\\n| extend csUserAgent_size
+ = string_size(csUserAgent)\\n| summarize StartTimeUtc = min(TimeGenerated),
+ EndTimeUtc = max(TimeGenerated), ConnectionCount = count() by Computer, sSiteName,
+ sPort, csUserAgent, csUserAgent_size, csUserName , csMethod, csUriStem, sIP,
+ cIP, scStatus, scSubStatus, scWin32Status\\n| where ConnectionCount < c_threshold\\n|
+ extend timestamp = StartTimeUtc, AccountCustomEntity = csUserName, HostCustomEntity
+ = Computer, IPCustomEntity = cIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Anomalous
+ User Agent connection attempt\",\"description\":\"Identifies connection attempts
+ (success or fail) from clients with very short or very long User Agent strings
+ and with less than 100 connection attempts.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-02-20T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/a50766a7-0674-4ccb-8845-15dc55a80ba1\",\"name\":\"a50766a7-0674-4ccb-8845-15dc55a80ba1\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n WireData | where TimeGenerated
+ >= ago(dt_lookBack)\\n | where isnotempty(RemoteIP)\\n // renaming time
+ column so it is clear the log this came from\\n | extend WireData_TimeGenerated
+ = TimeGenerated\\n)\\non $left.TI_ipEntity == $right.RemoteIP\\n| summarize
+ LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n| project
+ LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType,
+ Url, ExpirationDateTime, ConfidenceScore, WireData_TimeGenerated,\\nTI_ipEntity,
+ Computer, LocalIP, RemoteIP, ProcessName, ApplicationProtocol, LocalPortNumber,
+ NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n|
+ extend timestamp = WireData_TimeGenerated, IPCustomEntity = RemoteIP, HostCustomEntity
+ = Computer, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to WireData\",\"description\":\"Identifies a match in WireData
+ from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureMonitor(WireData)\",\"dataTypes\":[\"WireData\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/5e45930c-09b1-4430-b2d1-cc75ada0dc0f\",\"name\":\"5e45930c-09b1-4430-b2d1-cc75ada0dc0f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n W3CIISLog\\n | where
+ TimeGenerated >= ago(dt_lookBack)\\n | where isnotempty(cIP)\\n // renaming
+ time column so it is clear the log this came from\\n | extend W3CIISLog_TimeGenerated
+ = TimeGenerated\\n)\\non $left.TI_ipEntity == $right.cIP\\n| summarize LatestIndicatorTime
+ = arg_max(TimeGenerated, *) by IndicatorId\\n| project LatestIndicatorTime,
+ Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime,
+ ConfidenceScore,\\nW3CIISLog_TimeGenerated, TI_ipEntity, Computer, sSiteName,
+ cIP, sIP, sPort, csMethod, csUserName, scStatus, scSubStatus, scWin32Status,\\nNetworkIP,
+ NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp
+ = W3CIISLog_TimeGenerated, IPCustomEntity = cIP, HostCustomEntity = Computer,
+ AccountCustomEntity = csUserName, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to W3CIISLog\",\"description\":\"Identifies a match in W3CIISLog
+ from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"AzureMonitor(IIS)\",\"dataTypes\":[\"W3CIISLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/3174a9ec-d0ad-4152-8307-94ed04fa450a\",\"name\":\"3174a9ec-d0ad-4152-8307-94ed04fa450a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"High\",\"query\":\"let
+ timeframe = 1d;\\nlet SHA256Hash = \\\"1174fd03271f80f5e2a6435c72bdd0272a6e3a37049f6190abf125b216a83471\\\"
+ ;\\n(union isfuzzy=true\\n(CommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)
+ \\n| parse Message with * '(' DNSName ')' * \\n| where isnotempty(FileHash)\\n|
+ where FileHash in (SHA256Hash) \\n| extend Account = SourceUserID, Computer
+ = DeviceName, IPAddress = SourceIP\\n),\\n(Event\\n//This query uses sysmon
+ data depending on table name used this may need updataing\\n| where TimeGenerated
+ >= ago(3d)\\n| where Source == \\\"Microsoft-Windows-Sysmon\\\"\\n| extend
+ EvData = parse_xml(EventData)\\n| extend EventDetail = EvData.DataItem.EventData.Data\\n|
+ extend Hashes = EventDetail.[16].[\\\"#text\\\"]\\n| parse Hashes with * 'SHA256='
+ SHA265 ',' * \\n| where isnotempty(Hashes)\\n| where Hashes in (SHA256Hash)
+ \\n| extend Account = UserName\\n)\\n)\\n| extend timestamp = TimeGenerated,
+ AccountCustomEntity = Account, HostCustomEntity = Computer, IPCustomEntity
+ = IPAddress\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Known
+ ZINC related maldoc hash\",\"description\":\"Document hash used by ZINC in
+ highly targeted spear phishing campaign.\",\"tactics\":[\"CommandAndControl\",\"CredentialAccess\"],\"createdDateUTC\":\"2020-10-30T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"PaloAltoNetworks\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvent\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/f15370f4-c6fa-42c5-9be4-1d308f40284e\",\"name\":\"f15370f4-c6fa-42c5-9be4-1d308f40284e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\nThreatIntelligenceIndicator\\n|
+ where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n|
+ where Active == true\\n// Picking up only IOC's that contain the entities
+ we want\\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress)
+ or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\\n// As
+ there is potentially more than 1 indicator type for matching IP, taking NetworkIP
+ first, then others if that is empty.\\n// Taking the first non-empty value
+ based on potential IOC match availability\\n| extend TI_ipEntity = iff(isnotempty(NetworkIP),
+ NetworkIP, NetworkDestinationIP)\\n| extend TI_ipEntity = iff(isempty(TI_ipEntity)
+ and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\\n| extend
+ TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress),
+ EmailSourceIpAddress, TI_ipEntity)\\n| join (\\n OfficeActivity | where
+ TimeGenerated >= ago(dt_lookBack)\\n // renaming time column so it is clear
+ the log this came from\\n | extend OfficeActivity_TimeGenerated = TimeGenerated\\n)\\non
+ $left.TI_ipEntity == $right.ClientIP\\n| summarize LatestIndicatorTime = arg_max(TimeGenerated,
+ *) by IndicatorId\\n| project LatestIndicatorTime, Description, ActivityGroupNames,
+ IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, OfficeActivity_TimeGenerated,\\nTI_ipEntity,
+ ClientIP, UserId, Operation, ResultStatus, RecordType, OfficeObjectId, NetworkIP,
+ NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress\\n| extend timestamp
+ = OfficeActivity_TimeGenerated, IPCustomEntity = ClientIP, AccountCustomEntity
+ = UserId, URLCustomEntity = Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map IP entity to OfficeActivity\",\"description\":\"Identifies a match
+ in OfficeActivity from any IP IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-27T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/9c712bb2-08dc-44d3-b66b-af154dfc1c4f\",\"name\":\"9c712bb2-08dc-44d3-b66b-af154dfc1c4f\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Anomaly\",\"properties\":{\"severity\":\"Informational\",\"anomalyDefinitionVersion\":\"1.0.0\",\"techniques\":[\"T1001\"],\"customizableObservations\":{\"multiSelectObservations\":null,\"singleSelectObservations\":null,\"prioritizeExcludeObservations\":null,\"thresholdObservations\":[{\"minimum\":\"0\",\"maximum\":\"1\",\"value\":\"0.07\",\"name\":\"AnomalyScore\",\"description\":\"Generate
+ an anomaly when score is greater than the chosen value\",\"sequenceNumber\":1,\"rerun\":\"NotRequired\"}]},\"frequency\":\"P1D\",\"displayName\":\"(Preview)
+ Suspicious volume of logons to computer\",\"description\":\"This algorithm
+ is to detect unusually high volume of successful logins per each workspace
+ and computer. Successful logins are events with event id 4624.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2020-11-03T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"SecurityEvents\",\"dataTypes\":[\"SecurityEvents\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/68271db2-cbe9-4009-b1d3-bb3b5fe5713c\",\"name\":\"68271db2-cbe9-4009-b1d3-bb3b5fe5713c\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ detectionTime = 30d;\\nlet User_Agents = dynamic ([\\\"Mozilla/5.0 (Windows
+ NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70\\\",
+ \\n\\\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/605.1.15
+ (KHTML, like Gecko) Version/12.0.1 Safari/605.1.15\\\", \\n\\\"Mozilla/5.0
+ (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0\\\", \\n\\\"Mozilla/5.0
+ (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110
+ Safari/537.36\\\", \\n\\\"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36
+ (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\\\"]);\\nOfficeActivity\\n|
+ where TimeGenerated > ago(detectionTime)\\n| where RecordType in (\\\"AzureActiveDirectoryAccountLogon\\\",
+ \\\"AzureActiveDirectoryStsLogon\\\") \\n| where Operation != 'UserLoggedIn'\\n|
+ extend UserAgent = iff(parse_json(ExtendedProperties)[0].Name =~ \\\"UserAgent\\\",
+ extractjson(\\\"$[0].Value\\\", ExtendedProperties, typeof(string)),\\\"\\\")\\n|
+ mv-expand parse_json(ExtendedProperties)\\n| where ExtendedProperties.Name
+ =~ \\\"RequestType\\\"\\n| extend RequestType = todynamic(ExtendedProperties).Value\\n|
+ where UserAgent =~ \\\"ms-office\\\" or UserAgent has_any (User_Agents)\\n|
+ summarize authAttempts=dcount(TimeGenerated), firstAttempt=min(TimeGenerated),
+ lastAttempt=max(TimeGenerated), uniqueIPs=dcount(ClientIP), uniqueAccounts=dcount(UserId),
+ attemptedAccounts=make_set(UserId) by UserAgent\\n| where authAttempts > 500\\n|
+ extend timestamp = firstAttempt\\n| sort by uniqueAccounts\",\"queryFrequency\":\"P7D\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Possible
+ STRONTIUM attempted credential harvesting\",\"description\":\"Surfaces potential
+ STRONTIUM group Office365 credential harvesting attempts within OfficeActivity
+ Logon events.\",\"tactics\":[\"CredentialAccess\"],\"createdDateUTC\":\"2020-09-10T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/957cb240-f45d-4491-9ba5-93430a3c08be\",\"name\":\"957cb240-f45d-4491-9ba5-93430a3c08be\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Low\",\"query\":\"let
+ timeframe = 1d;\\nOfficeActivity\\n| where TimeGenerated >= ago(timeframe)\\n|
+ where Operation in~ ( \\\"Add-MailboxPermission\\\", \\\"Add-MailboxFolderPermission\\\",
+ \\\"Set-Mailbox\\\", \\\"New-ManagementRoleAssignment\\\")\\nand not(UserId
+ has_any ('NT AUTHORITY\\\\\\\\SYSTEM (Microsoft.Exchange.ServiceHost)','devilfish-applicationaccount')
+ and Operation in~ ( \\\"Add-MailboxPermission\\\", \\\"Set-Mailbox\\\"))\\n|
+ extend timestamp = TimeGenerated, AccountCustomEntity = UserId, IPCustomEntity
+ = ClientIP\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Rare
+ and potentially high-risk Office operations\",\"description\":\"Identifies
+ Office operations that are typically rare and can provide capabilities useful
+ to attackers.\",\"tactics\":[\"Persistence\",\"Collection\"],\"createdDateUTC\":\"2019-02-13T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"Office365\",\"dataTypes\":[\"OfficeActivity\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/795edf2d-cf3e-45b5-8452-fe6c9e6a582e\",\"name\":\"795edf2d-cf3e-45b5-8452-fe6c9e6a582e\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1h;\\nCommonSecurityLog \\n| where TimeGenerated >= ago(timeframe)\\n|
+ where isempty(CommunicationDirection) \\n| where DeviceEventClassID in (\\\"733101\\\",\\\"733102\\\",\\\"733103\\\",\\\"733104\\\",\\\"733105\\\")\\n|
+ extend timestamp = TimeGenerated, IPCustomEntity = SourceIP, HostCustomEntity
+ = DeviceName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Cisco
+ ASA - threat detection message fired\",\"description\":\"Identifies when the
+ Cisco ASA Threat Detection engine fired an alert based on malicious activity
+ occurring on the network inicated by DeviceEventClassID 733101-733105\\nResources:
+ https://www.cisco.com/c/en/us/td/docs/security/asa/syslog/b_syslog/syslogs9.html\\nDetails
+ on how to further troubleshoot/investigate: https://www.cisco.com/c/en/us/support/docs/security/asa-5500-x-series-next-generation-firewalls/113685-asa-threat-detection.html\",\"tactics\":[\"Discovery\",\"Impact\"],\"createdDateUTC\":\"2019-02-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/4d94d4a9-dc96-410a-8dea-4d4d4584188b\",\"name\":\"4d94d4a9-dc96-410a-8dea-4d4d4584188b\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ timeframe = 1h;\\nlet OperationList = dynamic([\\\"Add member to role\\\",\\\"Add
+ member to role in PIM requested (permanent)\\\"]);\\nlet PrivilegedGroups
+ = dynamic([\\\"UserAccountAdmins\\\",\\\"PrivilegedRoleAdmins\\\",\\\"TenantAdmins\\\"]);\\nAuditLogs\\n|
+ where TimeGenerated >= ago(timeframe)\\n| where LoggedByService =~ \\\"Core
+ Directory\\\"\\n| where Category =~ \\\"RoleManagement\\\"\\n| where OperationName
+ in~ (OperationList)\\n| mv-expand TargetResources\\n| extend modifiedProperties
+ = parse_json(TargetResources).modifiedProperties\\n| mv-expand modifiedProperties\\n|
+ extend DisplayName = tostring(parse_json(modifiedProperties).displayName),
+ GroupName = trim(@'\\\"',tostring(parse_json(modifiedProperties).newValue))\\n|
+ extend AppId = tostring(parse_json(parse_json(InitiatedBy).app).appId), InitiatedByDisplayName
+ = tostring(parse_json(parse_json(InitiatedBy).app).displayName), ServicePrincipalId
+ = tostring(parse_json(parse_json(InitiatedBy).app).servicePrincipalId), ServicePrincipalName
+ = tostring(parse_json(parse_json(InitiatedBy).app).servicePrincipalName)\\n|
+ where DisplayName =~ \\\"Role.WellKnownObjectName\\\"\\n| where GroupName
+ in~ (PrivilegedGroups)\\n// If you want to still alert for operations from
+ PIM, remove below filtering for MS-PIM.\\n| where InitiatedByDisplayName !=
+ \\\"MS-PIM\\\"\\n| project TimeGenerated, AADOperationType, Category, OperationName,
+ AADTenantId, AppId, InitiatedByDisplayName, ServicePrincipalId, ServicePrincipalName,
+ DisplayName, GroupName\\n| extend timestamp = TimeGenerated, AccountCustomEntity
+ = ServicePrincipalName\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"PT1H\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"User
+ added to Azure Active Directory Privileged Groups\",\"description\":\"This
+ will alert when a user is added to any of the Privileged Groups.\\nFor further
+ information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.\\nFor
+ Administrator role permissions in Azure Active Directory please see https://docs.microsoft.com/azure/active-directory/users-groups-roles/directory-assign-admin-roles\",\"tactics\":[\"Persistence\",\"PrivilegeEscalation\"],\"createdDateUTC\":\"2020-07-15T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"AuditLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/dd0a6029-ecef-4507-89c4-fc355ac52111\",\"name\":\"dd0a6029-ecef-4507-89c4-fc355ac52111\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ dt_lookBack = 1h;\\nlet ioc_lookBack = 14d;\\n//Create a list of TLDs in our
+ threat feed for later validation of extracted domains\\nlet list_tlds = ThreatIntelligenceIndicator\\n
+ \ | where TimeGenerated > ago(ioc_lookBack)\\n | where isnotempty(DomainName)\\n
+ \ | extend DomainName = tolower(DomainName)\\n | extend parts = split(DomainName,
+ '.')\\n | extend tld = parts[(array_length(parts)-1)]\\n | summarize
+ count() by tostring(tld)\\n | summarize make_list(tld);\\n ThreatIntelligenceIndicator\\n
+ \ | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\\n
+ \ | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\\n
+ \ | where Active == true\\n // Picking up only IOC's that contain the
+ entities we want\\n | where isnotempty(DomainName)\\n | join (\\n CommonSecurityLog\\n
+ \ | extend IngestionTime = ingestion_time()\\n | where IngestionTime
+ > ago(dt_lookBack)\\n | where DeviceEventClassID =~ 'url'\\n //Uncomment
+ the line below to only alert on allowed connections\\n //| where DeviceAction
+ !~ \\\"block-url\\\"\\n //Extract domain from RequestURL, if not present
+ extarct it from AdditionalExtentions\\n | extend PA_Url = columnifexists(\\\"RequestURL\\\",
+ \\\"None\\\")\\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions
+ !startswith \\\"PanOS\\\", extract(\\\"([^\\\\\\\"]+)\\\", 1, tolower(AdditionalExtensions)),
+ trim('\\\"', PA_Url))\\n | extend PA_Url = iif(PA_Url !startswith \\\"http://\\\"
+ and ApplicationProtocol !~ \\\"ssl\\\", strcat('http://', PA_Url), iif(PA_Url
+ !startswith \\\"https://\\\" and ApplicationProtocol =~ \\\"ssl\\\", strcat('https://',
+ PA_Url), PA_Url))\\n | extend Domain = trim(@\\\"\\\"\\\"\\\",tostring(parse_url(PA_Url).Host))\\n
+ \ | where isnotempty(Domain)\\n | extend Domain = tolower(Domain)\\n
+ \ | extend parts = split(Domain, '.')\\n //Split out the TLD
+ for the purpose of checking if we have any TI indicators with this TLD to
+ match on\\n | extend tld = parts[(array_length(parts)-1)]\\n //Validate
+ parsed domain by checking TLD against TLDs from threat feed and drop domains
+ where there is no chance of a match\\n | where tld in~ (list_tlds)\\n
+ \ | extend CSL_TimeGenerated = TimeGenerated\\n ) on $left.DomainName==$right.Domain\\n
+ \ | project LatestIndicatorTime, Description, ActivityGroupNames, PA_Url,
+ Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, CSL_TimeGenerated,
+ DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort,
+ ApplicationProtocol, RequestMethod\\n | extend timestamp = CSL_TimeGenerated,
+ IPCustomEntity = SourceIP, HostCustomEntity = DeviceName, URLCustomEntity
+ = PA_Url\",\"queryFrequency\":\"PT1H\",\"queryPeriod\":\"P14D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"(Preview)
+ TI map Domain entity to CommonSecurityLog\",\"description\":\"Identifies a
+ match in CommonSecurityLog table from any Domain IOC from TI\",\"tactics\":[\"Impact\"],\"createdDateUTC\":\"2019-08-28T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"ThreatIntelligence\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]},{\"connectorId\":\"ThreatIntelligenceTaxii\",\"dataTypes\":[\"ThreatIntelligenceIndicator\"]}],\"alertRulesCreatedByTemplateCount\":0}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/AlertRuleTemplates/157c0cfc-d76d-463b-8755-c781608cdc1a\",\"name\":\"157c0cfc-d76d-463b-8755-c781608cdc1a\",\"type\":\"Microsoft.SecurityInsights/AlertRuleTemplates\",\"kind\":\"Scheduled\",\"properties\":{\"severity\":\"Medium\",\"query\":\"let
+ PrivateIPregex = @'^127\\\\.|^10\\\\.|^172\\\\.1[6-9]\\\\.|^172\\\\.2[0-9]\\\\.|^172\\\\.3[0-1]\\\\.|^192\\\\.168\\\\.';\\nlet
+ endtime = 1d;\\nCommonSecurityLog\\n| where TimeGenerated >= ago(endtime)
+ \\n| where DeviceVendor =~ \\\"Cisco\\\"\\n| where DeviceAction =~ \\\"denied\\\"\\n|
+ extend SourceIPType = iff(SourceIP matches regex PrivateIPregex,\\\"private\\\"
+ ,\\\"public\\\" )\\n| where SourceIPType == \\\"public\\\"\\n| summarize count()
+ by SourceIP\\n| join (\\n // Successful signins from IPs blocked by the
+ firewall solution are suspect\\n // Include fully successful sign-ins,
+ but also ones that failed only at MFA stage\\n // as that supposes the
+ password was sucessfully guessed.\\n SigninLogs\\n | where ResultType in
+ (\\\"0\\\", \\\"50074\\\", \\\"50076\\\") \\n) on $left.SourceIP == $right.IPAddress\\n|
+ extend timestamp = TimeGenerated, IPCustomEntity = SourceIP, AccountCustomEntity
+ = UserPrincipalName\",\"queryFrequency\":\"P1D\",\"queryPeriod\":\"P1D\",\"triggerOperator\":\"GreaterThan\",\"triggerThreshold\":0,\"displayName\":\"Cisco
+ - firewall block but success logon to Azure AD\",\"description\":\"Correlate
+ IPs blocked by a Cisco firewall appliance with successful Azure Active Directory
+ signins. \\nBecause the IP was blocked by the firewall, that same IP logging
+ on successfully to AAD is potentially suspect\\nand could indicate credential
+ compromise for the user account.\",\"tactics\":[\"InitialAccess\"],\"createdDateUTC\":\"2019-07-08T00:00:00Z\",\"status\":\"Available\",\"requiredDataConnectors\":[{\"connectorId\":\"CiscoASA\",\"dataTypes\":[\"CommonSecurityLog\"]},{\"connectorId\":\"AzureActiveDirectory\",\"dataTypes\":[\"SigninLogs\"]}],\"alertRulesCreatedByTemplateCount\":0}}]}"
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '481815'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:32 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: '{"etag": "\"0300bf09-0000-0000-0000-5c37296e0000\"", "properties": {"created":
+ "2019-01-01T13:15:30.000Z", "displayName": "My bookmark", "labels": ["Tag2"],
+ "notes": "Found a suspicious activity", "query": "SecurityEvent | where TimeGenerated
+ > ago(1d) and TimeGenerated < ago(2d)", "queryResult": "Security Event query
+ result", "updated": "2019-01-01T13:15:30.000Z"}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel bookmark create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '368'
+ Content-Type:
+ - application/json
+ ParameterSetName:
+ - --etag --created --display-name --labels --labels --notes -q --query-result
+ --updated --bookmark-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5","name":"73e01a99-5cd7-4139-a149-9f2736ff2ab5","etag":"\"cb0046e7-0000-0100-0000-5fc47f430000\"","type":"Microsoft.SecurityInsights/Bookmarks","properties":{"displayName":"My
+ bookmark","created":"2020-11-30T05:12:35.7407413+00:00","updated":"2020-11-30T05:12:35+00:00","createdBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"updatedBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"eventTime":"2020-11-30T05:12:35.7407413+00:00","notes":"Found a suspicious
+ activity","labels":["Tag2"],"query":"SecurityEvent | where TimeGenerated >
+ ago(1d) and TimeGenerated < ago(2d)","queryResult":"Security Event query result","incidentInfo":{"incidentId":null,"title":null,"relationName":null,"severity":null}}}'
+ headers:
+ api-supported-versions:
+ - '2019-01-01'
+ cache-control:
+ - no-cache
+ content-length:
+ - '1112'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:36 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1198'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel bookmark show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --bookmark-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5","name":"73e01a99-5cd7-4139-a149-9f2736ff2ab5","etag":"\"cb0046e7-0000-0100-0000-5fc47f430000\"","type":"Microsoft.SecurityInsights/Bookmarks","properties":{"displayName":"My
+ bookmark","created":"2020-11-30T05:12:35.7407413+00:00","updated":"2020-11-30T05:12:35.7407413+00:00","createdBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"updatedBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"eventTime":"2020-11-30T05:12:35.7407413+00:00","notes":"Found a suspicious
+ activity","labels":["Tag2"],"query":"SecurityEvent | where TimeGenerated >
+ ago(1d) and TimeGenerated < ago(2d)","queryResult":"Security Event query result","incidentInfo":{"incidentId":null,"title":null,"relationName":null,"severity":null}}}'
+ headers:
+ api-supported-versions:
+ - '2019-01-01'
+ cache-control:
+ - no-cache
+ content-length:
+ - '1120'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:36 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel bookmark list
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/bookmarks?api-version=2020-01-01
+ response:
+ body:
+ string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5","name":"73e01a99-5cd7-4139-a149-9f2736ff2ab5","etag":"\"cb0046e7-0000-0100-0000-5fc47f430000\"","type":"Microsoft.SecurityInsights/Bookmarks","properties":{"displayName":"My
+ bookmark","created":"2020-11-30T05:12:35.7407413+00:00","updated":"2020-11-30T05:12:35.7407413+00:00","createdBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"updatedBy":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma"},"eventTime":"2020-11-30T05:12:35.7407413+00:00","notes":"Found a suspicious
+ activity","labels":["Tag2"],"query":"SecurityEvent | where TimeGenerated >
+ ago(1d) and TimeGenerated < ago(2d)","queryResult":"Security Event query result","incidentInfo":{"incidentId":null,"title":null,"relationName":null,"severity":null}}}]}'
+ headers:
+ api-supported-versions:
+ - '2019-01-01'
+ cache-control:
+ - no-cache
+ content-length:
+ - '1132'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:38 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel bookmark delete
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '0'
+ ParameterSetName:
+ - -y --bookmark-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: DELETE
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/bookmarks/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{}'
+ headers:
+ api-supported-versions:
+ - '2019-01-01'
+ cache-control:
+ - no-cache
+ content-length:
+ - '2'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:40 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-deletes:
+ - '14999'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: '{"etag": "\"0300bf09-0000-0000-0000-5c37296e0000\"", "properties": {"classification":
+ "FalsePositive", "classificationComment": "Not a malicious activity", "classificationReason":
+ "IncorrectAlertLogic", "description": "This is a demo incident", "firstActivityTimeUtc":
+ "2019-01-01T13:00:30.000Z", "lastActivityTimeUtc": "2019-01-01T13:05:30.000Z",
+ "owner": {"objectId": "2046feea-040d-4a46-9e2b-91c2941bfa70"}, "severity": "High",
+ "status": "Closed", "title": "title"}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '469'
+ Content-Type:
+ - application/json
+ ParameterSetName:
+ - --etag --description --classification --classification-comment --classification-reason
+ --first-activity-time-utc --last-activity-time-utc --owner --severity --status
+ --title --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5","name":"73e01a99-5cd7-4139-a149-9f2736ff2ab5","etag":"\"d800e253-0000-0100-0000-5fc47f4b0000\"","type":"Microsoft.SecurityInsights/Incidents","properties":{"title":"title","description":"This
+ is a demo incident","severity":"High","status":"Closed","classification":"FalsePositive","classificationReason":"IncorrectAlertLogic","classificationComment":"Not
+ a malicious activity","owner":{"objectId":"2046feea-040d-4a46-9e2b-91c2941bfa70","email":null,"assignedTo":null,"userPrincipalName":null},"labels":[],"firstActivityTimeUtc":"2019-01-01T13:00:30Z","lastActivityTimeUtc":"2019-01-01T13:05:30Z","lastModifiedTimeUtc":"2020-11-30T05:12:43.0112258Z","createdTimeUtc":"2020-11-30T05:12:43.0112258Z","incidentNumber":1,"additionalData":{"alertsCount":0,"bookmarksCount":0,"commentsCount":0,"alertProductNames":[],"tactics":[]},"relatedAnalyticRuleIds":[],"incidentUrl":"https://portal.azure.com/#asset/Microsoft_Azure_Security_Insights/Incident/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5"}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '1557'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:42 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1198'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5","name":"73e01a99-5cd7-4139-a149-9f2736ff2ab5","etag":"\"d800e253-0000-0100-0000-5fc47f4b0000\"","type":"Microsoft.SecurityInsights/Incidents","properties":{"title":"title","description":"This
+ is a demo incident","severity":"High","status":"Closed","classification":"FalsePositive","classificationReason":"IncorrectAlertLogic","classificationComment":"Not
+ a malicious activity","owner":{"objectId":"2046feea-040d-4a46-9e2b-91c2941bfa70","email":null,"assignedTo":null,"userPrincipalName":null},"labels":[],"firstActivityTimeUtc":"2019-01-01T13:00:30Z","lastActivityTimeUtc":"2019-01-01T13:05:30Z","lastModifiedTimeUtc":"2020-11-30T05:12:43.0112258Z","createdTimeUtc":"2020-11-30T05:12:43.0112258Z","incidentNumber":1,"additionalData":{"alertsCount":0,"bookmarksCount":0,"commentsCount":0,"alertProductNames":[],"tactics":[]},"relatedAnalyticRuleIds":[],"incidentUrl":"https://portal.azure.com/#asset/Microsoft_Azure_Security_Insights/Incident/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5"}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '1557'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:44 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: '{"properties": {"message": "Some message"}}'
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident-comment create
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '43'
+ Content-Type:
+ - application/json
+ ParameterSetName:
+ - --message --incident-comment-id --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: PUT
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/comments/4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/Comments/4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","name":"4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","etag":"\"d800e353-0000-0100-0000-5fc47f4e0000\"","type":"Microsoft.SecurityInsights/Incidents/Comments","properties":{"message":"Some
+ message","createdTimeUtc":"2020-11-30T05:12:46.1753157Z","lastModifiedTimeUtc":"2020-11-30T05:12:46.1753157Z","author":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma","userPrincipalName":"bim_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft.com"}}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '828'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:45 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-writes:
+ - '1199'
+ status:
+ code: 201
+ message: Created
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident-comment list
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/comments?api-version=2020-01-01
+ response:
+ body:
+ string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/Comments/4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","name":"4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","etag":"\"d800e353-0000-0100-0000-5fc47f4e0000\"","type":"Microsoft.SecurityInsights/Incidents/Comments","properties":{"message":"Some
+ message","createdTimeUtc":"2020-11-30T05:12:46.1753157Z","lastModifiedTimeUtc":"2020-11-30T05:12:46.1753157Z","author":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma","userPrincipalName":"bim_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft.com"}}}]}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '840'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:46 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident-comment show
+ Connection:
+ - keep-alive
+ ParameterSetName:
+ - --incident-comment-id --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: GET
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/comments/4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014?api-version=2020-01-01
+ response:
+ body:
+ string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/Incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5/Comments/4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","name":"4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014","etag":"\"d800e353-0000-0100-0000-5fc47f4e0000\"","type":"Microsoft.SecurityInsights/Incidents/Comments","properties":{"message":"Some
+ message","createdTimeUtc":"2020-11-30T05:12:46.1753157Z","lastModifiedTimeUtc":"2020-11-30T05:12:46.1753157Z","author":{"objectId":"9ac02ab3-5061-4ec6-a3d8-2cdaa5f29efa","email":"bim@microsoft.com","name":"Bin
+ Ma","userPrincipalName":"bim_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft.com"}}}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '828'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:47 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ CommandName:
+ - sentinel incident delete
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '0'
+ ParameterSetName:
+ - -y --incident-id --resource-group --workspace-name
+ User-Agent:
+ - AZURECLI/2.15.0 azsdk-python-securityinsights/unknown Python/3.8.5 (Windows-10-10.0.19041-SP0)
+ method: DELETE
+ uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.OperationalInsights/workspaces/cli-test-ws-000002/providers/Microsoft.SecurityInsights/incidents/73e01a99-5cd7-4139-a149-9f2736ff2ab5?api-version=2020-01-01
+ response:
+ body:
+ string: '{}'
+ headers:
+ cache-control:
+ - no-cache
+ content-length:
+ - '2'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 30 Nov 2020 05:12:47 GMT
+ expires:
+ - '-1'
+ pragma:
+ - no-cache
+ server:
+ - Kestrel
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains
+ transfer-encoding:
+ - chunked
+ vary:
+ - Accept-Encoding
+ x-content-type-options:
+ - nosniff
+ x-ms-ratelimit-remaining-subscription-deletes:
+ - '14999'
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario.py b/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario.py
new file mode 100644
index 00000000000..d31c08bb247
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario.py
@@ -0,0 +1,535 @@
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+import os
+from azure.cli.testsdk import ScenarioTest
+from .. import try_manual, raise_if, calc_coverage
+from azure.cli.testsdk import ResourceGroupPreparer
+from azure_devtools.scenario_tests import AllowLargeResponse
+
+
+TEST_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__), '..'))
+
+
+# Env setup
+@try_manual
+def setup(test, rg):
+ test.kwargs.update({
+ 'workspace': test.create_random_name('cli-test-ws-', 24)
+ })
+ test.cmd('az monitor log-analytics workspace create -g {rg} -n {workspace}')
+
+
+# EXAMPLE: /Actions/get/Get all actions of alert rule.
+@try_manual
+def step__actions_get_get_all_actions_of_alert_rule_(test, rg):
+ test.cmd('az sentinel action list '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/put/Creates or updates a Fusion alert rule.
+@try_manual
+def step__alertrules_put(test, rg):
+ test.cmd('az sentinel alert-rule create '
+ '--fusion-alert-rule etag="3d00c3ca-0000-0100-0000-5d42d5010000" alert-rule-template-name="f71aba3d-28fb-4'
+ '50b-b192-4e76a83015c8" enabled=true '
+ '--resource-group "{rg}" '
+ '--rule-id "myFirstFusionRule" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('enabled', True),
+ test.check('kind', 'Fusion'),
+ test.check('name', 'myFirstFusionRule')
+ ])
+
+
+# EXAMPLE: /AlertRules/put/Creates or updates a MicrosoftSecurityIncidentCreation rule.
+@try_manual
+def step__alertrules_put2(test, rg):
+ test.cmd('az sentinel alert-rule create '
+ '--microsoft-security-incident-creation-alert-rule etag="260097e0-0000-0d00-0000-5d6fa88f0000" '
+ 'product-filter="Microsoft Cloud App Security" display-name="testing displayname" enabled=true '
+ '--resource-group "{rg}" '
+ '--rule-id "microsoftSecurityIncidentCreationRuleExample" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('enabled', True),
+ test.check('kind', 'MicrosoftSecurityIncidentCreation'),
+ test.check('name', 'microsoftSecurityIncidentCreationRuleExample'),
+ test.check('productFilter', 'Microsoft Cloud App Security'),
+ test.check('displayName', 'testing displayname')
+ ])
+
+
+# EXAMPLE: /AlertRules/put/Creates or updates a Scheduled alert rule.
+@try_manual
+def step__alertrules_put3(test, rg):
+ # BadRequestError: (BadRequest) Failed to run the alert rule query. One of the tables does not exist.
+ test.cmd('az sentinel alert-rule create '
+ '--scheduled-alert-rule etag="0300bf09-0000-0000-0000-5c37296e0000" query="ProtectionStatus | extend HostCustomEntity = Computer | extend IPCustomEntity = ComputerIP_Hidden“ '
+ 'query-frequency="PT1H" query-period="P2DT1H30M" severity="High" '
+ 'trigger-operator="GreaterThan" trigger-threshold=0 description="" display-name="Rule2" enabled=true '
+ 'suppression-duration="PT1H" suppression-enabled=false tactics="Persistence" tactics="LateralMovement" '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/put/Creates or updates an action of alert rule.
+@try_manual
+def step__alertrules_put4(test, rg):
+ test.cmd('az sentinel alert-rule create '
+ '--etag "0300bf09-0000-0000-0000-5c37296e0000" '
+ '--logic-app-resource-id "/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.Logic/w'
+ 'orkflows/MyAlerts" '
+ '--trigger-uri "https://prod-31.northcentralus.logic.azure.com:443/workflows/cd3765391efd48549fd7681ded1d4'
+ '8d7/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=signatur'
+ 'e" '
+ '--action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/get/Get a Fusion alert rule.
+@try_manual
+def step__alertrules_get_get_a_fusion_alert_rule_(test, rg):
+ test.cmd('az sentinel alert-rule show '
+ '--resource-group "{rg}" '
+ '--rule-id "myFirstFusionRule" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('enabled', True),
+ test.check('kind', 'Fusion'),
+ test.check('name', 'myFirstFusionRule')
+ ])
+
+
+# EXAMPLE: /AlertRules/get/Get a MicrosoftSecurityIncidentCreation rule.
+@try_manual
+def step__alertrules_get(test, rg):
+ test.cmd('az sentinel alert-rule show '
+ '--resource-group "{rg}" '
+ '--rule-id "microsoftSecurityIncidentCreationRuleExample" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('enabled', True),
+ test.check('kind', 'MicrosoftSecurityIncidentCreation'),
+ test.check('name', 'microsoftSecurityIncidentCreationRuleExample'),
+ test.check('productFilter', 'Microsoft Cloud App Security'),
+ test.check('displayName', 'testing displayname')
+ ])
+
+
+# EXAMPLE: /AlertRules/get/Get a Scheduled alert rule.
+@try_manual
+def step__alertrules_get_get_a_scheduled_alert_rule_(test, rg):
+ test.cmd('az sentinel alert-rule show '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/get/Get all alert rules.
+@try_manual
+def step__alertrules_get_get_all_alert_rules_(test, rg):
+ test.cmd('az sentinel alert-rule list '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('length(@)', 2)
+ ])
+
+
+# EXAMPLE: /AlertRules/get/Get an action of alert rule.
+@try_manual
+def step__alertrules_get_get_an_action_of_alert_rule_(test, rg):
+ test.cmd('az sentinel alert-rule get-action '
+ '--action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/delete/Delete an action of alert rule.
+@try_manual
+def step__alertrules_delete(test, rg):
+ test.cmd('az sentinel alert-rule delete -y '
+ '--action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /AlertRules/delete/Delete an alert rule.
+@try_manual
+def step__alertrules_delete_delete_an_alert_rule_(test, rg):
+ test.cmd('az sentinel alert-rule delete -y '
+ '--resource-group "{rg}" '
+ '--rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+@try_manual
+def step__alertrules_delete_delete_a_fusion_alert_rule_(test, rg):
+ test.cmd('az sentinel alert-rule delete -y '
+ '--resource-group "{rg}" '
+ '--rule-id "myFirstFusionRule" '
+ '--workspace-name {workspace}')
+
+
+# EXAMPLE: /AlertRuleTemplates/get/Get alert rule template by Id.
+@try_manual
+def step__alertruletemplates_get(test, rg):
+ test.cmd('az sentinel alert-rule-template show '
+ '--alert-rule-template-id "65360bb0-8986-4ade-a89d-af3cf44d28aa" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('kind', 'Scheduled'),
+ test.check('name', '65360bb0-8986-4ade-a89d-af3cf44d28aa')
+ ])
+
+
+# EXAMPLE: /Bookmarks/put/Creates or updates a bookmark.
+@try_manual
+def step__bookmarks_put_creates_or_updates_a_bookmark_(test, rg):
+ test.cmd('az sentinel bookmark create '
+ '--etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" '
+ '--created "2019-01-01T13:15:30Z" '
+ '--display-name "My bookmark" '
+ '--labels "Tag1" '
+ '--labels "Tag2" '
+ '--notes "Found a suspicious activity" '
+ '-q "SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)" '
+ '--query-result "Security Event query result" '
+ '--updated "2019-01-01T13:15:30Z" '
+ '--bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('name', '73e01a99-5cd7-4139-a149-9f2736ff2ab5'),
+ test.check('query', 'SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)')
+ ])
+
+
+# EXAMPLE: /Bookmarks/get/Get a bookmark.
+@try_manual
+def step__bookmarks_get_get_a_bookmark_(test, rg):
+ test.cmd('az sentinel bookmark show '
+ '--bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('name', '73e01a99-5cd7-4139-a149-9f2736ff2ab5'),
+ test.check('query', 'SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)')
+ ])
+
+
+# EXAMPLE: /Bookmarks/get/Get all bookmarks.
+@try_manual
+def step__bookmarks_get_get_all_bookmarks_(test, rg):
+ test.cmd('az sentinel bookmark list '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('length(@)', 1),
+ test.check('[0].name', '73e01a99-5cd7-4139-a149-9f2736ff2ab5'),
+ test.check('[0].query', 'SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)')
+ ])
+
+
+# EXAMPLE: /DataConnectors/put/Creates or updates an Office365 data connector.
+@try_manual
+def step__dataconnectors_put(test, rg):
+ test.cmd('az sentinel data-connector create '
+ '--office-data-connector etag="\\"0300bf09-0000-0000-0000-5c37296e0000\\"" tenant-id="2070ecc9-b4d5-4ae4-adaa-936fa1954fa8" '
+ '--data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get a ASC data connector.
+@try_manual
+def step__dataconnectors_get_get_a_asc_data_connector_(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "763f9fa1-c2d3-4fa2-93e9-bccd4899aa12" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get a MCAS data connector.
+@try_manual
+def step__dataconnectors_get(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "b96d014d-b5c2-4a01-9aba-a8058f629d42" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get a MDATP data connector
+@try_manual
+def step__dataconnectors_get2(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "06b3ccb8-1384-4bcc-aec7-852f6d57161b" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get a TI data connector.
+@try_manual
+def step__dataconnectors_get_get_a_ti_data_connector_(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get all data connectors.
+@try_manual
+def step__dataconnectors_get_get_all_data_connectors_(test, rg):
+ test.cmd('az sentinel data-connector list '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get an AAD data connector.
+@try_manual
+def step__dataconnectors_get3(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "f0cd27d2-5f03-4c06-ba31-d2dc82dcb51d" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get an AATP data connector.
+@try_manual
+def step__dataconnectors_get4(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "07e42cb3-e658-4e90-801c-efa0f29d3d44" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get an AwsCloudTrail data connector.
+@try_manual
+def step__dataconnectors_get5(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/get/Get an Office365 data connector.
+@try_manual
+def step__dataconnectors_get6(test, rg):
+ test.cmd('az sentinel data-connector show '
+ '--data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /DataConnectors/delete/Delete an Office365 data connector.
+@try_manual
+def step__dataconnectors_delete(test, rg):
+ test.cmd('az sentinel data-connector delete -y '
+ '--data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[])
+
+
+# EXAMPLE: /IncidentComments/put/Creates an incident comment.
+@try_manual
+def step__incidentcomments_put(test, rg):
+ test.cmd('az sentinel incident-comment create '
+ '--message "Some message" '
+ '--incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" '
+ '--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('message', 'Some message'),
+ test.check('name', '4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014')
+ ])
+
+
+# EXAMPLE: /IncidentComments/get/Get all incident comments.
+@try_manual
+def step__incidentcomments_get(test, rg):
+ test.cmd('az sentinel incident-comment list '
+ '--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('length(@)', 1),
+ test.check('[0].message', 'Some message'),
+ test.check('[0].name', '4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014')
+ ])
+
+
+# EXAMPLE: /IncidentComments/get/Get an incident comment.
+@try_manual
+def step__incidentcomments_get2(test, rg):
+ test.cmd('az sentinel incident-comment show '
+ '--incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" '
+ '--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('message', 'Some message'),
+ test.check('name', '4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014')
+ ])
+
+
+# EXAMPLE: /Incidents/put/Creates or updates an incident.
+@try_manual
+def step__incidents_put(test, rg):
+ test.cmd('az sentinel incident create '
+ '--etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" '
+ '--description "This is a demo incident" '
+ '--classification "FalsePositive" '
+ '--classification-comment "Not a malicious activity" '
+ '--classification-reason "IncorrectAlertLogic" '
+ '--first-activity-time-utc "2019-01-01T13:00:30Z" '
+ '--last-activity-time-utc "2019-01-01T13:05:30Z" '
+ '--owner object-id="2046feea-040d-4a46-9e2b-91c2941bfa70" '
+ '--severity "High" '
+ '--status "Closed" '
+ '--title "title" '
+ '--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('classification', 'FalsePositive'),
+ test.check('classificationReason', 'IncorrectAlertLogic'),
+ test.check('classificationComment', 'Not a malicious activity'),
+ test.check('severity', 'High'),
+ test.check('title', 'title'),
+ test.check('status', 'Closed')
+ ])
+
+
+# EXAMPLE: /Incidents/get/Get all incidents.
+@try_manual
+def step__incidents_get_get_all_incidents_(test, rg):
+ test.cmd('az sentinel incident list '
+ '--orderby "properties/createdTimeUtc desc" '
+ '--top 1 '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('length(@)', 1),
+ test.check('[0].name', '73e01a99-5cd7-4139-a149-9f2736ff2ab5')
+ ])
+
+
+# EXAMPLE: /Incidents/get/Get an incident.
+@try_manual
+def step__incidents_get_get_an_incident_(test, rg):
+ test.cmd('az sentinel incident show '
+ '--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" '
+ '--resource-group "{rg}" '
+ '--workspace-name {workspace}',
+ checks=[
+ test.check('classification', 'FalsePositive'),
+ test.check('classificationReason', 'IncorrectAlertLogic'),
+ test.check('classificationComment', 'Not a malicious activity'),
+ test.check('severity', 'High'),
+ test.check('title', 'title'),
+ test.check('status', 'Closed')
+ ])
+
+
+# Env cleanup
+@try_manual
+def cleanup(test, rg):
+ pass
+
+
+# Testcase
+@try_manual
+def call_scenario(test, rg):
+ setup(test, rg)
+ step__alertrules_put(test, rg)
+ step__alertrules_put2(test, rg)
+ # step__alertrules_put3(test, rg)
+ # step__alertrules_put4(test, rg)
+ step__alertrules_get_get_a_fusion_alert_rule_(test, rg)
+ step__alertrules_get(test, rg)
+ # step__alertrules_get_get_a_scheduled_alert_rule_(test, rg)
+ step__alertrules_get_get_all_alert_rules_(test, rg)
+ # step__alertrules_get_get_an_action_of_alert_rule_(test, rg)
+ # step__alertrules_delete(test, rg)
+ # step__alertrules_delete_delete_an_alert_rule_(test, rg)
+ step__alertrules_delete_delete_a_fusion_alert_rule_(test, rg)
+ step__alertruletemplates_get(test, rg)
+ step__alertruletemplates_list(test, rg)
+ # step__actions_get_get_all_actions_of_alert_rule_(test, rg)
+ step__bookmarks_put_creates_or_updates_a_bookmark_(test, rg)
+ step__bookmarks_get_get_a_bookmark_(test, rg)
+ step__bookmarks_get_get_all_bookmarks_(test, rg)
+ step__bookmarks_delete_delete_a_bookmark_(test, rg)
+
+ # step__dataconnectors_put(test, rg)
+ # step__dataconnectors_get_get_a_asc_data_connector_(test, rg)
+ # step__dataconnectors_get(test, rg)
+ # step__dataconnectors_get2(test, rg)
+ # step__dataconnectors_get_get_a_ti_data_connector_(test, rg)
+ # step__dataconnectors_get_get_all_data_connectors_(test, rg)
+ # step__dataconnectors_get3(test, rg)
+ # step__dataconnectors_get4(test, rg)
+ # step__dataconnectors_get5(test, rg)
+ # step__dataconnectors_get6(test, rg)
+ # step__dataconnectors_delete(test, rg)
+
+ step__incidents_put(test, rg)
+ # step__incidents_get_get_all_incidents_(test, rg)
+ step__incidents_get_get_an_incident_(test, rg)
+ step__incidentcomments_put(test, rg)
+ step__incidentcomments_get(test, rg)
+ step__incidentcomments_get2(test, rg)
+ step__incidents_delete_delete_an_incident_(test, rg)
+ cleanup(test, rg)
+
+
+@try_manual
+class SecurityInsightsScenarioTest(ScenarioTest):
+
+ @ResourceGroupPreparer(name_prefix='clitestsentinel_myRg'[:7], key='rg', parameter_name='rg')
+ @AllowLargeResponse()
+ def test_sentinel(self, rg):
+
+ self.kwargs.update({
+ 'subscription_id': self.get_subscription_id()
+ })
+
+ call_scenario(self, rg)
+ calc_coverage(__file__)
+ raise_if()
diff --git a/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario_coverage.md b/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario_coverage.md
new file mode 100644
index 00000000000..92d9c097816
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/tests/latest/test_sentinel_scenario_coverage.md
@@ -0,0 +1,20 @@
+|Scenario|Result|ErrorMessage|ErrorStack|ErrorNormalized|StartDt|EndDt|
+|step__alertrules_put|successed||||2020-11-30 05:12:10.340025|2020-11-30 05:12:14.212919|
+|step__alertrules_put2|successed||||2020-11-30 05:12:14.213902|2020-11-30 05:12:16.912928|
+|step__alertrules_get_get_a_fusion_alert_rule_|successed||||2020-11-30 05:12:16.913927|2020-11-30 05:12:18.411054|
+|step__alertrules_get|successed||||2020-11-30 05:12:18.412055|2020-11-30 05:12:21.541734|
+|step__alertrules_get_get_all_alert_rules_|successed||||2020-11-30 05:12:21.541734|2020-11-30 05:12:23.591243|
+|step__alertrules_delete_delete_a_fusion_alert_rule_|successed||||2020-11-30 05:12:23.592241|2020-11-30 05:12:26.496214|
+|step__alertruletemplates_get|successed||||2020-11-30 05:12:26.497214|2020-11-30 05:12:29.682131|
+|step__alertruletemplates_list|successed||||2020-11-30 05:12:29.682131|2020-11-30 05:12:33.559276|
+|step__bookmarks_put_creates_or_updates_a_bookmark_|successed||||2020-11-30 05:12:33.560277|2020-11-30 05:12:36.664603|
+|step__bookmarks_get_get_a_bookmark_|successed||||2020-11-30 05:12:36.665672|2020-11-30 05:12:37.405872|
+|step__bookmarks_get_get_all_bookmarks_|successed||||2020-11-30 05:12:37.406872|2020-11-30 05:12:38.657312|
+|step__bookmarks_delete_delete_a_bookmark_|successed||||2020-11-30 05:12:38.658311|2020-11-30 05:12:41.040726|
+|step__incidents_put|successed||||2020-11-30 05:12:41.040726|2020-11-30 05:12:43.390843|
+|step__incidents_get_get_an_incident_|successed||||2020-11-30 05:12:43.391911|2020-11-30 05:12:45.395363|
+|step__incidentcomments_put|successed||||2020-11-30 05:12:45.396360|2020-11-30 05:12:46.378773|
+|step__incidentcomments_get|successed||||2020-11-30 05:12:46.379844|2020-11-30 05:12:47.110435|
+|step__incidentcomments_get2|successed||||2020-11-30 05:12:47.111432|2020-11-30 05:12:47.890755|
+|step__incidents_delete_delete_an_incident_|successed||||2020-11-30 05:12:47.891754|2020-11-30 05:12:48.690398|
+Coverage: 18/18
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/__init__.py
new file mode 100644
index 00000000000..c9cfdc73e77
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/__init__.py
@@ -0,0 +1,12 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+#
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is
+# regenerated.
+# --------------------------------------------------------------------------
+
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/__init__.py
new file mode 100644
index 00000000000..adcb1a40f19
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/__init__.py
@@ -0,0 +1,16 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from ._security_insights import SecurityInsights
+__all__ = ['SecurityInsights']
+
+try:
+ from ._patch import patch_sdk # type: ignore
+ patch_sdk()
+except ImportError:
+ pass
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_configuration.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_configuration.py
new file mode 100644
index 00000000000..e24ce7ef4eb
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_configuration.py
@@ -0,0 +1,70 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from typing import TYPE_CHECKING
+
+from azure.core.configuration import Configuration
+from azure.core.pipeline import policies
+from azure.mgmt.core.policies import ARMHttpLoggingPolicy
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any
+
+ from azure.core.credentials import TokenCredential
+
+VERSION = "unknown"
+
+class SecurityInsightsConfiguration(Configuration):
+ """Configuration for SecurityInsights.
+
+ Note that all parameters used to create this instance are saved as instance
+ attributes.
+
+ :param credential: Credential needed for the client to connect to Azure.
+ :type credential: ~azure.core.credentials.TokenCredential
+ :param subscription_id: Azure subscription ID.
+ :type subscription_id: str
+ """
+
+ def __init__(
+ self,
+ credential, # type: "TokenCredential"
+ subscription_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ if credential is None:
+ raise ValueError("Parameter 'credential' must not be None.")
+ if subscription_id is None:
+ raise ValueError("Parameter 'subscription_id' must not be None.")
+ super(SecurityInsightsConfiguration, self).__init__(**kwargs)
+
+ self.credential = credential
+ self.subscription_id = subscription_id
+ self.api_version = "2020-01-01"
+ self.credential_scopes = kwargs.pop('credential_scopes', ['https://management.azure.com/.default'])
+ kwargs.setdefault('sdk_moniker', 'securityinsights/{}'.format(VERSION))
+ self._configure(**kwargs)
+
+ def _configure(
+ self,
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get('http_logging_policy') or ARMHttpLoggingPolicy(**kwargs)
+ self.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs)
+ self.authentication_policy = kwargs.get('authentication_policy')
+ if self.credential and not self.authentication_policy:
+ self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_security_insights.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_security_insights.py
new file mode 100644
index 00000000000..3f1b4e49c01
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/_security_insights.py
@@ -0,0 +1,103 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from typing import TYPE_CHECKING
+
+from azure.mgmt.core import ARMPipelineClient
+from msrest import Deserializer, Serializer
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Optional
+
+ from azure.core.credentials import TokenCredential
+
+from ._configuration import SecurityInsightsConfiguration
+from .operations import OperationOperations
+from .operations import AlertRuleOperations
+from .operations import ActionOperations
+from .operations import AlertRuleTemplateOperations
+from .operations import BookmarkOperations
+from .operations import DataConnectorOperations
+from .operations import IncidentOperations
+from .operations import IncidentCommentOperations
+from . import models
+
+
+class SecurityInsights(object):
+ """API spec for Microsoft.SecurityInsights (Azure Security Insights) resource provider.
+
+ :ivar operation: OperationOperations operations
+ :vartype operation: security_insights.operations.OperationOperations
+ :ivar alert_rule: AlertRuleOperations operations
+ :vartype alert_rule: security_insights.operations.AlertRuleOperations
+ :ivar action: ActionOperations operations
+ :vartype action: security_insights.operations.ActionOperations
+ :ivar alert_rule_template: AlertRuleTemplateOperations operations
+ :vartype alert_rule_template: security_insights.operations.AlertRuleTemplateOperations
+ :ivar bookmark: BookmarkOperations operations
+ :vartype bookmark: security_insights.operations.BookmarkOperations
+ :ivar data_connector: DataConnectorOperations operations
+ :vartype data_connector: security_insights.operations.DataConnectorOperations
+ :ivar incident: IncidentOperations operations
+ :vartype incident: security_insights.operations.IncidentOperations
+ :ivar incident_comment: IncidentCommentOperations operations
+ :vartype incident_comment: security_insights.operations.IncidentCommentOperations
+ :param credential: Credential needed for the client to connect to Azure.
+ :type credential: ~azure.core.credentials.TokenCredential
+ :param subscription_id: Azure subscription ID.
+ :type subscription_id: str
+ :param str base_url: Service URL
+ """
+
+ def __init__(
+ self,
+ credential, # type: "TokenCredential"
+ subscription_id, # type: str
+ base_url=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ if not base_url:
+ base_url = 'https://management.azure.com'
+ self._config = SecurityInsightsConfiguration(credential, subscription_id, **kwargs)
+ self._client = ARMPipelineClient(base_url=base_url, config=self._config, **kwargs)
+
+ client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
+ self._serialize = Serializer(client_models)
+ self._deserialize = Deserializer(client_models)
+
+ self.operation = OperationOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.alert_rule = AlertRuleOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.action = ActionOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.alert_rule_template = AlertRuleTemplateOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.bookmark = BookmarkOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.data_connector = DataConnectorOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.incident = IncidentOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.incident_comment = IncidentCommentOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+
+ def close(self):
+ # type: () -> None
+ self._client.close()
+
+ def __enter__(self):
+ # type: () -> SecurityInsights
+ self._client.__enter__()
+ return self
+
+ def __exit__(self, *exc_details):
+ # type: (Any) -> None
+ self._client.__exit__(*exc_details)
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/__init__.py
new file mode 100644
index 00000000000..17980852599
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/__init__.py
@@ -0,0 +1,10 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from ._security_insights import SecurityInsights
+__all__ = ['SecurityInsights']
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_configuration.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_configuration.py
new file mode 100644
index 00000000000..160eb378d2f
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_configuration.py
@@ -0,0 +1,66 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from typing import Any, TYPE_CHECKING
+
+from azure.core.configuration import Configuration
+from azure.core.pipeline import policies
+from azure.mgmt.core.policies import ARMHttpLoggingPolicy
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from azure.core.credentials_async import AsyncTokenCredential
+
+VERSION = "unknown"
+
+class SecurityInsightsConfiguration(Configuration):
+ """Configuration for SecurityInsights.
+
+ Note that all parameters used to create this instance are saved as instance
+ attributes.
+
+ :param credential: Credential needed for the client to connect to Azure.
+ :type credential: ~azure.core.credentials_async.AsyncTokenCredential
+ :param subscription_id: Azure subscription ID.
+ :type subscription_id: str
+ """
+
+ def __init__(
+ self,
+ credential: "AsyncTokenCredential",
+ subscription_id: str,
+ **kwargs: Any
+ ) -> None:
+ if credential is None:
+ raise ValueError("Parameter 'credential' must not be None.")
+ if subscription_id is None:
+ raise ValueError("Parameter 'subscription_id' must not be None.")
+ super(SecurityInsightsConfiguration, self).__init__(**kwargs)
+
+ self.credential = credential
+ self.subscription_id = subscription_id
+ self.api_version = "2020-01-01"
+ self.credential_scopes = kwargs.pop('credential_scopes', ['https://management.azure.com/.default'])
+ kwargs.setdefault('sdk_moniker', 'securityinsights/{}'.format(VERSION))
+ self._configure(**kwargs)
+
+ def _configure(
+ self,
+ **kwargs: Any
+ ) -> None:
+ self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get('http_logging_policy') or ARMHttpLoggingPolicy(**kwargs)
+ self.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs)
+ self.authentication_policy = kwargs.get('authentication_policy')
+ if self.credential and not self.authentication_policy:
+ self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_security_insights.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_security_insights.py
new file mode 100644
index 00000000000..7eb275a24fa
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/_security_insights.py
@@ -0,0 +1,97 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from typing import Any, Optional, TYPE_CHECKING
+
+from azure.mgmt.core import AsyncARMPipelineClient
+from msrest import Deserializer, Serializer
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from azure.core.credentials_async import AsyncTokenCredential
+
+from ._configuration import SecurityInsightsConfiguration
+from .operations import OperationOperations
+from .operations import AlertRuleOperations
+from .operations import ActionOperations
+from .operations import AlertRuleTemplateOperations
+from .operations import BookmarkOperations
+from .operations import DataConnectorOperations
+from .operations import IncidentOperations
+from .operations import IncidentCommentOperations
+from .. import models
+
+
+class SecurityInsights(object):
+ """API spec for Microsoft.SecurityInsights (Azure Security Insights) resource provider.
+
+ :ivar operation: OperationOperations operations
+ :vartype operation: security_insights.aio.operations.OperationOperations
+ :ivar alert_rule: AlertRuleOperations operations
+ :vartype alert_rule: security_insights.aio.operations.AlertRuleOperations
+ :ivar action: ActionOperations operations
+ :vartype action: security_insights.aio.operations.ActionOperations
+ :ivar alert_rule_template: AlertRuleTemplateOperations operations
+ :vartype alert_rule_template: security_insights.aio.operations.AlertRuleTemplateOperations
+ :ivar bookmark: BookmarkOperations operations
+ :vartype bookmark: security_insights.aio.operations.BookmarkOperations
+ :ivar data_connector: DataConnectorOperations operations
+ :vartype data_connector: security_insights.aio.operations.DataConnectorOperations
+ :ivar incident: IncidentOperations operations
+ :vartype incident: security_insights.aio.operations.IncidentOperations
+ :ivar incident_comment: IncidentCommentOperations operations
+ :vartype incident_comment: security_insights.aio.operations.IncidentCommentOperations
+ :param credential: Credential needed for the client to connect to Azure.
+ :type credential: ~azure.core.credentials_async.AsyncTokenCredential
+ :param subscription_id: Azure subscription ID.
+ :type subscription_id: str
+ :param str base_url: Service URL
+ """
+
+ def __init__(
+ self,
+ credential: "AsyncTokenCredential",
+ subscription_id: str,
+ base_url: Optional[str] = None,
+ **kwargs: Any
+ ) -> None:
+ if not base_url:
+ base_url = 'https://management.azure.com'
+ self._config = SecurityInsightsConfiguration(credential, subscription_id, **kwargs)
+ self._client = AsyncARMPipelineClient(base_url=base_url, config=self._config, **kwargs)
+
+ client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
+ self._serialize = Serializer(client_models)
+ self._deserialize = Deserializer(client_models)
+
+ self.operation = OperationOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.alert_rule = AlertRuleOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.action = ActionOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.alert_rule_template = AlertRuleTemplateOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.bookmark = BookmarkOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.data_connector = DataConnectorOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.incident = IncidentOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+ self.incident_comment = IncidentCommentOperations(
+ self._client, self._config, self._serialize, self._deserialize)
+
+ async def close(self) -> None:
+ await self._client.close()
+
+ async def __aenter__(self) -> "SecurityInsights":
+ await self._client.__aenter__()
+ return self
+
+ async def __aexit__(self, *exc_details) -> None:
+ await self._client.__aexit__(*exc_details)
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/__init__.py
new file mode 100644
index 00000000000..5e67996dcd4
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/__init__.py
@@ -0,0 +1,27 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from ._operation_operations import OperationOperations
+from ._alert_rule_operations import AlertRuleOperations
+from ._action_operations import ActionOperations
+from ._alert_rule_template_operations import AlertRuleTemplateOperations
+from ._bookmark_operations import BookmarkOperations
+from ._data_connector_operations import DataConnectorOperations
+from ._incident_operations import IncidentOperations
+from ._incident_comment_operations import IncidentCommentOperations
+
+__all__ = [
+ 'OperationOperations',
+ 'AlertRuleOperations',
+ 'ActionOperations',
+ 'AlertRuleTemplateOperations',
+ 'BookmarkOperations',
+ 'DataConnectorOperations',
+ 'IncidentOperations',
+ 'IncidentCommentOperations',
+]
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_action_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_action_operations.py
new file mode 100644
index 00000000000..378198b2cfb
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_action_operations.py
@@ -0,0 +1,121 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class ActionOperations:
+ """ActionOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list_by_alert_rule(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ **kwargs
+ ) -> AsyncIterable["models.ActionsList"]:
+ """Gets all actions of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either ActionsList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.ActionsList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionsList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list_by_alert_rule.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('ActionsList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list_by_alert_rule.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_operations.py
new file mode 100644
index 00000000000..89d90bb06be
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_operations.py
@@ -0,0 +1,535 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar, Union
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class AlertRuleOperations:
+ """AlertRuleOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ **kwargs
+ ) -> AsyncIterable["models.AlertRulesList"]:
+ """Gets all alert rules.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either AlertRulesList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.AlertRulesList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRulesList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('AlertRulesList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ **kwargs
+ ) -> "models.AlertRule":
+ """Gets the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRule, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRule
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRule"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ async def create_or_update(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ alert_rule: "models.AlertRule",
+ **kwargs
+ ) -> "models.AlertRule":
+ """Creates or updates the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param alert_rule: The alert rule.
+ :type alert_rule: ~security_insights.models.AlertRule
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRule, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRule
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRule"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(alert_rule, 'AlertRule')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ async def delete(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ **kwargs
+ ) -> None:
+ """Delete the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ async def get_action(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ action_id: str,
+ **kwargs
+ ) -> "models.ActionResponse":
+ """Gets the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: ActionResponse, or the result of cls(response)
+ :rtype: ~security_insights.models.ActionResponse
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionResponse"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
+
+ async def create_or_update_action(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ action_id: str,
+ etag: Optional[str] = None,
+ logic_app_resource_id: Optional[str] = None,
+ trigger_uri: Optional[str] = None,
+ **kwargs
+ ) -> "models.ActionResponse":
+ """Creates or updates the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: ActionResponse, or the result of cls(response)
+ :rtype: ~security_insights.models.ActionResponse
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionResponse"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ action = models.ActionRequest(etag=etag, logic_app_resource_id=logic_app_resource_id, trigger_uri=trigger_uri)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(action, 'ActionRequest')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
+
+ async def delete_action(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ rule_id: str,
+ action_id: str,
+ **kwargs
+ ) -> None:
+ """Delete the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_template_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_template_operations.py
new file mode 100644
index 00000000000..986138cb66b
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_alert_rule_template_operations.py
@@ -0,0 +1,180 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class AlertRuleTemplateOperations:
+ """AlertRuleTemplateOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ **kwargs
+ ) -> AsyncIterable["models.AlertRuleTemplatesList"]:
+ """Gets all alert rule templates.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either AlertRuleTemplatesList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.AlertRuleTemplatesList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRuleTemplatesList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('AlertRuleTemplatesList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRuleTemplates'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ alert_rule_template_id: str,
+ **kwargs
+ ) -> "models.AlertRuleTemplate":
+ """Gets the alert rule template.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param alert_rule_template_id: Alert rule template ID.
+ :type alert_rule_template_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRuleTemplate, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRuleTemplate
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRuleTemplate"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'alertRuleTemplateId': self._serialize.url("alert_rule_template_id", alert_rule_template_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('AlertRuleTemplate', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRuleTemplates/{alertRuleTemplateId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_bookmark_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_bookmark_operations.py
new file mode 100644
index 00000000000..6cd59a2dc8c
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_bookmark_operations.py
@@ -0,0 +1,345 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+import datetime
+from typing import Any, AsyncIterable, Callable, Dict, Generic, List, Optional, TypeVar, Union
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class BookmarkOperations:
+ """BookmarkOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ **kwargs
+ ) -> AsyncIterable["models.BookmarkList"]:
+ """Gets all bookmarks.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either BookmarkList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.BookmarkList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.BookmarkList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('BookmarkList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ bookmark_id: str,
+ **kwargs
+ ) -> "models.Bookmark":
+ """Gets a bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Bookmark, or the result of cls(response)
+ :rtype: ~security_insights.models.Bookmark
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Bookmark"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
+
+ async def create_or_update(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ bookmark_id: str,
+ etag: Optional[str] = None,
+ created: Optional[datetime.datetime] = None,
+ display_name: Optional[str] = None,
+ labels: Optional[List[str]] = None,
+ notes: Optional[str] = None,
+ query: Optional[str] = None,
+ query_result: Optional[str] = None,
+ updated: Optional[datetime.datetime] = None,
+ incident_info: Optional["models.IncidentInfo"] = None,
+ object_id: Optional[str] = None,
+ **kwargs
+ ) -> "models.Bookmark":
+ """Creates or updates the bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param created: The time the bookmark was created.
+ :type created: ~datetime.datetime
+ :param display_name: The display name of the bookmark.
+ :type display_name: str
+ :param labels: List of labels relevant to this bookmark.
+ :type labels: list[str]
+ :param notes: The notes of the bookmark.
+ :type notes: str
+ :param query: The query of the bookmark.
+ :type query: str
+ :param query_result: The query result of the bookmark.
+ :type query_result: str
+ :param updated: The last time the bookmark was updated.
+ :type updated: ~datetime.datetime
+ :param incident_info: Describes an incident that relates to bookmark.
+ :type incident_info: ~security_insights.models.IncidentInfo
+ :param object_id: The object id of the user.
+ :type object_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Bookmark, or the result of cls(response)
+ :rtype: ~security_insights.models.Bookmark
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Bookmark"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ bookmark = models.Bookmark(etag=etag, created=created, display_name=display_name, labels=labels, notes=notes, query=query, query_result=query_result, updated=updated, incident_info=incident_info, object_id_updated_by_object_id=object_id)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(bookmark, 'Bookmark')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
+
+ async def delete(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ bookmark_id: str,
+ **kwargs
+ ) -> None:
+ """Delete the bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_data_connector_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_data_connector_operations.py
new file mode 100644
index 00000000000..9f83b3170a9
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_data_connector_operations.py
@@ -0,0 +1,315 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar, Union
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class DataConnectorOperations:
+ """DataConnectorOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ **kwargs
+ ) -> AsyncIterable["models.DataConnectorList"]:
+ """Gets all data connectors.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either DataConnectorList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.DataConnectorList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnectorList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('DataConnectorList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ data_connector_id: str,
+ **kwargs
+ ) -> "models.DataConnector":
+ """Gets a data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: DataConnector, or the result of cls(response)
+ :rtype: ~security_insights.models.DataConnector
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnector"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
+
+ async def create_or_update(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ data_connector_id: str,
+ data_connector: "models.DataConnector",
+ **kwargs
+ ) -> "models.DataConnector":
+ """Creates or updates the data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :param data_connector: The data connector.
+ :type data_connector: ~security_insights.models.DataConnector
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: DataConnector, or the result of cls(response)
+ :rtype: ~security_insights.models.DataConnector
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnector"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(data_connector, 'DataConnector')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
+
+ async def delete(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ data_connector_id: str,
+ **kwargs
+ ) -> None:
+ """Delete the data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_comment_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_comment_operations.py
new file mode 100644
index 00000000000..cc2b8403fc1
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_comment_operations.py
@@ -0,0 +1,287 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class IncidentCommentOperations:
+ """IncidentCommentOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list_by_incident(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ filter: Optional[str] = None,
+ orderby: Optional[str] = None,
+ top: Optional[int] = None,
+ skip_token: Optional[str] = None,
+ **kwargs
+ ) -> AsyncIterable["models.IncidentCommentList"]:
+ """Gets all incident comments.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param filter: Filters the results, based on a Boolean condition. Optional.
+ :type filter: str
+ :param orderby: Sorts the results. Optional.
+ :type orderby: str
+ :param top: Returns only the first n results. Optional.
+ :type top: int
+ :param skip_token: Skiptoken is only used if a previous operation returned a partial result. If
+ a previous response contains a nextLink element, the value of the nextLink element will include
+ a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.
+ :type skip_token: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either IncidentCommentList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.IncidentCommentList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentCommentList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list_by_incident.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+ if filter is not None:
+ query_parameters['$filter'] = self._serialize.query("filter", filter, 'str')
+ if orderby is not None:
+ query_parameters['$orderby'] = self._serialize.query("orderby", orderby, 'str')
+ if top is not None:
+ query_parameters['$top'] = self._serialize.query("top", top, 'int')
+ if skip_token is not None:
+ query_parameters['$skipToken'] = self._serialize.query("skip_token", skip_token, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('IncidentCommentList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list_by_incident.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ incident_comment_id: str,
+ **kwargs
+ ) -> "models.IncidentComment":
+ """Gets an incident comment.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param incident_comment_id: Incident comment ID.
+ :type incident_comment_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: IncidentComment, or the result of cls(response)
+ :rtype: ~security_insights.models.IncidentComment
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentComment"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ 'incidentCommentId': self._serialize.url("incident_comment_id", incident_comment_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('IncidentComment', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments/{incidentCommentId}'} # type: ignore
+
+ async def create_comment(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ incident_comment_id: str,
+ message: Optional[str] = None,
+ **kwargs
+ ) -> "models.IncidentComment":
+ """Creates the incident comment.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param incident_comment_id: Incident comment ID.
+ :type incident_comment_id: str
+ :param message: The comment message.
+ :type message: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: IncidentComment, or the result of cls(response)
+ :rtype: ~security_insights.models.IncidentComment
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentComment"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ incident_comment = models.IncidentComment(message=message)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_comment.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ 'incidentCommentId': self._serialize.url("incident_comment_id", incident_comment_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(incident_comment, 'IncidentComment')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('IncidentComment', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_comment.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments/{incidentCommentId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_operations.py
new file mode 100644
index 00000000000..8efc09e2788
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_incident_operations.py
@@ -0,0 +1,373 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+import datetime
+from typing import Any, AsyncIterable, Callable, Dict, Generic, List, Optional, TypeVar, Union
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class IncidentOperations:
+ """IncidentOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ filter: Optional[str] = None,
+ orderby: Optional[str] = None,
+ top: Optional[int] = None,
+ skip_token: Optional[str] = None,
+ **kwargs
+ ) -> AsyncIterable["models.IncidentList"]:
+ """Gets all incidents.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param filter: Filters the results, based on a Boolean condition. Optional.
+ :type filter: str
+ :param orderby: Sorts the results. Optional.
+ :type orderby: str
+ :param top: Returns only the first n results. Optional.
+ :type top: int
+ :param skip_token: Skiptoken is only used if a previous operation returned a partial result. If
+ a previous response contains a nextLink element, the value of the nextLink element will include
+ a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.
+ :type skip_token: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either IncidentList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.IncidentList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+ if filter is not None:
+ query_parameters['$filter'] = self._serialize.query("filter", filter, 'str')
+ if orderby is not None:
+ query_parameters['$orderby'] = self._serialize.query("orderby", orderby, 'str')
+ if top is not None:
+ query_parameters['$top'] = self._serialize.query("top", top, 'int')
+ if skip_token is not None:
+ query_parameters['$skipToken'] = self._serialize.query("skip_token", skip_token, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('IncidentList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents'} # type: ignore
+
+ async def get(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ **kwargs
+ ) -> "models.Incident":
+ """Gets an incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Incident, or the result of cls(response)
+ :rtype: ~security_insights.models.Incident
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Incident"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
+
+ async def create_or_update(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ etag: Optional[str] = None,
+ classification: Optional[Union[str, "models.IncidentClassification"]] = None,
+ classification_comment: Optional[str] = None,
+ classification_reason: Optional[Union[str, "models.IncidentClassificationReason"]] = None,
+ description: Optional[str] = None,
+ first_activity_time_utc: Optional[datetime.datetime] = None,
+ labels: Optional[List["models.IncidentLabel"]] = None,
+ last_activity_time_utc: Optional[datetime.datetime] = None,
+ owner: Optional["models.IncidentOwnerInfo"] = None,
+ severity: Optional[Union[str, "models.IncidentSeverity"]] = None,
+ status: Optional[Union[str, "models.IncidentStatus"]] = None,
+ title: Optional[str] = None,
+ **kwargs
+ ) -> "models.Incident":
+ """Creates or updates the incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param classification: The reason the incident was closed.
+ :type classification: str or ~security_insights.models.IncidentClassification
+ :param classification_comment: Describes the reason the incident was closed.
+ :type classification_comment: str
+ :param classification_reason: The classification reason the incident was closed with.
+ :type classification_reason: str or ~security_insights.models.IncidentClassificationReason
+ :param description: The description of the incident.
+ :type description: str
+ :param first_activity_time_utc: The time of the first activity in the incident.
+ :type first_activity_time_utc: ~datetime.datetime
+ :param labels: List of labels relevant to this incident.
+ :type labels: list[~security_insights.models.IncidentLabel]
+ :param last_activity_time_utc: The time of the last activity in the incident.
+ :type last_activity_time_utc: ~datetime.datetime
+ :param owner: Describes a user that the incident is assigned to.
+ :type owner: ~security_insights.models.IncidentOwnerInfo
+ :param severity: The severity of the incident.
+ :type severity: str or ~security_insights.models.IncidentSeverity
+ :param status: The status of the incident.
+ :type status: str or ~security_insights.models.IncidentStatus
+ :param title: The title of the incident.
+ :type title: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Incident, or the result of cls(response)
+ :rtype: ~security_insights.models.Incident
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Incident"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ incident = models.Incident(etag=etag, classification=classification, classification_comment=classification_comment, classification_reason=classification_reason, description=description, first_activity_time_utc=first_activity_time_utc, labels=labels, last_activity_time_utc=last_activity_time_utc, owner=owner, severity=severity, status=status, title=title)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(incident, 'Incident')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
+
+ async def delete(
+ self,
+ resource_group_name: str,
+ workspace_name: str,
+ incident_id: str,
+ **kwargs
+ ) -> None:
+ """Delete the incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_operation_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_operation_operations.py
new file mode 100644
index 00000000000..d8d19921e5c
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/aio/operations/_operation_operations.py
@@ -0,0 +1,104 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar
+import warnings
+
+from azure.core.async_paging import AsyncItemPaged, AsyncList
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from ... import models
+
+T = TypeVar('T')
+ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
+
+class OperationOperations:
+ """OperationOperations async operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer) -> None:
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ **kwargs
+ ) -> AsyncIterable["models.OperationsList"]:
+ """Lists all operations available Azure Security Insights Resource Provider.
+
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either OperationsList or the result of cls(response)
+ :rtype: ~azure.core.async_paging.AsyncItemPaged[~security_insights.models.OperationsList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.OperationsList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ async def extract_data(pipeline_response):
+ deserialized = self._deserialize('OperationsList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, AsyncList(list_of_elem)
+
+ async def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return AsyncItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/providers/Microsoft.SecurityInsights/operations'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/__init__.py
new file mode 100644
index 00000000000..d50534763d7
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/__init__.py
@@ -0,0 +1,245 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+try:
+ from ._models_py3 import AADDataConnector
+ from ._models_py3 import AATPDataConnector
+ from ._models_py3 import ASCDataConnector
+ from ._models_py3 import ASCDataConnectorProperties
+ from ._models_py3 import ActionPropertiesBase
+ from ._models_py3 import ActionRequest
+ from ._models_py3 import ActionRequestProperties
+ from ._models_py3 import ActionResponse
+ from ._models_py3 import ActionResponseProperties
+ from ._models_py3 import ActionsList
+ from ._models_py3 import AlertRule
+ from ._models_py3 import AlertRuleTemplate
+ from ._models_py3 import AlertRuleTemplateDataSource
+ from ._models_py3 import AlertRuleTemplatesList
+ from ._models_py3 import AlertRulesList
+ from ._models_py3 import AlertsDataTypeOfDataConnector
+ from ._models_py3 import AwsCloudTrailDataConnector
+ from ._models_py3 import AwsCloudTrailDataConnectorDataTypesLogs
+ from ._models_py3 import Bookmark
+ from ._models_py3 import BookmarkList
+ from ._models_py3 import ClientInfo
+ from ._models_py3 import DataConnector
+ from ._models_py3 import DataConnectorDataTypeCommon
+ from ._models_py3 import DataConnectorList
+ from ._models_py3 import DataConnectorTenantId
+ from ._models_py3 import DataConnectorWithAlertsProperties
+ from ._models_py3 import ErrorAdditionalInfo
+ from ._models_py3 import ErrorResponse
+ from ._models_py3 import FusionAlertRule
+ from ._models_py3 import FusionAlertRuleTemplate
+ from ._models_py3 import Incident
+ from ._models_py3 import IncidentAdditionalData
+ from ._models_py3 import IncidentComment
+ from ._models_py3 import IncidentCommentList
+ from ._models_py3 import IncidentInfo
+ from ._models_py3 import IncidentLabel
+ from ._models_py3 import IncidentList
+ from ._models_py3 import IncidentOwnerInfo
+ from ._models_py3 import MCASDataConnector
+ from ._models_py3 import MCASDataConnectorDataTypes
+ from ._models_py3 import MDATPDataConnector
+ from ._models_py3 import MicrosoftSecurityIncidentCreationAlertRule
+ from ._models_py3 import MicrosoftSecurityIncidentCreationAlertRuleCommonProperties
+ from ._models_py3 import MicrosoftSecurityIncidentCreationAlertRuleProperties
+ from ._models_py3 import MicrosoftSecurityIncidentCreationAlertRuleTemplate
+ from ._models_py3 import OfficeConsent
+ from ._models_py3 import OfficeConsentList
+ from ._models_py3 import OfficeDataConnector
+ from ._models_py3 import OfficeDataConnectorDataTypesExchange
+ from ._models_py3 import OfficeDataConnectorDataTypesSharePoint
+ from ._models_py3 import Operation
+ from ._models_py3 import OperationDisplay
+ from ._models_py3 import OperationsList
+ from ._models_py3 import Resource
+ from ._models_py3 import ResourceWithEtag
+ from ._models_py3 import ScheduledAlertRule
+ from ._models_py3 import ScheduledAlertRuleCommonProperties
+ from ._models_py3 import ScheduledAlertRuleProperties
+ from ._models_py3 import ScheduledAlertRuleTemplate
+ from ._models_py3 import Settings
+ from ._models_py3 import TIDataConnector
+ from ._models_py3 import TIDataConnectorDataTypesIndicators
+ from ._models_py3 import ThreatIntelligence
+ from ._models_py3 import ToggleSettings
+ from ._models_py3 import UebaSettings
+except (SyntaxError, ImportError):
+ from ._models import AADDataConnector # type: ignore
+ from ._models import AATPDataConnector # type: ignore
+ from ._models import ASCDataConnector # type: ignore
+ from ._models import ASCDataConnectorProperties # type: ignore
+ from ._models import ActionPropertiesBase # type: ignore
+ from ._models import ActionRequest # type: ignore
+ from ._models import ActionRequestProperties # type: ignore
+ from ._models import ActionResponse # type: ignore
+ from ._models import ActionResponseProperties # type: ignore
+ from ._models import ActionsList # type: ignore
+ from ._models import AlertRule # type: ignore
+ from ._models import AlertRuleTemplate # type: ignore
+ from ._models import AlertRuleTemplateDataSource # type: ignore
+ from ._models import AlertRuleTemplatesList # type: ignore
+ from ._models import AlertRulesList # type: ignore
+ from ._models import AlertsDataTypeOfDataConnector # type: ignore
+ from ._models import AwsCloudTrailDataConnector # type: ignore
+ from ._models import AwsCloudTrailDataConnectorDataTypesLogs # type: ignore
+ from ._models import Bookmark # type: ignore
+ from ._models import BookmarkList # type: ignore
+ from ._models import ClientInfo # type: ignore
+ from ._models import DataConnector # type: ignore
+ from ._models import DataConnectorDataTypeCommon # type: ignore
+ from ._models import DataConnectorList # type: ignore
+ from ._models import DataConnectorTenantId # type: ignore
+ from ._models import DataConnectorWithAlertsProperties # type: ignore
+ from ._models import ErrorAdditionalInfo # type: ignore
+ from ._models import ErrorResponse # type: ignore
+ from ._models import FusionAlertRule # type: ignore
+ from ._models import FusionAlertRuleTemplate # type: ignore
+ from ._models import Incident # type: ignore
+ from ._models import IncidentAdditionalData # type: ignore
+ from ._models import IncidentComment # type: ignore
+ from ._models import IncidentCommentList # type: ignore
+ from ._models import IncidentInfo # type: ignore
+ from ._models import IncidentLabel # type: ignore
+ from ._models import IncidentList # type: ignore
+ from ._models import IncidentOwnerInfo # type: ignore
+ from ._models import MCASDataConnector # type: ignore
+ from ._models import MCASDataConnectorDataTypes # type: ignore
+ from ._models import MDATPDataConnector # type: ignore
+ from ._models import MicrosoftSecurityIncidentCreationAlertRule # type: ignore
+ from ._models import MicrosoftSecurityIncidentCreationAlertRuleCommonProperties # type: ignore
+ from ._models import MicrosoftSecurityIncidentCreationAlertRuleProperties # type: ignore
+ from ._models import MicrosoftSecurityIncidentCreationAlertRuleTemplate # type: ignore
+ from ._models import OfficeConsent # type: ignore
+ from ._models import OfficeConsentList # type: ignore
+ from ._models import OfficeDataConnector # type: ignore
+ from ._models import OfficeDataConnectorDataTypesExchange # type: ignore
+ from ._models import OfficeDataConnectorDataTypesSharePoint # type: ignore
+ from ._models import Operation # type: ignore
+ from ._models import OperationDisplay # type: ignore
+ from ._models import OperationsList # type: ignore
+ from ._models import Resource # type: ignore
+ from ._models import ResourceWithEtag # type: ignore
+ from ._models import ScheduledAlertRule # type: ignore
+ from ._models import ScheduledAlertRuleCommonProperties # type: ignore
+ from ._models import ScheduledAlertRuleProperties # type: ignore
+ from ._models import ScheduledAlertRuleTemplate # type: ignore
+ from ._models import Settings # type: ignore
+ from ._models import TIDataConnector # type: ignore
+ from ._models import TIDataConnectorDataTypesIndicators # type: ignore
+ from ._models import ThreatIntelligence # type: ignore
+ from ._models import ToggleSettings # type: ignore
+ from ._models import UebaSettings # type: ignore
+
+from ._security_insights_enums import (
+ AlertRuleKind,
+ AlertSeverity,
+ AttackTactic,
+ CaseSeverity,
+ DataConnectorKind,
+ DataTypeState,
+ IncidentClassification,
+ IncidentClassificationReason,
+ IncidentLabelType,
+ IncidentSeverity,
+ IncidentStatus,
+ LicenseStatus,
+ MicrosoftSecurityProductName,
+ SettingKind,
+ StatusInMCAS,
+ TemplateStatus,
+ TriggerOperator,
+)
+
+__all__ = [
+ 'AADDataConnector',
+ 'AATPDataConnector',
+ 'ASCDataConnector',
+ 'ASCDataConnectorProperties',
+ 'ActionPropertiesBase',
+ 'ActionRequest',
+ 'ActionRequestProperties',
+ 'ActionResponse',
+ 'ActionResponseProperties',
+ 'ActionsList',
+ 'AlertRule',
+ 'AlertRuleTemplate',
+ 'AlertRuleTemplateDataSource',
+ 'AlertRuleTemplatesList',
+ 'AlertRulesList',
+ 'AlertsDataTypeOfDataConnector',
+ 'AwsCloudTrailDataConnector',
+ 'AwsCloudTrailDataConnectorDataTypesLogs',
+ 'Bookmark',
+ 'BookmarkList',
+ 'ClientInfo',
+ 'DataConnector',
+ 'DataConnectorDataTypeCommon',
+ 'DataConnectorList',
+ 'DataConnectorTenantId',
+ 'DataConnectorWithAlertsProperties',
+ 'ErrorAdditionalInfo',
+ 'ErrorResponse',
+ 'FusionAlertRule',
+ 'FusionAlertRuleTemplate',
+ 'Incident',
+ 'IncidentAdditionalData',
+ 'IncidentComment',
+ 'IncidentCommentList',
+ 'IncidentInfo',
+ 'IncidentLabel',
+ 'IncidentList',
+ 'IncidentOwnerInfo',
+ 'MCASDataConnector',
+ 'MCASDataConnectorDataTypes',
+ 'MDATPDataConnector',
+ 'MicrosoftSecurityIncidentCreationAlertRule',
+ 'MicrosoftSecurityIncidentCreationAlertRuleCommonProperties',
+ 'MicrosoftSecurityIncidentCreationAlertRuleProperties',
+ 'MicrosoftSecurityIncidentCreationAlertRuleTemplate',
+ 'OfficeConsent',
+ 'OfficeConsentList',
+ 'OfficeDataConnector',
+ 'OfficeDataConnectorDataTypesExchange',
+ 'OfficeDataConnectorDataTypesSharePoint',
+ 'Operation',
+ 'OperationDisplay',
+ 'OperationsList',
+ 'Resource',
+ 'ResourceWithEtag',
+ 'ScheduledAlertRule',
+ 'ScheduledAlertRuleCommonProperties',
+ 'ScheduledAlertRuleProperties',
+ 'ScheduledAlertRuleTemplate',
+ 'Settings',
+ 'TIDataConnector',
+ 'TIDataConnectorDataTypesIndicators',
+ 'ThreatIntelligence',
+ 'ToggleSettings',
+ 'UebaSettings',
+ 'AlertRuleKind',
+ 'AlertSeverity',
+ 'AttackTactic',
+ 'CaseSeverity',
+ 'DataConnectorKind',
+ 'DataTypeState',
+ 'IncidentClassification',
+ 'IncidentClassificationReason',
+ 'IncidentLabelType',
+ 'IncidentSeverity',
+ 'IncidentStatus',
+ 'LicenseStatus',
+ 'MicrosoftSecurityProductName',
+ 'SettingKind',
+ 'StatusInMCAS',
+ 'TemplateStatus',
+ 'TriggerOperator',
+]
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models.py
new file mode 100644
index 00000000000..53b00b59bc5
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models.py
@@ -0,0 +1,2922 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+import msrest.serialization
+
+
+class ResourceWithEtag(msrest.serialization.Model):
+ """An azure resource object with an Etag property.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ResourceWithEtag, self).__init__(**kwargs)
+ self.id = None
+ self.name = None
+ self.type = None
+ self.etag = kwargs.get('etag', None)
+
+
+class DataConnector(ResourceWithEtag):
+ """Data connector.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: AwsCloudTrailDataConnector, AADDataConnector, AATPDataConnector, ASCDataConnector, MCASDataConnector, MDATPDataConnector, OfficeDataConnector, TIDataConnector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'AmazonWebServicesCloudTrail': 'AwsCloudTrailDataConnector', 'AzureActiveDirectory': 'AADDataConnector', 'AzureAdvancedThreatProtection': 'AATPDataConnector', 'AzureSecurityCenter': 'ASCDataConnector', 'MicrosoftCloudAppSecurity': 'MCASDataConnector', 'MicrosoftDefenderAdvancedThreatProtection': 'MDATPDataConnector', 'Office365': 'OfficeDataConnector', 'ThreatIntelligence': 'TIDataConnector'}
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(DataConnector, self).__init__(**kwargs)
+ self.kind = 'DataConnector' # type: str
+
+
+class AADDataConnector(DataConnector):
+ """Represents AAD (Azure Active Directory) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AADDataConnector, self).__init__(**kwargs)
+ self.kind = 'AzureActiveDirectory' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state = kwargs.get('state', None)
+
+
+class AATPDataConnector(DataConnector):
+ """Represents AATP (Azure Advanced Threat Protection) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AATPDataConnector, self).__init__(**kwargs)
+ self.kind = 'AzureAdvancedThreatProtection' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state = kwargs.get('state', None)
+
+
+class ActionPropertiesBase(msrest.serialization.Model):
+ """Action property bag base.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionPropertiesBase, self).__init__(**kwargs)
+ self.logic_app_resource_id = kwargs['logic_app_resource_id']
+
+
+class ActionRequest(ResourceWithEtag):
+ """Action for alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'logic_app_resource_id': {'key': 'properties.logicAppResourceId', 'type': 'str'},
+ 'trigger_uri': {'key': 'properties.triggerUri', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionRequest, self).__init__(**kwargs)
+ self.logic_app_resource_id = kwargs.get('logic_app_resource_id', None)
+ self.trigger_uri = kwargs.get('trigger_uri', None)
+
+
+class ActionRequestProperties(ActionPropertiesBase):
+ """Action property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ 'trigger_uri': {'key': 'triggerUri', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionRequestProperties, self).__init__(**kwargs)
+ self.trigger_uri = kwargs.get('trigger_uri', None)
+
+
+class Resource(msrest.serialization.Model):
+ """An azure resource object.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Resource, self).__init__(**kwargs)
+ self.id = None
+ self.name = None
+ self.type = None
+
+
+class ActionResponse(Resource):
+ """Action for alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the action.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param workflow_id: The name of the logic app's workflow.
+ :type workflow_id: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'logic_app_resource_id': {'key': 'properties.logicAppResourceId', 'type': 'str'},
+ 'workflow_id': {'key': 'properties.workflowId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionResponse, self).__init__(**kwargs)
+ self.etag = kwargs.get('etag', None)
+ self.logic_app_resource_id = kwargs.get('logic_app_resource_id', None)
+ self.workflow_id = kwargs.get('workflow_id', None)
+
+
+class ActionResponseProperties(ActionPropertiesBase):
+ """Action property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param workflow_id: The name of the logic app's workflow.
+ :type workflow_id: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ 'workflow_id': {'key': 'workflowId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionResponseProperties, self).__init__(**kwargs)
+ self.workflow_id = kwargs.get('workflow_id', None)
+
+
+class ActionsList(msrest.serialization.Model):
+ """List all the actions.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of actions.
+ :vartype next_link: str
+ :param value: Required. Array of actions.
+ :type value: list[~security_insights.models.ActionResponse]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[ActionResponse]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ActionsList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class AlertRule(ResourceWithEtag):
+ """Alert rule.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: FusionAlertRule, MicrosoftSecurityIncidentCreationAlertRule, ScheduledAlertRule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'Fusion': 'FusionAlertRule', 'MicrosoftSecurityIncidentCreation': 'MicrosoftSecurityIncidentCreationAlertRule', 'Scheduled': 'ScheduledAlertRule'}
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRule, self).__init__(**kwargs)
+ self.kind = 'AlertRule' # type: str
+
+
+class AlertRulesList(msrest.serialization.Model):
+ """List all the alert rules.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of alert rules.
+ :vartype next_link: str
+ :param value: Required. Array of alert rules.
+ :type value: list[~security_insights.models.AlertRule]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[AlertRule]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRulesList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class AlertRuleTemplate(Resource):
+ """Alert rule template.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: FusionAlertRuleTemplate, MicrosoftSecurityIncidentCreationAlertRuleTemplate, ScheduledAlertRuleTemplate.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'Fusion': 'FusionAlertRuleTemplate', 'MicrosoftSecurityIncidentCreation': 'MicrosoftSecurityIncidentCreationAlertRuleTemplate', 'Scheduled': 'ScheduledAlertRuleTemplate'}
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'AlertRuleTemplate' # type: str
+
+
+class AlertRuleTemplateDataSource(msrest.serialization.Model):
+ """alert rule template data sources.
+
+ :param connector_id: The connector id that provides the following data types.
+ :type connector_id: str
+ :param data_types: The data types used by the alert rule template.
+ :type data_types: list[str]
+ """
+
+ _attribute_map = {
+ 'connector_id': {'key': 'connectorId', 'type': 'str'},
+ 'data_types': {'key': 'dataTypes', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRuleTemplateDataSource, self).__init__(**kwargs)
+ self.connector_id = kwargs.get('connector_id', None)
+ self.data_types = kwargs.get('data_types', None)
+
+
+class AlertRuleTemplatesList(msrest.serialization.Model):
+ """List all the alert rule templates.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of alert rule templates.
+ :vartype next_link: str
+ :param value: Required. Array of alert rule templates.
+ :type value: list[~security_insights.models.AlertRuleTemplate]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[AlertRuleTemplate]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRuleTemplatesList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class AlertsDataTypeOfDataConnector(msrest.serialization.Model):
+ """Alerts data type for data connectors.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertsDataTypeOfDataConnector, self).__init__(**kwargs)
+ self.state = kwargs.get('state', None)
+
+
+class ASCDataConnector(DataConnector):
+ """Represents ASC (Azure Security Center) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param subscription_id: The subscription id to connect to, and get the data from.
+ :type subscription_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'subscription_id': {'key': 'properties.subscriptionId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ASCDataConnector, self).__init__(**kwargs)
+ self.kind = 'AzureSecurityCenter' # type: str
+ self.subscription_id = kwargs.get('subscription_id', None)
+ self.state = kwargs.get('state', None)
+
+
+class DataConnectorWithAlertsProperties(msrest.serialization.Model):
+ """Data connector properties.
+
+ :param data_types: The available data types for the connector.
+ :type data_types: ~security_insights.models.AlertsDataTypeOfDataConnector
+ """
+
+ _attribute_map = {
+ 'data_types': {'key': 'dataTypes', 'type': 'AlertsDataTypeOfDataConnector'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(DataConnectorWithAlertsProperties, self).__init__(**kwargs)
+ self.data_types = kwargs.get('data_types', None)
+
+
+class ASCDataConnectorProperties(DataConnectorWithAlertsProperties):
+ """ASC (Azure Security Center) data connector properties.
+
+ :param data_types: The available data types for the connector.
+ :type data_types: ~security_insights.models.AlertsDataTypeOfDataConnector
+ :param subscription_id: The subscription id to connect to, and get the data from.
+ :type subscription_id: str
+ """
+
+ _attribute_map = {
+ 'data_types': {'key': 'dataTypes', 'type': 'AlertsDataTypeOfDataConnector'},
+ 'subscription_id': {'key': 'subscriptionId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ASCDataConnectorProperties, self).__init__(**kwargs)
+ self.subscription_id = kwargs.get('subscription_id', None)
+
+
+class AwsCloudTrailDataConnector(DataConnector):
+ """Represents Amazon Web Services CloudTrail data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param aws_role_arn: The Aws Role Arn (with CloudTrailReadOnly policy) that is used to access
+ the Aws account.
+ :type aws_role_arn: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'aws_role_arn': {'key': 'properties.awsRoleArn', 'type': 'str'},
+ 'state': {'key': 'dataTypes.logs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AwsCloudTrailDataConnector, self).__init__(**kwargs)
+ self.kind = 'AmazonWebServicesCloudTrail' # type: str
+ self.aws_role_arn = kwargs.get('aws_role_arn', None)
+ self.state = kwargs.get('state', None)
+
+
+class DataConnectorDataTypeCommon(msrest.serialization.Model):
+ """Common field for data type in data connectors.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(DataConnectorDataTypeCommon, self).__init__(**kwargs)
+ self.state = kwargs.get('state', None)
+
+
+class AwsCloudTrailDataConnectorDataTypesLogs(DataConnectorDataTypeCommon):
+ """Logs data type.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AwsCloudTrailDataConnectorDataTypesLogs, self).__init__(**kwargs)
+
+
+class Bookmark(ResourceWithEtag):
+ """Represents a bookmark in Azure Security Insights.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param created: The time the bookmark was created.
+ :type created: ~datetime.datetime
+ :param display_name: The display name of the bookmark.
+ :type display_name: str
+ :param labels: List of labels relevant to this bookmark.
+ :type labels: list[str]
+ :param notes: The notes of the bookmark.
+ :type notes: str
+ :param query: The query of the bookmark.
+ :type query: str
+ :param query_result: The query result of the bookmark.
+ :type query_result: str
+ :param updated: The last time the bookmark was updated.
+ :type updated: ~datetime.datetime
+ :param incident_info: Describes an incident that relates to bookmark.
+ :type incident_info: ~security_insights.models.IncidentInfo
+ :ivar email_updated_by_email: The email of the user.
+ :vartype email_updated_by_email: str
+ :ivar name_updated_by_name: The name of the user.
+ :vartype name_updated_by_name: str
+ :param object_id_updated_by_object_id: The object id of the user.
+ :type object_id_updated_by_object_id: str
+ :ivar email_created_by_email: The email of the user.
+ :vartype email_created_by_email: str
+ :ivar name_created_by_name: The name of the user.
+ :vartype name_created_by_name: str
+ :param object_id_created_by_object_id: The object id of the user.
+ :type object_id_created_by_object_id: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'email_updated_by_email': {'readonly': True},
+ 'name_updated_by_name': {'readonly': True},
+ 'email_created_by_email': {'readonly': True},
+ 'name_created_by_name': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'created': {'key': 'properties.created', 'type': 'iso-8601'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'labels': {'key': 'properties.labels', 'type': '[str]'},
+ 'notes': {'key': 'properties.notes', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_result': {'key': 'properties.queryResult', 'type': 'str'},
+ 'updated': {'key': 'properties.updated', 'type': 'iso-8601'},
+ 'incident_info': {'key': 'properties.incidentInfo', 'type': 'IncidentInfo'},
+ 'email_updated_by_email': {'key': 'updatedBy.email', 'type': 'str'},
+ 'name_updated_by_name': {'key': 'updatedBy.name', 'type': 'str'},
+ 'object_id_updated_by_object_id': {'key': 'updatedBy.objectId', 'type': 'str'},
+ 'email_created_by_email': {'key': 'createdBy.email', 'type': 'str'},
+ 'name_created_by_name': {'key': 'createdBy.name', 'type': 'str'},
+ 'object_id_created_by_object_id': {'key': 'createdBy.objectId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Bookmark, self).__init__(**kwargs)
+ self.created = kwargs.get('created', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.labels = kwargs.get('labels', None)
+ self.notes = kwargs.get('notes', None)
+ self.query = kwargs.get('query', None)
+ self.query_result = kwargs.get('query_result', None)
+ self.updated = kwargs.get('updated', None)
+ self.incident_info = kwargs.get('incident_info', None)
+ self.email_updated_by_email = None
+ self.name_updated_by_name = None
+ self.object_id_updated_by_object_id = kwargs.get('object_id_updated_by_object_id', None)
+ self.email_created_by_email = None
+ self.name_created_by_name = None
+ self.object_id_created_by_object_id = kwargs.get('object_id_created_by_object_id', None)
+
+
+class BookmarkList(msrest.serialization.Model):
+ """List all the bookmarks.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of cases.
+ :vartype next_link: str
+ :param value: Required. Array of bookmarks.
+ :type value: list[~security_insights.models.Bookmark]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Bookmark]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(BookmarkList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class ClientInfo(msrest.serialization.Model):
+ """Information on the client (user or application) that made some action.
+
+ :param email: The email of the client.
+ :type email: str
+ :param name: The name of the client.
+ :type name: str
+ :param object_id: The object id of the client.
+ :type object_id: str
+ :param user_principal_name: The user principal name of the client.
+ :type user_principal_name: str
+ """
+
+ _attribute_map = {
+ 'email': {'key': 'email', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'object_id': {'key': 'objectId', 'type': 'str'},
+ 'user_principal_name': {'key': 'userPrincipalName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ClientInfo, self).__init__(**kwargs)
+ self.email = kwargs.get('email', None)
+ self.name = kwargs.get('name', None)
+ self.object_id = kwargs.get('object_id', None)
+ self.user_principal_name = kwargs.get('user_principal_name', None)
+
+
+class DataConnectorList(msrest.serialization.Model):
+ """List all the data connectors.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of data connectors.
+ :vartype next_link: str
+ :param value: Required. Array of data connectors.
+ :type value: list[~security_insights.models.DataConnector]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[DataConnector]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(DataConnectorList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class DataConnectorTenantId(msrest.serialization.Model):
+ """Properties data connector on tenant level.
+
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ """
+
+ _attribute_map = {
+ 'tenant_id': {'key': 'tenantId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(DataConnectorTenantId, self).__init__(**kwargs)
+ self.tenant_id = kwargs.get('tenant_id', None)
+
+
+class ErrorAdditionalInfo(msrest.serialization.Model):
+ """The resource management error additional info.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar type: The additional info type.
+ :vartype type: str
+ :ivar info: The additional info.
+ :vartype info: object
+ """
+
+ _validation = {
+ 'type': {'readonly': True},
+ 'info': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'type': {'key': 'type', 'type': 'str'},
+ 'info': {'key': 'info', 'type': 'object'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ErrorAdditionalInfo, self).__init__(**kwargs)
+ self.type = None
+ self.info = None
+
+
+class ErrorResponse(msrest.serialization.Model):
+ """Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.).
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar code: The error code.
+ :vartype code: str
+ :ivar message: The error message.
+ :vartype message: str
+ :ivar target: The error target.
+ :vartype target: str
+ :ivar details: The error details.
+ :vartype details: list[~security_insights.models.ErrorResponse]
+ :ivar additional_info: The error additional info.
+ :vartype additional_info: list[~security_insights.models.ErrorAdditionalInfo]
+ """
+
+ _validation = {
+ 'code': {'readonly': True},
+ 'message': {'readonly': True},
+ 'target': {'readonly': True},
+ 'details': {'readonly': True},
+ 'additional_info': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'code': {'key': 'code', 'type': 'str'},
+ 'message': {'key': 'message', 'type': 'str'},
+ 'target': {'key': 'target', 'type': 'str'},
+ 'details': {'key': 'details', 'type': '[ErrorResponse]'},
+ 'additional_info': {'key': 'additionalInfo', 'type': '[ErrorAdditionalInfo]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ErrorResponse, self).__init__(**kwargs)
+ self.code = None
+ self.message = None
+ self.target = None
+ self.details = None
+ self.additional_info = None
+
+
+class FusionAlertRule(AlertRule):
+ """Represents Fusion alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :ivar description: The description of the alert rule.
+ :vartype description: str
+ :ivar display_name: The display name for alerts created by this alert rule.
+ :vartype display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :ivar severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :vartype severity: str or ~security_insights.models.AlertSeverity
+ :ivar tactics: The tactics of the alert rule.
+ :vartype tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'description': {'readonly': True},
+ 'display_name': {'readonly': True},
+ 'last_modified_utc': {'readonly': True},
+ 'severity': {'readonly': True},
+ 'tactics': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(FusionAlertRule, self).__init__(**kwargs)
+ self.kind = 'Fusion' # type: str
+ self.alert_rule_template_name = kwargs.get('alert_rule_template_name', None)
+ self.description = None
+ self.display_name = None
+ self.enabled = kwargs.get('enabled', None)
+ self.last_modified_utc = None
+ self.severity = None
+ self.tactics = None
+
+
+class FusionAlertRuleTemplate(AlertRuleTemplate):
+ """Represents Fusion alert rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param tactics: The tactics of the alert rule template.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(FusionAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'Fusion' # type: str
+ self.alert_rules_created_by_template_count = kwargs.get('alert_rules_created_by_template_count', None)
+ self.created_date_utc = None
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.required_data_connectors = kwargs.get('required_data_connectors', None)
+ self.status = kwargs.get('status', None)
+ self.severity = kwargs.get('severity', None)
+ self.tactics = kwargs.get('tactics', None)
+
+
+class Incident(ResourceWithEtag):
+ """Represents an incident in Azure Security Insights.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :ivar additional_data: Additional data on the incident.
+ :vartype additional_data: ~security_insights.models.IncidentAdditionalData
+ :param classification: The reason the incident was closed. Possible values include:
+ "Undetermined", "TruePositive", "BenignPositive", "FalsePositive".
+ :type classification: str or ~security_insights.models.IncidentClassification
+ :param classification_comment: Describes the reason the incident was closed.
+ :type classification_comment: str
+ :param classification_reason: The classification reason the incident was closed with. Possible
+ values include: "SuspiciousActivity", "SuspiciousButExpected", "IncorrectAlertLogic",
+ "InaccurateData".
+ :type classification_reason: str or ~security_insights.models.IncidentClassificationReason
+ :ivar created_time_utc: The time the incident was created.
+ :vartype created_time_utc: ~datetime.datetime
+ :param description: The description of the incident.
+ :type description: str
+ :param first_activity_time_utc: The time of the first activity in the incident.
+ :type first_activity_time_utc: ~datetime.datetime
+ :ivar incident_url: The deep-link url to the incident in Azure portal.
+ :vartype incident_url: str
+ :ivar incident_number: A sequential number.
+ :vartype incident_number: int
+ :param labels: List of labels relevant to this incident.
+ :type labels: list[~security_insights.models.IncidentLabel]
+ :param last_activity_time_utc: The time of the last activity in the incident.
+ :type last_activity_time_utc: ~datetime.datetime
+ :ivar last_modified_time_utc: The last time the incident was updated.
+ :vartype last_modified_time_utc: ~datetime.datetime
+ :param owner: Describes a user that the incident is assigned to.
+ :type owner: ~security_insights.models.IncidentOwnerInfo
+ :ivar related_analytic_rule_ids: List of resource ids of Analytic rules related to the
+ incident.
+ :vartype related_analytic_rule_ids: list[str]
+ :param severity: The severity of the incident. Possible values include: "High", "Medium",
+ "Low", "Informational".
+ :type severity: str or ~security_insights.models.IncidentSeverity
+ :param status: The status of the incident. Possible values include: "New", "Active", "Closed".
+ :type status: str or ~security_insights.models.IncidentStatus
+ :param title: The title of the incident.
+ :type title: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'additional_data': {'readonly': True},
+ 'created_time_utc': {'readonly': True},
+ 'incident_url': {'readonly': True},
+ 'incident_number': {'readonly': True},
+ 'last_modified_time_utc': {'readonly': True},
+ 'related_analytic_rule_ids': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'additional_data': {'key': 'properties.additionalData', 'type': 'IncidentAdditionalData'},
+ 'classification': {'key': 'properties.classification', 'type': 'str'},
+ 'classification_comment': {'key': 'properties.classificationComment', 'type': 'str'},
+ 'classification_reason': {'key': 'properties.classificationReason', 'type': 'str'},
+ 'created_time_utc': {'key': 'properties.createdTimeUtc', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'first_activity_time_utc': {'key': 'properties.firstActivityTimeUtc', 'type': 'iso-8601'},
+ 'incident_url': {'key': 'properties.incidentUrl', 'type': 'str'},
+ 'incident_number': {'key': 'properties.incidentNumber', 'type': 'int'},
+ 'labels': {'key': 'properties.labels', 'type': '[IncidentLabel]'},
+ 'last_activity_time_utc': {'key': 'properties.lastActivityTimeUtc', 'type': 'iso-8601'},
+ 'last_modified_time_utc': {'key': 'properties.lastModifiedTimeUtc', 'type': 'iso-8601'},
+ 'owner': {'key': 'properties.owner', 'type': 'IncidentOwnerInfo'},
+ 'related_analytic_rule_ids': {'key': 'properties.relatedAnalyticRuleIds', 'type': '[str]'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'title': {'key': 'properties.title', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Incident, self).__init__(**kwargs)
+ self.additional_data = None
+ self.classification = kwargs.get('classification', None)
+ self.classification_comment = kwargs.get('classification_comment', None)
+ self.classification_reason = kwargs.get('classification_reason', None)
+ self.created_time_utc = None
+ self.description = kwargs.get('description', None)
+ self.first_activity_time_utc = kwargs.get('first_activity_time_utc', None)
+ self.incident_url = None
+ self.incident_number = None
+ self.labels = kwargs.get('labels', None)
+ self.last_activity_time_utc = kwargs.get('last_activity_time_utc', None)
+ self.last_modified_time_utc = None
+ self.owner = kwargs.get('owner', None)
+ self.related_analytic_rule_ids = None
+ self.severity = kwargs.get('severity', None)
+ self.status = kwargs.get('status', None)
+ self.title = kwargs.get('title', None)
+
+
+class IncidentAdditionalData(msrest.serialization.Model):
+ """Incident additional data property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar alerts_count: The number of alerts in the incident.
+ :vartype alerts_count: int
+ :ivar bookmarks_count: The number of bookmarks in the incident.
+ :vartype bookmarks_count: int
+ :ivar comments_count: The number of comments in the incident.
+ :vartype comments_count: int
+ :ivar alert_product_names: List of product names of alerts in the incident.
+ :vartype alert_product_names: list[str]
+ :ivar tactics: The tactics associated with incident.
+ :vartype tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'alerts_count': {'readonly': True},
+ 'bookmarks_count': {'readonly': True},
+ 'comments_count': {'readonly': True},
+ 'alert_product_names': {'readonly': True},
+ 'tactics': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'alerts_count': {'key': 'alertsCount', 'type': 'int'},
+ 'bookmarks_count': {'key': 'bookmarksCount', 'type': 'int'},
+ 'comments_count': {'key': 'commentsCount', 'type': 'int'},
+ 'alert_product_names': {'key': 'alertProductNames', 'type': '[str]'},
+ 'tactics': {'key': 'tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentAdditionalData, self).__init__(**kwargs)
+ self.alerts_count = None
+ self.bookmarks_count = None
+ self.comments_count = None
+ self.alert_product_names = None
+ self.tactics = None
+
+
+class IncidentComment(Resource):
+ """Represents an incident comment.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :ivar created_time_utc: The time the comment was created.
+ :vartype created_time_utc: ~datetime.datetime
+ :param message: The comment message.
+ :type message: str
+ :ivar author: Describes the client that created the comment.
+ :vartype author: ~security_insights.models.ClientInfo
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'created_time_utc': {'readonly': True},
+ 'author': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'created_time_utc': {'key': 'properties.createdTimeUtc', 'type': 'iso-8601'},
+ 'message': {'key': 'properties.message', 'type': 'str'},
+ 'author': {'key': 'properties.author', 'type': 'ClientInfo'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentComment, self).__init__(**kwargs)
+ self.created_time_utc = None
+ self.message = kwargs.get('message', None)
+ self.author = None
+
+
+class IncidentCommentList(msrest.serialization.Model):
+ """List of incident comments.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of comments.
+ :vartype next_link: str
+ :param value: Required. Array of comments.
+ :type value: list[~security_insights.models.IncidentComment]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[IncidentComment]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentCommentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class IncidentInfo(msrest.serialization.Model):
+ """Describes related incident information for the bookmark.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param incident_id: Required. Incident Id.
+ :type incident_id: str
+ :param severity: Required. The severity of the incident. Possible values include: "Critical",
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.CaseSeverity
+ :param title: Required. The title of the incident.
+ :type title: str
+ :param relation_name: Required. Relation Name.
+ :type relation_name: str
+ """
+
+ _validation = {
+ 'incident_id': {'required': True},
+ 'severity': {'required': True},
+ 'title': {'required': True},
+ 'relation_name': {'required': True},
+ }
+
+ _attribute_map = {
+ 'incident_id': {'key': 'incidentId', 'type': 'str'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'title': {'key': 'title', 'type': 'str'},
+ 'relation_name': {'key': 'relationName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentInfo, self).__init__(**kwargs)
+ self.incident_id = kwargs['incident_id']
+ self.severity = kwargs['severity']
+ self.title = kwargs['title']
+ self.relation_name = kwargs['relation_name']
+
+
+class IncidentLabel(msrest.serialization.Model):
+ """Represents an incident label.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param label_name: Required. The name of the label.
+ :type label_name: str
+ :ivar label_type: The type of the label. Possible values include: "User", "System".
+ :vartype label_type: str or ~security_insights.models.IncidentLabelType
+ """
+
+ _validation = {
+ 'label_name': {'required': True},
+ 'label_type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'label_name': {'key': 'labelName', 'type': 'str'},
+ 'label_type': {'key': 'labelType', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentLabel, self).__init__(**kwargs)
+ self.label_name = kwargs['label_name']
+ self.label_type = None
+
+
+class IncidentList(msrest.serialization.Model):
+ """List all the incidents.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of incidents.
+ :vartype next_link: str
+ :param value: Required. Array of incidents.
+ :type value: list[~security_insights.models.Incident]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Incident]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class IncidentOwnerInfo(msrest.serialization.Model):
+ """Information on the user an incident is assigned to.
+
+ :param email: The email of the user the incident is assigned to.
+ :type email: str
+ :param assigned_to: The name of the user the incident is assigned to.
+ :type assigned_to: str
+ :param object_id: The object id of the user the incident is assigned to.
+ :type object_id: str
+ :param user_principal_name: The user principal name of the user the incident is assigned to.
+ :type user_principal_name: str
+ """
+
+ _attribute_map = {
+ 'email': {'key': 'email', 'type': 'str'},
+ 'assigned_to': {'key': 'assignedTo', 'type': 'str'},
+ 'object_id': {'key': 'objectId', 'type': 'str'},
+ 'user_principal_name': {'key': 'userPrincipalName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentOwnerInfo, self).__init__(**kwargs)
+ self.email = kwargs.get('email', None)
+ self.assigned_to = kwargs.get('assigned_to', None)
+ self.object_id = kwargs.get('object_id', None)
+ self.user_principal_name = kwargs.get('user_principal_name', None)
+
+
+class MCASDataConnector(DataConnector):
+ """Represents MCAS (Microsoft Cloud App Security) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state_data_types_alerts_state: Describe whether this data type connection is enabled or
+ not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_alerts_state: str or ~security_insights.models.DataTypeState
+ :param state_data_types_discovery_logs_state: Describe whether this data type connection is
+ enabled or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_discovery_logs_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state_data_types_alerts_state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ 'state_data_types_discovery_logs_state': {'key': 'dataTypes.discoveryLogs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MCASDataConnector, self).__init__(**kwargs)
+ self.kind = 'MicrosoftCloudAppSecurity' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state_data_types_alerts_state = kwargs.get('state_data_types_alerts_state', None)
+ self.state_data_types_discovery_logs_state = kwargs.get('state_data_types_discovery_logs_state', None)
+
+
+class MCASDataConnectorDataTypes(AlertsDataTypeOfDataConnector):
+ """The available data types for MCAS (Microsoft Cloud App Security) data connector.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ :param state_discovery_logs_state: Describe whether this data type connection is enabled or
+ not. Possible values include: "Enabled", "Disabled".
+ :type state_discovery_logs_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'alerts.state', 'type': 'str'},
+ 'state_discovery_logs_state': {'key': 'discoveryLogs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MCASDataConnectorDataTypes, self).__init__(**kwargs)
+ self.state_discovery_logs_state = kwargs.get('state_discovery_logs_state', None)
+
+
+class MDATPDataConnector(DataConnector):
+ """Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MDATPDataConnector, self).__init__(**kwargs)
+ self.kind = 'MicrosoftDefenderAdvancedThreatProtection' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state = kwargs.get('state', None)
+
+
+class MicrosoftSecurityIncidentCreationAlertRule(AlertRule):
+ """Represents MicrosoftSecurityIncidentCreation rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: The alerts' productName on which the cases will be generated. Possible
+ values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure Advanced Threat
+ Protection", "Azure Active Directory Identity Protection", "Azure Security Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'display_names_filter': {'key': 'properties.displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'properties.displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'properties.productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'properties.severitiesFilter', 'type': '[str]'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRule, self).__init__(**kwargs)
+ self.kind = 'MicrosoftSecurityIncidentCreation' # type: str
+ self.display_names_filter = kwargs.get('display_names_filter', None)
+ self.display_names_exclude_filter = kwargs.get('display_names_exclude_filter', None)
+ self.product_filter = kwargs.get('product_filter', None)
+ self.severities_filter = kwargs.get('severities_filter', None)
+ self.alert_rule_template_name = kwargs.get('alert_rule_template_name', None)
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.enabled = kwargs.get('enabled', None)
+ self.last_modified_utc = None
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleCommonProperties(msrest.serialization.Model):
+ """MicrosoftSecurityIncidentCreation rule common property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: Required. The alerts' productName on which the cases will be generated.
+ Possible values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure
+ Advanced Threat Protection", "Azure Active Directory Identity Protection", "Azure Security
+ Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ """
+
+ _validation = {
+ 'product_filter': {'required': True},
+ }
+
+ _attribute_map = {
+ 'display_names_filter': {'key': 'displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'severitiesFilter', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleCommonProperties, self).__init__(**kwargs)
+ self.display_names_filter = kwargs.get('display_names_filter', None)
+ self.display_names_exclude_filter = kwargs.get('display_names_exclude_filter', None)
+ self.product_filter = kwargs['product_filter']
+ self.severities_filter = kwargs.get('severities_filter', None)
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleProperties(MicrosoftSecurityIncidentCreationAlertRuleCommonProperties):
+ """MicrosoftSecurityIncidentCreation rule property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: Required. The alerts' productName on which the cases will be generated.
+ Possible values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure
+ Advanced Threat Protection", "Azure Active Directory Identity Protection", "Azure Security
+ Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: Required. The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Required. Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ """
+
+ _validation = {
+ 'product_filter': {'required': True},
+ 'display_name': {'required': True},
+ 'enabled': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'display_names_filter': {'key': 'displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'severitiesFilter', 'type': '[str]'},
+ 'alert_rule_template_name': {'key': 'alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'description', 'type': 'str'},
+ 'display_name': {'key': 'displayName', 'type': 'str'},
+ 'enabled': {'key': 'enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'lastModifiedUtc', 'type': 'iso-8601'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleProperties, self).__init__(**kwargs)
+ self.alert_rule_template_name = kwargs.get('alert_rule_template_name', None)
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs['display_name']
+ self.enabled = kwargs['enabled']
+ self.last_modified_utc = None
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleTemplate(AlertRuleTemplate):
+ """Represents MicrosoftSecurityIncidentCreation rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: The alerts' productName on which the cases will be generated. Possible
+ values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure Advanced Threat
+ Protection", "Azure Active Directory Identity Protection", "Azure Security Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'display_names_filter': {'key': 'properties.displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'properties.displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'properties.productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'properties.severitiesFilter', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'MicrosoftSecurityIncidentCreation' # type: str
+ self.alert_rules_created_by_template_count = kwargs.get('alert_rules_created_by_template_count', None)
+ self.created_date_utc = None
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.required_data_connectors = kwargs.get('required_data_connectors', None)
+ self.status = kwargs.get('status', None)
+ self.display_names_filter = kwargs.get('display_names_filter', None)
+ self.display_names_exclude_filter = kwargs.get('display_names_exclude_filter', None)
+ self.product_filter = kwargs.get('product_filter', None)
+ self.severities_filter = kwargs.get('severities_filter', None)
+
+
+class OfficeConsent(Resource):
+ """Consent for Office365 tenant that already made.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param tenant_id: The tenantId of the Office365 with the consent.
+ :type tenant_id: str
+ :ivar tenant_name: The tenant name of the Office365 with the consent.
+ :vartype tenant_name: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'tenant_name': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'tenant_name': {'key': 'properties.tenantName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OfficeConsent, self).__init__(**kwargs)
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.tenant_name = None
+
+
+class OfficeConsentList(msrest.serialization.Model):
+ """List of all the office365 consents.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of office consents.
+ :vartype next_link: str
+ :param value: Required. Array of the consents.
+ :type value: list[~security_insights.models.OfficeConsent]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[OfficeConsent]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OfficeConsentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = kwargs['value']
+
+
+class OfficeDataConnector(DataConnector):
+ """Represents office data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state_data_types_share_point_state: Describe whether this data type connection is
+ enabled or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_share_point_state: str or ~security_insights.models.DataTypeState
+ :param state_data_types_exchange_state: Describe whether this data type connection is enabled
+ or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_exchange_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state_data_types_share_point_state': {'key': 'dataTypes.sharePoint.state', 'type': 'str'},
+ 'state_data_types_exchange_state': {'key': 'dataTypes.exchange.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OfficeDataConnector, self).__init__(**kwargs)
+ self.kind = 'Office365' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state_data_types_share_point_state = kwargs.get('state_data_types_share_point_state', None)
+ self.state_data_types_exchange_state = kwargs.get('state_data_types_exchange_state', None)
+
+
+class OfficeDataConnectorDataTypesExchange(DataConnectorDataTypeCommon):
+ """Exchange data type connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OfficeDataConnectorDataTypesExchange, self).__init__(**kwargs)
+
+
+class OfficeDataConnectorDataTypesSharePoint(DataConnectorDataTypeCommon):
+ """SharePoint data type connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OfficeDataConnectorDataTypesSharePoint, self).__init__(**kwargs)
+
+
+class Operation(msrest.serialization.Model):
+ """Operation provided by provider.
+
+ :param display: Properties of the operation.
+ :type display: ~security_insights.models.OperationDisplay
+ :param name: Name of the operation.
+ :type name: str
+ """
+
+ _attribute_map = {
+ 'display': {'key': 'display', 'type': 'OperationDisplay'},
+ 'name': {'key': 'name', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Operation, self).__init__(**kwargs)
+ self.display = kwargs.get('display', None)
+ self.name = kwargs.get('name', None)
+
+
+class OperationDisplay(msrest.serialization.Model):
+ """Properties of the operation.
+
+ :param description: Description of the operation.
+ :type description: str
+ :param operation: Operation name.
+ :type operation: str
+ :param provider: Provider name.
+ :type provider: str
+ :param resource: Resource name.
+ :type resource: str
+ """
+
+ _attribute_map = {
+ 'description': {'key': 'description', 'type': 'str'},
+ 'operation': {'key': 'operation', 'type': 'str'},
+ 'provider': {'key': 'provider', 'type': 'str'},
+ 'resource': {'key': 'resource', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OperationDisplay, self).__init__(**kwargs)
+ self.description = kwargs.get('description', None)
+ self.operation = kwargs.get('operation', None)
+ self.provider = kwargs.get('provider', None)
+ self.resource = kwargs.get('resource', None)
+
+
+class OperationsList(msrest.serialization.Model):
+ """Lists the operations available in the SecurityInsights RP.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param next_link: URL to fetch the next set of operations.
+ :type next_link: str
+ :param value: Required. Array of operations.
+ :type value: list[~security_insights.models.Operation]
+ """
+
+ _validation = {
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Operation]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(OperationsList, self).__init__(**kwargs)
+ self.next_link = kwargs.get('next_link', None)
+ self.value = kwargs['value']
+
+
+class ScheduledAlertRule(AlertRule):
+ """Represents scheduled alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert rule has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :param suppression_duration: The suppression (in ISO 8601 duration format) to wait since last
+ time this alert rule been triggered.
+ :type suppression_duration: ~datetime.timedelta
+ :param suppression_enabled: Determines whether the suppression for this alert rule is enabled
+ or disabled.
+ :type suppression_enabled: bool
+ :param tactics: The tactics of the alert rule.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_frequency': {'key': 'properties.queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'properties.queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'properties.triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'properties.triggerThreshold', 'type': 'int'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ 'suppression_duration': {'key': 'properties.suppressionDuration', 'type': 'duration'},
+ 'suppression_enabled': {'key': 'properties.suppressionEnabled', 'type': 'bool'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ScheduledAlertRule, self).__init__(**kwargs)
+ self.kind = 'Scheduled' # type: str
+ self.query = kwargs.get('query', None)
+ self.query_frequency = kwargs.get('query_frequency', None)
+ self.query_period = kwargs.get('query_period', None)
+ self.severity = kwargs.get('severity', None)
+ self.trigger_operator = kwargs.get('trigger_operator', None)
+ self.trigger_threshold = kwargs.get('trigger_threshold', None)
+ self.alert_rule_template_name = kwargs.get('alert_rule_template_name', None)
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.enabled = kwargs.get('enabled', None)
+ self.last_modified_utc = None
+ self.suppression_duration = kwargs.get('suppression_duration', None)
+ self.suppression_enabled = kwargs.get('suppression_enabled', None)
+ self.tactics = kwargs.get('tactics', None)
+
+
+class ScheduledAlertRuleCommonProperties(msrest.serialization.Model):
+ """Schedule alert rule template property bag.
+
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ """
+
+ _attribute_map = {
+ 'query': {'key': 'query', 'type': 'str'},
+ 'query_frequency': {'key': 'queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'triggerThreshold', 'type': 'int'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleCommonProperties, self).__init__(**kwargs)
+ self.query = kwargs.get('query', None)
+ self.query_frequency = kwargs.get('query_frequency', None)
+ self.query_period = kwargs.get('query_period', None)
+ self.severity = kwargs.get('severity', None)
+ self.trigger_operator = kwargs.get('trigger_operator', None)
+ self.trigger_threshold = kwargs.get('trigger_threshold', None)
+
+
+class ScheduledAlertRuleProperties(ScheduledAlertRuleCommonProperties):
+ """Scheduled alert rule base property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: Required. The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Required. Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert rule has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :param suppression_duration: Required. The suppression (in ISO 8601 duration format) to wait
+ since last time this alert rule been triggered.
+ :type suppression_duration: ~datetime.timedelta
+ :param suppression_enabled: Required. Determines whether the suppression for this alert rule is
+ enabled or disabled.
+ :type suppression_enabled: bool
+ :param tactics: The tactics of the alert rule.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'display_name': {'required': True},
+ 'enabled': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ 'suppression_duration': {'required': True},
+ 'suppression_enabled': {'required': True},
+ }
+
+ _attribute_map = {
+ 'query': {'key': 'query', 'type': 'str'},
+ 'query_frequency': {'key': 'queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'triggerThreshold', 'type': 'int'},
+ 'alert_rule_template_name': {'key': 'alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'description', 'type': 'str'},
+ 'display_name': {'key': 'displayName', 'type': 'str'},
+ 'enabled': {'key': 'enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'lastModifiedUtc', 'type': 'iso-8601'},
+ 'suppression_duration': {'key': 'suppressionDuration', 'type': 'duration'},
+ 'suppression_enabled': {'key': 'suppressionEnabled', 'type': 'bool'},
+ 'tactics': {'key': 'tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleProperties, self).__init__(**kwargs)
+ self.alert_rule_template_name = kwargs.get('alert_rule_template_name', None)
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs['display_name']
+ self.enabled = kwargs['enabled']
+ self.last_modified_utc = None
+ self.suppression_duration = kwargs['suppression_duration']
+ self.suppression_enabled = kwargs['suppression_enabled']
+ self.tactics = kwargs.get('tactics', None)
+
+
+class ScheduledAlertRuleTemplate(AlertRuleTemplate):
+ """Represents scheduled alert rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param tactics: The tactics of the alert rule template.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_frequency': {'key': 'properties.queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'properties.queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'properties.triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'properties.triggerThreshold', 'type': 'int'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'Scheduled' # type: str
+ self.alert_rules_created_by_template_count = kwargs.get('alert_rules_created_by_template_count', None)
+ self.created_date_utc = None
+ self.description = kwargs.get('description', None)
+ self.display_name = kwargs.get('display_name', None)
+ self.required_data_connectors = kwargs.get('required_data_connectors', None)
+ self.status = kwargs.get('status', None)
+ self.query = kwargs.get('query', None)
+ self.query_frequency = kwargs.get('query_frequency', None)
+ self.query_period = kwargs.get('query_period', None)
+ self.severity = kwargs.get('severity', None)
+ self.trigger_operator = kwargs.get('trigger_operator', None)
+ self.trigger_threshold = kwargs.get('trigger_threshold', None)
+ self.tactics = kwargs.get('tactics', None)
+
+
+class Settings(ResourceWithEtag):
+ """The Settings.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: ToggleSettings, UebaSettings.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'ToggleSettings': 'ToggleSettings', 'UebaSettings': 'UebaSettings'}
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Settings, self).__init__(**kwargs)
+ self.kind = 'Settings' # type: str
+
+
+class ThreatIntelligence(msrest.serialization.Model):
+ """ThreatIntelligence property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar confidence: Confidence (must be between 0 and 1).
+ :vartype confidence: float
+ :ivar provider_name: Name of the provider from whom this Threat Intelligence information was
+ received.
+ :vartype provider_name: str
+ :ivar report_link: Report link.
+ :vartype report_link: str
+ :ivar threat_description: Threat description (free text).
+ :vartype threat_description: str
+ :ivar threat_name: Threat name (e.g. "Jedobot malware").
+ :vartype threat_name: str
+ :ivar threat_type: Threat type (e.g. "Botnet").
+ :vartype threat_type: str
+ """
+
+ _validation = {
+ 'confidence': {'readonly': True},
+ 'provider_name': {'readonly': True},
+ 'report_link': {'readonly': True},
+ 'threat_description': {'readonly': True},
+ 'threat_name': {'readonly': True},
+ 'threat_type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'confidence': {'key': 'confidence', 'type': 'float'},
+ 'provider_name': {'key': 'providerName', 'type': 'str'},
+ 'report_link': {'key': 'reportLink', 'type': 'str'},
+ 'threat_description': {'key': 'threatDescription', 'type': 'str'},
+ 'threat_name': {'key': 'threatName', 'type': 'str'},
+ 'threat_type': {'key': 'threatType', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ThreatIntelligence, self).__init__(**kwargs)
+ self.confidence = None
+ self.provider_name = None
+ self.report_link = None
+ self.threat_description = None
+ self.threat_name = None
+ self.threat_type = None
+
+
+class TIDataConnector(DataConnector):
+ """Represents threat intelligence data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.indicators.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(TIDataConnector, self).__init__(**kwargs)
+ self.kind = 'ThreatIntelligence' # type: str
+ self.tenant_id = kwargs.get('tenant_id', None)
+ self.state = kwargs.get('state', None)
+
+
+class TIDataConnectorDataTypesIndicators(DataConnectorDataTypeCommon):
+ """Data type for indicators connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(TIDataConnectorDataTypesIndicators, self).__init__(**kwargs)
+
+
+class ToggleSettings(Settings):
+ """Settings with single toggle.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ :param is_enabled: Determines whether the setting is enable or disabled.
+ :type is_enabled: bool
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'is_enabled': {'key': 'properties.isEnabled', 'type': 'bool'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ToggleSettings, self).__init__(**kwargs)
+ self.kind = 'ToggleSettings' # type: str
+ self.is_enabled = kwargs.get('is_enabled', None)
+
+
+class UebaSettings(Settings):
+ """Represents settings for User and Entity Behavior Analytics enablement.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ :ivar atp_license_status: Determines whether the tenant has ATP (Advanced Threat Protection)
+ license. Possible values include: "Enabled", "Disabled".
+ :vartype atp_license_status: str or ~security_insights.models.LicenseStatus
+ :param is_enabled: Determines whether User and Entity Behavior Analytics is enabled for this
+ workspace.
+ :type is_enabled: bool
+ :ivar status_in_mcas: Determines whether User and Entity Behavior Analytics is enabled from
+ MCAS (Microsoft Cloud App Security). Possible values include: "Enabled", "Disabled".
+ :vartype status_in_mcas: str or ~security_insights.models.StatusInMCAS
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'atp_license_status': {'readonly': True},
+ 'status_in_mcas': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'atp_license_status': {'key': 'properties.atpLicenseStatus', 'type': 'str'},
+ 'is_enabled': {'key': 'properties.isEnabled', 'type': 'bool'},
+ 'status_in_mcas': {'key': 'properties.statusInMcas', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(UebaSettings, self).__init__(**kwargs)
+ self.kind = 'UebaSettings' # type: str
+ self.atp_license_status = None
+ self.is_enabled = kwargs.get('is_enabled', None)
+ self.status_in_mcas = None
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models_py3.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models_py3.py
new file mode 100644
index 00000000000..25dbbd71b16
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_models_py3.py
@@ -0,0 +1,3184 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+import datetime
+from typing import List, Optional, Union
+
+import msrest.serialization
+
+from ._security_insights_enums import *
+
+
+class ResourceWithEtag(msrest.serialization.Model):
+ """An azure resource object with an Etag property.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ **kwargs
+ ):
+ super(ResourceWithEtag, self).__init__(**kwargs)
+ self.id = None
+ self.name = None
+ self.type = None
+ self.etag = etag
+
+
+class DataConnector(ResourceWithEtag):
+ """Data connector.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: AwsCloudTrailDataConnector, AADDataConnector, AATPDataConnector, ASCDataConnector, MCASDataConnector, MDATPDataConnector, OfficeDataConnector, TIDataConnector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'AmazonWebServicesCloudTrail': 'AwsCloudTrailDataConnector', 'AzureActiveDirectory': 'AADDataConnector', 'AzureAdvancedThreatProtection': 'AATPDataConnector', 'AzureSecurityCenter': 'ASCDataConnector', 'MicrosoftCloudAppSecurity': 'MCASDataConnector', 'MicrosoftDefenderAdvancedThreatProtection': 'MDATPDataConnector', 'Office365': 'OfficeDataConnector', 'ThreatIntelligence': 'TIDataConnector'}
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ **kwargs
+ ):
+ super(DataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'DataConnector' # type: str
+
+
+class AADDataConnector(DataConnector):
+ """Represents AAD (Azure Active Directory) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(AADDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'AzureActiveDirectory' # type: str
+ self.tenant_id = tenant_id
+ self.state = state
+
+
+class AATPDataConnector(DataConnector):
+ """Represents AATP (Azure Advanced Threat Protection) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(AATPDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'AzureAdvancedThreatProtection' # type: str
+ self.tenant_id = tenant_id
+ self.state = state
+
+
+class ActionPropertiesBase(msrest.serialization.Model):
+ """Action property bag base.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ logic_app_resource_id: str,
+ **kwargs
+ ):
+ super(ActionPropertiesBase, self).__init__(**kwargs)
+ self.logic_app_resource_id = logic_app_resource_id
+
+
+class ActionRequest(ResourceWithEtag):
+ """Action for alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'logic_app_resource_id': {'key': 'properties.logicAppResourceId', 'type': 'str'},
+ 'trigger_uri': {'key': 'properties.triggerUri', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ logic_app_resource_id: Optional[str] = None,
+ trigger_uri: Optional[str] = None,
+ **kwargs
+ ):
+ super(ActionRequest, self).__init__(etag=etag, **kwargs)
+ self.logic_app_resource_id = logic_app_resource_id
+ self.trigger_uri = trigger_uri
+
+
+class ActionRequestProperties(ActionPropertiesBase):
+ """Action property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ 'trigger_uri': {'key': 'triggerUri', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ logic_app_resource_id: str,
+ trigger_uri: Optional[str] = None,
+ **kwargs
+ ):
+ super(ActionRequestProperties, self).__init__(logic_app_resource_id=logic_app_resource_id, **kwargs)
+ self.trigger_uri = trigger_uri
+
+
+class Resource(msrest.serialization.Model):
+ """An azure resource object.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(Resource, self).__init__(**kwargs)
+ self.id = None
+ self.name = None
+ self.type = None
+
+
+class ActionResponse(Resource):
+ """Action for alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the action.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param workflow_id: The name of the logic app's workflow.
+ :type workflow_id: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'logic_app_resource_id': {'key': 'properties.logicAppResourceId', 'type': 'str'},
+ 'workflow_id': {'key': 'properties.workflowId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ logic_app_resource_id: Optional[str] = None,
+ workflow_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(ActionResponse, self).__init__(**kwargs)
+ self.etag = etag
+ self.logic_app_resource_id = logic_app_resource_id
+ self.workflow_id = workflow_id
+
+
+class ActionResponseProperties(ActionPropertiesBase):
+ """Action property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param logic_app_resource_id: Required. Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param workflow_id: The name of the logic app's workflow.
+ :type workflow_id: str
+ """
+
+ _validation = {
+ 'logic_app_resource_id': {'required': True},
+ }
+
+ _attribute_map = {
+ 'logic_app_resource_id': {'key': 'logicAppResourceId', 'type': 'str'},
+ 'workflow_id': {'key': 'workflowId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ logic_app_resource_id: str,
+ workflow_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(ActionResponseProperties, self).__init__(logic_app_resource_id=logic_app_resource_id, **kwargs)
+ self.workflow_id = workflow_id
+
+
+class ActionsList(msrest.serialization.Model):
+ """List all the actions.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of actions.
+ :vartype next_link: str
+ :param value: Required. Array of actions.
+ :type value: list[~security_insights.models.ActionResponse]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[ActionResponse]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["ActionResponse"],
+ **kwargs
+ ):
+ super(ActionsList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class AlertRule(ResourceWithEtag):
+ """Alert rule.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: FusionAlertRule, MicrosoftSecurityIncidentCreationAlertRule, ScheduledAlertRule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'Fusion': 'FusionAlertRule', 'MicrosoftSecurityIncidentCreation': 'MicrosoftSecurityIncidentCreationAlertRule', 'Scheduled': 'ScheduledAlertRule'}
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ **kwargs
+ ):
+ super(AlertRule, self).__init__(etag=etag, **kwargs)
+ self.kind = 'AlertRule' # type: str
+
+
+class AlertRulesList(msrest.serialization.Model):
+ """List all the alert rules.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of alert rules.
+ :vartype next_link: str
+ :param value: Required. Array of alert rules.
+ :type value: list[~security_insights.models.AlertRule]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[AlertRule]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["AlertRule"],
+ **kwargs
+ ):
+ super(AlertRulesList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class AlertRuleTemplate(Resource):
+ """Alert rule template.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: FusionAlertRuleTemplate, MicrosoftSecurityIncidentCreationAlertRuleTemplate, ScheduledAlertRuleTemplate.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'Fusion': 'FusionAlertRuleTemplate', 'MicrosoftSecurityIncidentCreation': 'MicrosoftSecurityIncidentCreationAlertRuleTemplate', 'Scheduled': 'ScheduledAlertRuleTemplate'}
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(AlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'AlertRuleTemplate' # type: str
+
+
+class AlertRuleTemplateDataSource(msrest.serialization.Model):
+ """alert rule template data sources.
+
+ :param connector_id: The connector id that provides the following data types.
+ :type connector_id: str
+ :param data_types: The data types used by the alert rule template.
+ :type data_types: list[str]
+ """
+
+ _attribute_map = {
+ 'connector_id': {'key': 'connectorId', 'type': 'str'},
+ 'data_types': {'key': 'dataTypes', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ connector_id: Optional[str] = None,
+ data_types: Optional[List[str]] = None,
+ **kwargs
+ ):
+ super(AlertRuleTemplateDataSource, self).__init__(**kwargs)
+ self.connector_id = connector_id
+ self.data_types = data_types
+
+
+class AlertRuleTemplatesList(msrest.serialization.Model):
+ """List all the alert rule templates.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of alert rule templates.
+ :vartype next_link: str
+ :param value: Required. Array of alert rule templates.
+ :type value: list[~security_insights.models.AlertRuleTemplate]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[AlertRuleTemplate]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["AlertRuleTemplate"],
+ **kwargs
+ ):
+ super(AlertRuleTemplatesList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class AlertsDataTypeOfDataConnector(msrest.serialization.Model):
+ """Alerts data type for data connectors.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(AlertsDataTypeOfDataConnector, self).__init__(**kwargs)
+ self.state = state
+
+
+class ASCDataConnector(DataConnector):
+ """Represents ASC (Azure Security Center) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param subscription_id: The subscription id to connect to, and get the data from.
+ :type subscription_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'subscription_id': {'key': 'properties.subscriptionId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ subscription_id: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(ASCDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'AzureSecurityCenter' # type: str
+ self.subscription_id = subscription_id
+ self.state = state
+
+
+class DataConnectorWithAlertsProperties(msrest.serialization.Model):
+ """Data connector properties.
+
+ :param data_types: The available data types for the connector.
+ :type data_types: ~security_insights.models.AlertsDataTypeOfDataConnector
+ """
+
+ _attribute_map = {
+ 'data_types': {'key': 'dataTypes', 'type': 'AlertsDataTypeOfDataConnector'},
+ }
+
+ def __init__(
+ self,
+ *,
+ data_types: Optional["AlertsDataTypeOfDataConnector"] = None,
+ **kwargs
+ ):
+ super(DataConnectorWithAlertsProperties, self).__init__(**kwargs)
+ self.data_types = data_types
+
+
+class ASCDataConnectorProperties(DataConnectorWithAlertsProperties):
+ """ASC (Azure Security Center) data connector properties.
+
+ :param data_types: The available data types for the connector.
+ :type data_types: ~security_insights.models.AlertsDataTypeOfDataConnector
+ :param subscription_id: The subscription id to connect to, and get the data from.
+ :type subscription_id: str
+ """
+
+ _attribute_map = {
+ 'data_types': {'key': 'dataTypes', 'type': 'AlertsDataTypeOfDataConnector'},
+ 'subscription_id': {'key': 'subscriptionId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ data_types: Optional["AlertsDataTypeOfDataConnector"] = None,
+ subscription_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(ASCDataConnectorProperties, self).__init__(data_types=data_types, **kwargs)
+ self.subscription_id = subscription_id
+
+
+class AwsCloudTrailDataConnector(DataConnector):
+ """Represents Amazon Web Services CloudTrail data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param aws_role_arn: The Aws Role Arn (with CloudTrailReadOnly policy) that is used to access
+ the Aws account.
+ :type aws_role_arn: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'aws_role_arn': {'key': 'properties.awsRoleArn', 'type': 'str'},
+ 'state': {'key': 'dataTypes.logs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ aws_role_arn: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(AwsCloudTrailDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'AmazonWebServicesCloudTrail' # type: str
+ self.aws_role_arn = aws_role_arn
+ self.state = state
+
+
+class DataConnectorDataTypeCommon(msrest.serialization.Model):
+ """Common field for data type in data connectors.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(DataConnectorDataTypeCommon, self).__init__(**kwargs)
+ self.state = state
+
+
+class AwsCloudTrailDataConnectorDataTypesLogs(DataConnectorDataTypeCommon):
+ """Logs data type.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(AwsCloudTrailDataConnectorDataTypesLogs, self).__init__(state=state, **kwargs)
+
+
+class Bookmark(ResourceWithEtag):
+ """Represents a bookmark in Azure Security Insights.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param created: The time the bookmark was created.
+ :type created: ~datetime.datetime
+ :param display_name: The display name of the bookmark.
+ :type display_name: str
+ :param labels: List of labels relevant to this bookmark.
+ :type labels: list[str]
+ :param notes: The notes of the bookmark.
+ :type notes: str
+ :param query: The query of the bookmark.
+ :type query: str
+ :param query_result: The query result of the bookmark.
+ :type query_result: str
+ :param updated: The last time the bookmark was updated.
+ :type updated: ~datetime.datetime
+ :param incident_info: Describes an incident that relates to bookmark.
+ :type incident_info: ~security_insights.models.IncidentInfo
+ :ivar email_updated_by_email: The email of the user.
+ :vartype email_updated_by_email: str
+ :ivar name_updated_by_name: The name of the user.
+ :vartype name_updated_by_name: str
+ :param object_id_updated_by_object_id: The object id of the user.
+ :type object_id_updated_by_object_id: str
+ :ivar email_created_by_email: The email of the user.
+ :vartype email_created_by_email: str
+ :ivar name_created_by_name: The name of the user.
+ :vartype name_created_by_name: str
+ :param object_id_created_by_object_id: The object id of the user.
+ :type object_id_created_by_object_id: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'email_updated_by_email': {'readonly': True},
+ 'name_updated_by_name': {'readonly': True},
+ 'email_created_by_email': {'readonly': True},
+ 'name_created_by_name': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'created': {'key': 'properties.created', 'type': 'iso-8601'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'labels': {'key': 'properties.labels', 'type': '[str]'},
+ 'notes': {'key': 'properties.notes', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_result': {'key': 'properties.queryResult', 'type': 'str'},
+ 'updated': {'key': 'properties.updated', 'type': 'iso-8601'},
+ 'incident_info': {'key': 'properties.incidentInfo', 'type': 'IncidentInfo'},
+ 'email_updated_by_email': {'key': 'updatedBy.email', 'type': 'str'},
+ 'name_updated_by_name': {'key': 'updatedBy.name', 'type': 'str'},
+ 'object_id_updated_by_object_id': {'key': 'updatedBy.objectId', 'type': 'str'},
+ 'email_created_by_email': {'key': 'createdBy.email', 'type': 'str'},
+ 'name_created_by_name': {'key': 'createdBy.name', 'type': 'str'},
+ 'object_id_created_by_object_id': {'key': 'createdBy.objectId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ created: Optional[datetime.datetime] = None,
+ display_name: Optional[str] = None,
+ labels: Optional[List[str]] = None,
+ notes: Optional[str] = None,
+ query: Optional[str] = None,
+ query_result: Optional[str] = None,
+ updated: Optional[datetime.datetime] = None,
+ incident_info: Optional["IncidentInfo"] = None,
+ object_id_updated_by_object_id: Optional[str] = None,
+ object_id_created_by_object_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(Bookmark, self).__init__(etag=etag, **kwargs)
+ self.created = created
+ self.display_name = display_name
+ self.labels = labels
+ self.notes = notes
+ self.query = query
+ self.query_result = query_result
+ self.updated = updated
+ self.incident_info = incident_info
+ self.email_updated_by_email = None
+ self.name_updated_by_name = None
+ self.object_id_updated_by_object_id = object_id_updated_by_object_id
+ self.email_created_by_email = None
+ self.name_created_by_name = None
+ self.object_id_created_by_object_id = object_id_created_by_object_id
+
+
+class BookmarkList(msrest.serialization.Model):
+ """List all the bookmarks.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of cases.
+ :vartype next_link: str
+ :param value: Required. Array of bookmarks.
+ :type value: list[~security_insights.models.Bookmark]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Bookmark]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["Bookmark"],
+ **kwargs
+ ):
+ super(BookmarkList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class ClientInfo(msrest.serialization.Model):
+ """Information on the client (user or application) that made some action.
+
+ :param email: The email of the client.
+ :type email: str
+ :param name: The name of the client.
+ :type name: str
+ :param object_id: The object id of the client.
+ :type object_id: str
+ :param user_principal_name: The user principal name of the client.
+ :type user_principal_name: str
+ """
+
+ _attribute_map = {
+ 'email': {'key': 'email', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'object_id': {'key': 'objectId', 'type': 'str'},
+ 'user_principal_name': {'key': 'userPrincipalName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ email: Optional[str] = None,
+ name: Optional[str] = None,
+ object_id: Optional[str] = None,
+ user_principal_name: Optional[str] = None,
+ **kwargs
+ ):
+ super(ClientInfo, self).__init__(**kwargs)
+ self.email = email
+ self.name = name
+ self.object_id = object_id
+ self.user_principal_name = user_principal_name
+
+
+class DataConnectorList(msrest.serialization.Model):
+ """List all the data connectors.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of data connectors.
+ :vartype next_link: str
+ :param value: Required. Array of data connectors.
+ :type value: list[~security_insights.models.DataConnector]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[DataConnector]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["DataConnector"],
+ **kwargs
+ ):
+ super(DataConnectorList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class DataConnectorTenantId(msrest.serialization.Model):
+ """Properties data connector on tenant level.
+
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ """
+
+ _attribute_map = {
+ 'tenant_id': {'key': 'tenantId', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ tenant_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(DataConnectorTenantId, self).__init__(**kwargs)
+ self.tenant_id = tenant_id
+
+
+class ErrorAdditionalInfo(msrest.serialization.Model):
+ """The resource management error additional info.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar type: The additional info type.
+ :vartype type: str
+ :ivar info: The additional info.
+ :vartype info: object
+ """
+
+ _validation = {
+ 'type': {'readonly': True},
+ 'info': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'type': {'key': 'type', 'type': 'str'},
+ 'info': {'key': 'info', 'type': 'object'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ErrorAdditionalInfo, self).__init__(**kwargs)
+ self.type = None
+ self.info = None
+
+
+class ErrorResponse(msrest.serialization.Model):
+ """Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.).
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar code: The error code.
+ :vartype code: str
+ :ivar message: The error message.
+ :vartype message: str
+ :ivar target: The error target.
+ :vartype target: str
+ :ivar details: The error details.
+ :vartype details: list[~security_insights.models.ErrorResponse]
+ :ivar additional_info: The error additional info.
+ :vartype additional_info: list[~security_insights.models.ErrorAdditionalInfo]
+ """
+
+ _validation = {
+ 'code': {'readonly': True},
+ 'message': {'readonly': True},
+ 'target': {'readonly': True},
+ 'details': {'readonly': True},
+ 'additional_info': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'code': {'key': 'code', 'type': 'str'},
+ 'message': {'key': 'message', 'type': 'str'},
+ 'target': {'key': 'target', 'type': 'str'},
+ 'details': {'key': 'details', 'type': '[ErrorResponse]'},
+ 'additional_info': {'key': 'additionalInfo', 'type': '[ErrorAdditionalInfo]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ErrorResponse, self).__init__(**kwargs)
+ self.code = None
+ self.message = None
+ self.target = None
+ self.details = None
+ self.additional_info = None
+
+
+class FusionAlertRule(AlertRule):
+ """Represents Fusion alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :ivar description: The description of the alert rule.
+ :vartype description: str
+ :ivar display_name: The display name for alerts created by this alert rule.
+ :vartype display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :ivar severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :vartype severity: str or ~security_insights.models.AlertSeverity
+ :ivar tactics: The tactics of the alert rule.
+ :vartype tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'description': {'readonly': True},
+ 'display_name': {'readonly': True},
+ 'last_modified_utc': {'readonly': True},
+ 'severity': {'readonly': True},
+ 'tactics': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ alert_rule_template_name: Optional[str] = None,
+ enabled: Optional[bool] = None,
+ **kwargs
+ ):
+ super(FusionAlertRule, self).__init__(etag=etag, **kwargs)
+ self.kind = 'Fusion' # type: str
+ self.alert_rule_template_name = alert_rule_template_name
+ self.description = None
+ self.display_name = None
+ self.enabled = enabled
+ self.last_modified_utc = None
+ self.severity = None
+ self.tactics = None
+
+
+class FusionAlertRuleTemplate(AlertRuleTemplate):
+ """Represents Fusion alert rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param tactics: The tactics of the alert rule template.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ alert_rules_created_by_template_count: Optional[int] = None,
+ description: Optional[str] = None,
+ display_name: Optional[str] = None,
+ required_data_connectors: Optional[List["AlertRuleTemplateDataSource"]] = None,
+ status: Optional[Union[str, "TemplateStatus"]] = None,
+ severity: Optional[Union[str, "AlertSeverity"]] = None,
+ tactics: Optional[List[Union[str, "AttackTactic"]]] = None,
+ **kwargs
+ ):
+ super(FusionAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'Fusion' # type: str
+ self.alert_rules_created_by_template_count = alert_rules_created_by_template_count
+ self.created_date_utc = None
+ self.description = description
+ self.display_name = display_name
+ self.required_data_connectors = required_data_connectors
+ self.status = status
+ self.severity = severity
+ self.tactics = tactics
+
+
+class Incident(ResourceWithEtag):
+ """Represents an incident in Azure Security Insights.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :ivar additional_data: Additional data on the incident.
+ :vartype additional_data: ~security_insights.models.IncidentAdditionalData
+ :param classification: The reason the incident was closed. Possible values include:
+ "Undetermined", "TruePositive", "BenignPositive", "FalsePositive".
+ :type classification: str or ~security_insights.models.IncidentClassification
+ :param classification_comment: Describes the reason the incident was closed.
+ :type classification_comment: str
+ :param classification_reason: The classification reason the incident was closed with. Possible
+ values include: "SuspiciousActivity", "SuspiciousButExpected", "IncorrectAlertLogic",
+ "InaccurateData".
+ :type classification_reason: str or ~security_insights.models.IncidentClassificationReason
+ :ivar created_time_utc: The time the incident was created.
+ :vartype created_time_utc: ~datetime.datetime
+ :param description: The description of the incident.
+ :type description: str
+ :param first_activity_time_utc: The time of the first activity in the incident.
+ :type first_activity_time_utc: ~datetime.datetime
+ :ivar incident_url: The deep-link url to the incident in Azure portal.
+ :vartype incident_url: str
+ :ivar incident_number: A sequential number.
+ :vartype incident_number: int
+ :param labels: List of labels relevant to this incident.
+ :type labels: list[~security_insights.models.IncidentLabel]
+ :param last_activity_time_utc: The time of the last activity in the incident.
+ :type last_activity_time_utc: ~datetime.datetime
+ :ivar last_modified_time_utc: The last time the incident was updated.
+ :vartype last_modified_time_utc: ~datetime.datetime
+ :param owner: Describes a user that the incident is assigned to.
+ :type owner: ~security_insights.models.IncidentOwnerInfo
+ :ivar related_analytic_rule_ids: List of resource ids of Analytic rules related to the
+ incident.
+ :vartype related_analytic_rule_ids: list[str]
+ :param severity: The severity of the incident. Possible values include: "High", "Medium",
+ "Low", "Informational".
+ :type severity: str or ~security_insights.models.IncidentSeverity
+ :param status: The status of the incident. Possible values include: "New", "Active", "Closed".
+ :type status: str or ~security_insights.models.IncidentStatus
+ :param title: The title of the incident.
+ :type title: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'additional_data': {'readonly': True},
+ 'created_time_utc': {'readonly': True},
+ 'incident_url': {'readonly': True},
+ 'incident_number': {'readonly': True},
+ 'last_modified_time_utc': {'readonly': True},
+ 'related_analytic_rule_ids': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'additional_data': {'key': 'properties.additionalData', 'type': 'IncidentAdditionalData'},
+ 'classification': {'key': 'properties.classification', 'type': 'str'},
+ 'classification_comment': {'key': 'properties.classificationComment', 'type': 'str'},
+ 'classification_reason': {'key': 'properties.classificationReason', 'type': 'str'},
+ 'created_time_utc': {'key': 'properties.createdTimeUtc', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'first_activity_time_utc': {'key': 'properties.firstActivityTimeUtc', 'type': 'iso-8601'},
+ 'incident_url': {'key': 'properties.incidentUrl', 'type': 'str'},
+ 'incident_number': {'key': 'properties.incidentNumber', 'type': 'int'},
+ 'labels': {'key': 'properties.labels', 'type': '[IncidentLabel]'},
+ 'last_activity_time_utc': {'key': 'properties.lastActivityTimeUtc', 'type': 'iso-8601'},
+ 'last_modified_time_utc': {'key': 'properties.lastModifiedTimeUtc', 'type': 'iso-8601'},
+ 'owner': {'key': 'properties.owner', 'type': 'IncidentOwnerInfo'},
+ 'related_analytic_rule_ids': {'key': 'properties.relatedAnalyticRuleIds', 'type': '[str]'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'title': {'key': 'properties.title', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ classification: Optional[Union[str, "IncidentClassification"]] = None,
+ classification_comment: Optional[str] = None,
+ classification_reason: Optional[Union[str, "IncidentClassificationReason"]] = None,
+ description: Optional[str] = None,
+ first_activity_time_utc: Optional[datetime.datetime] = None,
+ labels: Optional[List["IncidentLabel"]] = None,
+ last_activity_time_utc: Optional[datetime.datetime] = None,
+ owner: Optional["IncidentOwnerInfo"] = None,
+ severity: Optional[Union[str, "IncidentSeverity"]] = None,
+ status: Optional[Union[str, "IncidentStatus"]] = None,
+ title: Optional[str] = None,
+ **kwargs
+ ):
+ super(Incident, self).__init__(etag=etag, **kwargs)
+ self.additional_data = None
+ self.classification = classification
+ self.classification_comment = classification_comment
+ self.classification_reason = classification_reason
+ self.created_time_utc = None
+ self.description = description
+ self.first_activity_time_utc = first_activity_time_utc
+ self.incident_url = None
+ self.incident_number = None
+ self.labels = labels
+ self.last_activity_time_utc = last_activity_time_utc
+ self.last_modified_time_utc = None
+ self.owner = owner
+ self.related_analytic_rule_ids = None
+ self.severity = severity
+ self.status = status
+ self.title = title
+
+
+class IncidentAdditionalData(msrest.serialization.Model):
+ """Incident additional data property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar alerts_count: The number of alerts in the incident.
+ :vartype alerts_count: int
+ :ivar bookmarks_count: The number of bookmarks in the incident.
+ :vartype bookmarks_count: int
+ :ivar comments_count: The number of comments in the incident.
+ :vartype comments_count: int
+ :ivar alert_product_names: List of product names of alerts in the incident.
+ :vartype alert_product_names: list[str]
+ :ivar tactics: The tactics associated with incident.
+ :vartype tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'alerts_count': {'readonly': True},
+ 'bookmarks_count': {'readonly': True},
+ 'comments_count': {'readonly': True},
+ 'alert_product_names': {'readonly': True},
+ 'tactics': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'alerts_count': {'key': 'alertsCount', 'type': 'int'},
+ 'bookmarks_count': {'key': 'bookmarksCount', 'type': 'int'},
+ 'comments_count': {'key': 'commentsCount', 'type': 'int'},
+ 'alert_product_names': {'key': 'alertProductNames', 'type': '[str]'},
+ 'tactics': {'key': 'tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(IncidentAdditionalData, self).__init__(**kwargs)
+ self.alerts_count = None
+ self.bookmarks_count = None
+ self.comments_count = None
+ self.alert_product_names = None
+ self.tactics = None
+
+
+class IncidentComment(Resource):
+ """Represents an incident comment.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :ivar created_time_utc: The time the comment was created.
+ :vartype created_time_utc: ~datetime.datetime
+ :param message: The comment message.
+ :type message: str
+ :ivar author: Describes the client that created the comment.
+ :vartype author: ~security_insights.models.ClientInfo
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'created_time_utc': {'readonly': True},
+ 'author': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'created_time_utc': {'key': 'properties.createdTimeUtc', 'type': 'iso-8601'},
+ 'message': {'key': 'properties.message', 'type': 'str'},
+ 'author': {'key': 'properties.author', 'type': 'ClientInfo'},
+ }
+
+ def __init__(
+ self,
+ *,
+ message: Optional[str] = None,
+ **kwargs
+ ):
+ super(IncidentComment, self).__init__(**kwargs)
+ self.created_time_utc = None
+ self.message = message
+ self.author = None
+
+
+class IncidentCommentList(msrest.serialization.Model):
+ """List of incident comments.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of comments.
+ :vartype next_link: str
+ :param value: Required. Array of comments.
+ :type value: list[~security_insights.models.IncidentComment]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[IncidentComment]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["IncidentComment"],
+ **kwargs
+ ):
+ super(IncidentCommentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class IncidentInfo(msrest.serialization.Model):
+ """Describes related incident information for the bookmark.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param incident_id: Required. Incident Id.
+ :type incident_id: str
+ :param severity: Required. The severity of the incident. Possible values include: "Critical",
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.CaseSeverity
+ :param title: Required. The title of the incident.
+ :type title: str
+ :param relation_name: Required. Relation Name.
+ :type relation_name: str
+ """
+
+ _validation = {
+ 'incident_id': {'required': True},
+ 'severity': {'required': True},
+ 'title': {'required': True},
+ 'relation_name': {'required': True},
+ }
+
+ _attribute_map = {
+ 'incident_id': {'key': 'incidentId', 'type': 'str'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'title': {'key': 'title', 'type': 'str'},
+ 'relation_name': {'key': 'relationName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ incident_id: str,
+ severity: Union[str, "CaseSeverity"],
+ title: str,
+ relation_name: str,
+ **kwargs
+ ):
+ super(IncidentInfo, self).__init__(**kwargs)
+ self.incident_id = incident_id
+ self.severity = severity
+ self.title = title
+ self.relation_name = relation_name
+
+
+class IncidentLabel(msrest.serialization.Model):
+ """Represents an incident label.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param label_name: Required. The name of the label.
+ :type label_name: str
+ :ivar label_type: The type of the label. Possible values include: "User", "System".
+ :vartype label_type: str or ~security_insights.models.IncidentLabelType
+ """
+
+ _validation = {
+ 'label_name': {'required': True},
+ 'label_type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'label_name': {'key': 'labelName', 'type': 'str'},
+ 'label_type': {'key': 'labelType', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ label_name: str,
+ **kwargs
+ ):
+ super(IncidentLabel, self).__init__(**kwargs)
+ self.label_name = label_name
+ self.label_type = None
+
+
+class IncidentList(msrest.serialization.Model):
+ """List all the incidents.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of incidents.
+ :vartype next_link: str
+ :param value: Required. Array of incidents.
+ :type value: list[~security_insights.models.Incident]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Incident]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["Incident"],
+ **kwargs
+ ):
+ super(IncidentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class IncidentOwnerInfo(msrest.serialization.Model):
+ """Information on the user an incident is assigned to.
+
+ :param email: The email of the user the incident is assigned to.
+ :type email: str
+ :param assigned_to: The name of the user the incident is assigned to.
+ :type assigned_to: str
+ :param object_id: The object id of the user the incident is assigned to.
+ :type object_id: str
+ :param user_principal_name: The user principal name of the user the incident is assigned to.
+ :type user_principal_name: str
+ """
+
+ _attribute_map = {
+ 'email': {'key': 'email', 'type': 'str'},
+ 'assigned_to': {'key': 'assignedTo', 'type': 'str'},
+ 'object_id': {'key': 'objectId', 'type': 'str'},
+ 'user_principal_name': {'key': 'userPrincipalName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ email: Optional[str] = None,
+ assigned_to: Optional[str] = None,
+ object_id: Optional[str] = None,
+ user_principal_name: Optional[str] = None,
+ **kwargs
+ ):
+ super(IncidentOwnerInfo, self).__init__(**kwargs)
+ self.email = email
+ self.assigned_to = assigned_to
+ self.object_id = object_id
+ self.user_principal_name = user_principal_name
+
+
+class MCASDataConnector(DataConnector):
+ """Represents MCAS (Microsoft Cloud App Security) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state_data_types_alerts_state: Describe whether this data type connection is enabled or
+ not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_alerts_state: str or ~security_insights.models.DataTypeState
+ :param state_data_types_discovery_logs_state: Describe whether this data type connection is
+ enabled or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_discovery_logs_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state_data_types_alerts_state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ 'state_data_types_discovery_logs_state': {'key': 'dataTypes.discoveryLogs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state_data_types_alerts_state: Optional[Union[str, "DataTypeState"]] = None,
+ state_data_types_discovery_logs_state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(MCASDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'MicrosoftCloudAppSecurity' # type: str
+ self.tenant_id = tenant_id
+ self.state_data_types_alerts_state = state_data_types_alerts_state
+ self.state_data_types_discovery_logs_state = state_data_types_discovery_logs_state
+
+
+class MCASDataConnectorDataTypes(AlertsDataTypeOfDataConnector):
+ """The available data types for MCAS (Microsoft Cloud App Security) data connector.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ :param state_discovery_logs_state: Describe whether this data type connection is enabled or
+ not. Possible values include: "Enabled", "Disabled".
+ :type state_discovery_logs_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'alerts.state', 'type': 'str'},
+ 'state_discovery_logs_state': {'key': 'discoveryLogs.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ state_discovery_logs_state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(MCASDataConnectorDataTypes, self).__init__(state=state, **kwargs)
+ self.state_discovery_logs_state = state_discovery_logs_state
+
+
+class MDATPDataConnector(DataConnector):
+ """Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.alerts.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(MDATPDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'MicrosoftDefenderAdvancedThreatProtection' # type: str
+ self.tenant_id = tenant_id
+ self.state = state
+
+
+class MicrosoftSecurityIncidentCreationAlertRule(AlertRule):
+ """Represents MicrosoftSecurityIncidentCreation rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: The alerts' productName on which the cases will be generated. Possible
+ values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure Advanced Threat
+ Protection", "Azure Active Directory Identity Protection", "Azure Security Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'display_names_filter': {'key': 'properties.displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'properties.displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'properties.productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'properties.severitiesFilter', 'type': '[str]'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ display_names_filter: Optional[List[str]] = None,
+ display_names_exclude_filter: Optional[List[str]] = None,
+ product_filter: Optional[Union[str, "MicrosoftSecurityProductName"]] = None,
+ severities_filter: Optional[List[Union[str, "AlertSeverity"]]] = None,
+ alert_rule_template_name: Optional[str] = None,
+ description: Optional[str] = None,
+ display_name: Optional[str] = None,
+ enabled: Optional[bool] = None,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRule, self).__init__(etag=etag, **kwargs)
+ self.kind = 'MicrosoftSecurityIncidentCreation' # type: str
+ self.display_names_filter = display_names_filter
+ self.display_names_exclude_filter = display_names_exclude_filter
+ self.product_filter = product_filter
+ self.severities_filter = severities_filter
+ self.alert_rule_template_name = alert_rule_template_name
+ self.description = description
+ self.display_name = display_name
+ self.enabled = enabled
+ self.last_modified_utc = None
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleCommonProperties(msrest.serialization.Model):
+ """MicrosoftSecurityIncidentCreation rule common property bag.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: Required. The alerts' productName on which the cases will be generated.
+ Possible values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure
+ Advanced Threat Protection", "Azure Active Directory Identity Protection", "Azure Security
+ Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ """
+
+ _validation = {
+ 'product_filter': {'required': True},
+ }
+
+ _attribute_map = {
+ 'display_names_filter': {'key': 'displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'severitiesFilter', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ product_filter: Union[str, "MicrosoftSecurityProductName"],
+ display_names_filter: Optional[List[str]] = None,
+ display_names_exclude_filter: Optional[List[str]] = None,
+ severities_filter: Optional[List[Union[str, "AlertSeverity"]]] = None,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleCommonProperties, self).__init__(**kwargs)
+ self.display_names_filter = display_names_filter
+ self.display_names_exclude_filter = display_names_exclude_filter
+ self.product_filter = product_filter
+ self.severities_filter = severities_filter
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleProperties(MicrosoftSecurityIncidentCreationAlertRuleCommonProperties):
+ """MicrosoftSecurityIncidentCreation rule property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: Required. The alerts' productName on which the cases will be generated.
+ Possible values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure
+ Advanced Threat Protection", "Azure Active Directory Identity Protection", "Azure Security
+ Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: Required. The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Required. Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ """
+
+ _validation = {
+ 'product_filter': {'required': True},
+ 'display_name': {'required': True},
+ 'enabled': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'display_names_filter': {'key': 'displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'severitiesFilter', 'type': '[str]'},
+ 'alert_rule_template_name': {'key': 'alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'description', 'type': 'str'},
+ 'display_name': {'key': 'displayName', 'type': 'str'},
+ 'enabled': {'key': 'enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'lastModifiedUtc', 'type': 'iso-8601'},
+ }
+
+ def __init__(
+ self,
+ *,
+ product_filter: Union[str, "MicrosoftSecurityProductName"],
+ display_name: str,
+ enabled: bool,
+ display_names_filter: Optional[List[str]] = None,
+ display_names_exclude_filter: Optional[List[str]] = None,
+ severities_filter: Optional[List[Union[str, "AlertSeverity"]]] = None,
+ alert_rule_template_name: Optional[str] = None,
+ description: Optional[str] = None,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleProperties, self).__init__(display_names_filter=display_names_filter, display_names_exclude_filter=display_names_exclude_filter, product_filter=product_filter, severities_filter=severities_filter, **kwargs)
+ self.alert_rule_template_name = alert_rule_template_name
+ self.description = description
+ self.display_name = display_name
+ self.enabled = enabled
+ self.last_modified_utc = None
+
+
+class MicrosoftSecurityIncidentCreationAlertRuleTemplate(AlertRuleTemplate):
+ """Represents MicrosoftSecurityIncidentCreation rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param display_names_filter: the alerts' displayNames on which the cases will be generated.
+ :type display_names_filter: list[str]
+ :param display_names_exclude_filter: the alerts' displayNames on which the cases will not be
+ generated.
+ :type display_names_exclude_filter: list[str]
+ :param product_filter: The alerts' productName on which the cases will be generated. Possible
+ values include: "Microsoft Cloud App Security", "Azure Security Center", "Azure Advanced Threat
+ Protection", "Azure Active Directory Identity Protection", "Azure Security Center for IoT".
+ :type product_filter: str or ~security_insights.models.MicrosoftSecurityProductName
+ :param severities_filter: the alerts' severities on which the cases will be generated.
+ :type severities_filter: list[str or ~security_insights.models.AlertSeverity]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'display_names_filter': {'key': 'properties.displayNamesFilter', 'type': '[str]'},
+ 'display_names_exclude_filter': {'key': 'properties.displayNamesExcludeFilter', 'type': '[str]'},
+ 'product_filter': {'key': 'properties.productFilter', 'type': 'str'},
+ 'severities_filter': {'key': 'properties.severitiesFilter', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ alert_rules_created_by_template_count: Optional[int] = None,
+ description: Optional[str] = None,
+ display_name: Optional[str] = None,
+ required_data_connectors: Optional[List["AlertRuleTemplateDataSource"]] = None,
+ status: Optional[Union[str, "TemplateStatus"]] = None,
+ display_names_filter: Optional[List[str]] = None,
+ display_names_exclude_filter: Optional[List[str]] = None,
+ product_filter: Optional[Union[str, "MicrosoftSecurityProductName"]] = None,
+ severities_filter: Optional[List[Union[str, "AlertSeverity"]]] = None,
+ **kwargs
+ ):
+ super(MicrosoftSecurityIncidentCreationAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'MicrosoftSecurityIncidentCreation' # type: str
+ self.alert_rules_created_by_template_count = alert_rules_created_by_template_count
+ self.created_date_utc = None
+ self.description = description
+ self.display_name = display_name
+ self.required_data_connectors = required_data_connectors
+ self.status = status
+ self.display_names_filter = display_names_filter
+ self.display_names_exclude_filter = display_names_exclude_filter
+ self.product_filter = product_filter
+ self.severities_filter = severities_filter
+
+
+class OfficeConsent(Resource):
+ """Consent for Office365 tenant that already made.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param tenant_id: The tenantId of the Office365 with the consent.
+ :type tenant_id: str
+ :ivar tenant_name: The tenant name of the Office365 with the consent.
+ :vartype tenant_name: str
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'tenant_name': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'tenant_name': {'key': 'properties.tenantName', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ tenant_id: Optional[str] = None,
+ **kwargs
+ ):
+ super(OfficeConsent, self).__init__(**kwargs)
+ self.tenant_id = tenant_id
+ self.tenant_name = None
+
+
+class OfficeConsentList(msrest.serialization.Model):
+ """List of all the office365 consents.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar next_link: URL to fetch the next set of office consents.
+ :vartype next_link: str
+ :param value: Required. Array of the consents.
+ :type value: list[~security_insights.models.OfficeConsent]
+ """
+
+ _validation = {
+ 'next_link': {'readonly': True},
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[OfficeConsent]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["OfficeConsent"],
+ **kwargs
+ ):
+ super(OfficeConsentList, self).__init__(**kwargs)
+ self.next_link = None
+ self.value = value
+
+
+class OfficeDataConnector(DataConnector):
+ """Represents office data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state_data_types_share_point_state: Describe whether this data type connection is
+ enabled or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_share_point_state: str or ~security_insights.models.DataTypeState
+ :param state_data_types_exchange_state: Describe whether this data type connection is enabled
+ or not. Possible values include: "Enabled", "Disabled".
+ :type state_data_types_exchange_state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state_data_types_share_point_state': {'key': 'dataTypes.sharePoint.state', 'type': 'str'},
+ 'state_data_types_exchange_state': {'key': 'dataTypes.exchange.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state_data_types_share_point_state: Optional[Union[str, "DataTypeState"]] = None,
+ state_data_types_exchange_state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(OfficeDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'Office365' # type: str
+ self.tenant_id = tenant_id
+ self.state_data_types_share_point_state = state_data_types_share_point_state
+ self.state_data_types_exchange_state = state_data_types_exchange_state
+
+
+class OfficeDataConnectorDataTypesExchange(DataConnectorDataTypeCommon):
+ """Exchange data type connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(OfficeDataConnectorDataTypesExchange, self).__init__(state=state, **kwargs)
+
+
+class OfficeDataConnectorDataTypesSharePoint(DataConnectorDataTypeCommon):
+ """SharePoint data type connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(OfficeDataConnectorDataTypesSharePoint, self).__init__(state=state, **kwargs)
+
+
+class Operation(msrest.serialization.Model):
+ """Operation provided by provider.
+
+ :param display: Properties of the operation.
+ :type display: ~security_insights.models.OperationDisplay
+ :param name: Name of the operation.
+ :type name: str
+ """
+
+ _attribute_map = {
+ 'display': {'key': 'display', 'type': 'OperationDisplay'},
+ 'name': {'key': 'name', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ display: Optional["OperationDisplay"] = None,
+ name: Optional[str] = None,
+ **kwargs
+ ):
+ super(Operation, self).__init__(**kwargs)
+ self.display = display
+ self.name = name
+
+
+class OperationDisplay(msrest.serialization.Model):
+ """Properties of the operation.
+
+ :param description: Description of the operation.
+ :type description: str
+ :param operation: Operation name.
+ :type operation: str
+ :param provider: Provider name.
+ :type provider: str
+ :param resource: Resource name.
+ :type resource: str
+ """
+
+ _attribute_map = {
+ 'description': {'key': 'description', 'type': 'str'},
+ 'operation': {'key': 'operation', 'type': 'str'},
+ 'provider': {'key': 'provider', 'type': 'str'},
+ 'resource': {'key': 'resource', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ description: Optional[str] = None,
+ operation: Optional[str] = None,
+ provider: Optional[str] = None,
+ resource: Optional[str] = None,
+ **kwargs
+ ):
+ super(OperationDisplay, self).__init__(**kwargs)
+ self.description = description
+ self.operation = operation
+ self.provider = provider
+ self.resource = resource
+
+
+class OperationsList(msrest.serialization.Model):
+ """Lists the operations available in the SecurityInsights RP.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param next_link: URL to fetch the next set of operations.
+ :type next_link: str
+ :param value: Required. Array of operations.
+ :type value: list[~security_insights.models.Operation]
+ """
+
+ _validation = {
+ 'value': {'required': True},
+ }
+
+ _attribute_map = {
+ 'next_link': {'key': 'nextLink', 'type': 'str'},
+ 'value': {'key': 'value', 'type': '[Operation]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ value: List["Operation"],
+ next_link: Optional[str] = None,
+ **kwargs
+ ):
+ super(OperationsList, self).__init__(**kwargs)
+ self.next_link = next_link
+ self.value = value
+
+
+class ScheduledAlertRule(AlertRule):
+ """Represents scheduled alert rule.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert rule has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :param suppression_duration: The suppression (in ISO 8601 duration format) to wait since last
+ time this alert rule been triggered.
+ :type suppression_duration: ~datetime.timedelta
+ :param suppression_enabled: Determines whether the suppression for this alert rule is enabled
+ or disabled.
+ :type suppression_enabled: bool
+ :param tactics: The tactics of the alert rule.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_frequency': {'key': 'properties.queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'properties.queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'properties.triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'properties.triggerThreshold', 'type': 'int'},
+ 'alert_rule_template_name': {'key': 'properties.alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'enabled': {'key': 'properties.enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'properties.lastModifiedUtc', 'type': 'iso-8601'},
+ 'suppression_duration': {'key': 'properties.suppressionDuration', 'type': 'duration'},
+ 'suppression_enabled': {'key': 'properties.suppressionEnabled', 'type': 'bool'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ query: Optional[str] = None,
+ query_frequency: Optional[datetime.timedelta] = None,
+ query_period: Optional[datetime.timedelta] = None,
+ severity: Optional[Union[str, "AlertSeverity"]] = None,
+ trigger_operator: Optional[Union[str, "TriggerOperator"]] = None,
+ trigger_threshold: Optional[int] = None,
+ alert_rule_template_name: Optional[str] = None,
+ description: Optional[str] = None,
+ display_name: Optional[str] = None,
+ enabled: Optional[bool] = None,
+ suppression_duration: Optional[datetime.timedelta] = None,
+ suppression_enabled: Optional[bool] = None,
+ tactics: Optional[List[Union[str, "AttackTactic"]]] = None,
+ **kwargs
+ ):
+ super(ScheduledAlertRule, self).__init__(etag=etag, **kwargs)
+ self.kind = 'Scheduled' # type: str
+ self.query = query
+ self.query_frequency = query_frequency
+ self.query_period = query_period
+ self.severity = severity
+ self.trigger_operator = trigger_operator
+ self.trigger_threshold = trigger_threshold
+ self.alert_rule_template_name = alert_rule_template_name
+ self.description = description
+ self.display_name = display_name
+ self.enabled = enabled
+ self.last_modified_utc = None
+ self.suppression_duration = suppression_duration
+ self.suppression_enabled = suppression_enabled
+ self.tactics = tactics
+
+
+class ScheduledAlertRuleCommonProperties(msrest.serialization.Model):
+ """Schedule alert rule template property bag.
+
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ """
+
+ _attribute_map = {
+ 'query': {'key': 'query', 'type': 'str'},
+ 'query_frequency': {'key': 'queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'triggerThreshold', 'type': 'int'},
+ }
+
+ def __init__(
+ self,
+ *,
+ query: Optional[str] = None,
+ query_frequency: Optional[datetime.timedelta] = None,
+ query_period: Optional[datetime.timedelta] = None,
+ severity: Optional[Union[str, "AlertSeverity"]] = None,
+ trigger_operator: Optional[Union[str, "TriggerOperator"]] = None,
+ trigger_threshold: Optional[int] = None,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleCommonProperties, self).__init__(**kwargs)
+ self.query = query
+ self.query_frequency = query_frequency
+ self.query_period = query_period
+ self.severity = severity
+ self.trigger_operator = trigger_operator
+ self.trigger_threshold = trigger_threshold
+
+
+class ScheduledAlertRuleProperties(ScheduledAlertRuleCommonProperties):
+ """Scheduled alert rule base property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param alert_rule_template_name: The Name of the alert rule template used to create this rule.
+ :type alert_rule_template_name: str
+ :param description: The description of the alert rule.
+ :type description: str
+ :param display_name: Required. The display name for alerts created by this alert rule.
+ :type display_name: str
+ :param enabled: Required. Determines whether this alert rule is enabled or disabled.
+ :type enabled: bool
+ :ivar last_modified_utc: The last time that this alert rule has been modified.
+ :vartype last_modified_utc: ~datetime.datetime
+ :param suppression_duration: Required. The suppression (in ISO 8601 duration format) to wait
+ since last time this alert rule been triggered.
+ :type suppression_duration: ~datetime.timedelta
+ :param suppression_enabled: Required. Determines whether the suppression for this alert rule is
+ enabled or disabled.
+ :type suppression_enabled: bool
+ :param tactics: The tactics of the alert rule.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'display_name': {'required': True},
+ 'enabled': {'required': True},
+ 'last_modified_utc': {'readonly': True},
+ 'suppression_duration': {'required': True},
+ 'suppression_enabled': {'required': True},
+ }
+
+ _attribute_map = {
+ 'query': {'key': 'query', 'type': 'str'},
+ 'query_frequency': {'key': 'queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'triggerThreshold', 'type': 'int'},
+ 'alert_rule_template_name': {'key': 'alertRuleTemplateName', 'type': 'str'},
+ 'description': {'key': 'description', 'type': 'str'},
+ 'display_name': {'key': 'displayName', 'type': 'str'},
+ 'enabled': {'key': 'enabled', 'type': 'bool'},
+ 'last_modified_utc': {'key': 'lastModifiedUtc', 'type': 'iso-8601'},
+ 'suppression_duration': {'key': 'suppressionDuration', 'type': 'duration'},
+ 'suppression_enabled': {'key': 'suppressionEnabled', 'type': 'bool'},
+ 'tactics': {'key': 'tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ display_name: str,
+ enabled: bool,
+ suppression_duration: datetime.timedelta,
+ suppression_enabled: bool,
+ query: Optional[str] = None,
+ query_frequency: Optional[datetime.timedelta] = None,
+ query_period: Optional[datetime.timedelta] = None,
+ severity: Optional[Union[str, "AlertSeverity"]] = None,
+ trigger_operator: Optional[Union[str, "TriggerOperator"]] = None,
+ trigger_threshold: Optional[int] = None,
+ alert_rule_template_name: Optional[str] = None,
+ description: Optional[str] = None,
+ tactics: Optional[List[Union[str, "AttackTactic"]]] = None,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleProperties, self).__init__(query=query, query_frequency=query_frequency, query_period=query_period, severity=severity, trigger_operator=trigger_operator, trigger_threshold=trigger_threshold, **kwargs)
+ self.alert_rule_template_name = alert_rule_template_name
+ self.description = description
+ self.display_name = display_name
+ self.enabled = enabled
+ self.last_modified_utc = None
+ self.suppression_duration = suppression_duration
+ self.suppression_enabled = suppression_enabled
+ self.tactics = tactics
+
+
+class ScheduledAlertRuleTemplate(AlertRuleTemplate):
+ """Represents scheduled alert rule template.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param kind: Required. The alert rule kind.Constant filled by server. Possible values include:
+ "Scheduled", "MicrosoftSecurityIncidentCreation", "Fusion".
+ :type kind: str or ~security_insights.models.AlertRuleKind
+ :param alert_rules_created_by_template_count: the number of alert rules that were created by
+ this template.
+ :type alert_rules_created_by_template_count: int
+ :ivar created_date_utc: The time that this alert rule template has been added.
+ :vartype created_date_utc: ~datetime.datetime
+ :param description: The description of the alert rule template.
+ :type description: str
+ :param display_name: The display name for alert rule template.
+ :type display_name: str
+ :param required_data_connectors: The required data connectors for this template.
+ :type required_data_connectors: list[~security_insights.models.AlertRuleTemplateDataSource]
+ :param status: The alert rule template status. Possible values include: "Installed",
+ "Available", "NotAvailable".
+ :type status: str or ~security_insights.models.TemplateStatus
+ :param query: The query that creates alerts for this rule.
+ :type query: str
+ :param query_frequency: The frequency (in ISO 8601 duration format) for this alert rule to run.
+ :type query_frequency: ~datetime.timedelta
+ :param query_period: The period (in ISO 8601 duration format) that this alert rule looks at.
+ :type query_period: ~datetime.timedelta
+ :param severity: The severity for alerts created by this alert rule. Possible values include:
+ "High", "Medium", "Low", "Informational".
+ :type severity: str or ~security_insights.models.AlertSeverity
+ :param trigger_operator: The operation against the threshold that triggers alert rule. Possible
+ values include: "GreaterThan", "LessThan", "Equal", "NotEqual".
+ :type trigger_operator: str or ~security_insights.models.TriggerOperator
+ :param trigger_threshold: The threshold triggers this alert rule.
+ :type trigger_threshold: int
+ :param tactics: The tactics of the alert rule template.
+ :type tactics: list[str or ~security_insights.models.AttackTactic]
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'created_date_utc': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'alert_rules_created_by_template_count': {'key': 'properties.alertRulesCreatedByTemplateCount', 'type': 'int'},
+ 'created_date_utc': {'key': 'properties.createdDateUTC', 'type': 'iso-8601'},
+ 'description': {'key': 'properties.description', 'type': 'str'},
+ 'display_name': {'key': 'properties.displayName', 'type': 'str'},
+ 'required_data_connectors': {'key': 'properties.requiredDataConnectors', 'type': '[AlertRuleTemplateDataSource]'},
+ 'status': {'key': 'properties.status', 'type': 'str'},
+ 'query': {'key': 'properties.query', 'type': 'str'},
+ 'query_frequency': {'key': 'properties.queryFrequency', 'type': 'duration'},
+ 'query_period': {'key': 'properties.queryPeriod', 'type': 'duration'},
+ 'severity': {'key': 'properties.severity', 'type': 'str'},
+ 'trigger_operator': {'key': 'properties.triggerOperator', 'type': 'str'},
+ 'trigger_threshold': {'key': 'properties.triggerThreshold', 'type': 'int'},
+ 'tactics': {'key': 'properties.tactics', 'type': '[str]'},
+ }
+
+ def __init__(
+ self,
+ *,
+ alert_rules_created_by_template_count: Optional[int] = None,
+ description: Optional[str] = None,
+ display_name: Optional[str] = None,
+ required_data_connectors: Optional[List["AlertRuleTemplateDataSource"]] = None,
+ status: Optional[Union[str, "TemplateStatus"]] = None,
+ query: Optional[str] = None,
+ query_frequency: Optional[datetime.timedelta] = None,
+ query_period: Optional[datetime.timedelta] = None,
+ severity: Optional[Union[str, "AlertSeverity"]] = None,
+ trigger_operator: Optional[Union[str, "TriggerOperator"]] = None,
+ trigger_threshold: Optional[int] = None,
+ tactics: Optional[List[Union[str, "AttackTactic"]]] = None,
+ **kwargs
+ ):
+ super(ScheduledAlertRuleTemplate, self).__init__(**kwargs)
+ self.kind = 'Scheduled' # type: str
+ self.alert_rules_created_by_template_count = alert_rules_created_by_template_count
+ self.created_date_utc = None
+ self.description = description
+ self.display_name = display_name
+ self.required_data_connectors = required_data_connectors
+ self.status = status
+ self.query = query
+ self.query_frequency = query_frequency
+ self.query_period = query_period
+ self.severity = severity
+ self.trigger_operator = trigger_operator
+ self.trigger_threshold = trigger_threshold
+ self.tactics = tactics
+
+
+class Settings(ResourceWithEtag):
+ """The Settings.
+
+ You probably want to use the sub-classes and not this class directly. Known
+ sub-classes are: ToggleSettings, UebaSettings.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ }
+
+ _subtype_map = {
+ 'kind': {'ToggleSettings': 'ToggleSettings', 'UebaSettings': 'UebaSettings'}
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ **kwargs
+ ):
+ super(Settings, self).__init__(etag=etag, **kwargs)
+ self.kind = 'Settings' # type: str
+
+
+class ThreatIntelligence(msrest.serialization.Model):
+ """ThreatIntelligence property bag.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ :ivar confidence: Confidence (must be between 0 and 1).
+ :vartype confidence: float
+ :ivar provider_name: Name of the provider from whom this Threat Intelligence information was
+ received.
+ :vartype provider_name: str
+ :ivar report_link: Report link.
+ :vartype report_link: str
+ :ivar threat_description: Threat description (free text).
+ :vartype threat_description: str
+ :ivar threat_name: Threat name (e.g. "Jedobot malware").
+ :vartype threat_name: str
+ :ivar threat_type: Threat type (e.g. "Botnet").
+ :vartype threat_type: str
+ """
+
+ _validation = {
+ 'confidence': {'readonly': True},
+ 'provider_name': {'readonly': True},
+ 'report_link': {'readonly': True},
+ 'threat_description': {'readonly': True},
+ 'threat_name': {'readonly': True},
+ 'threat_type': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'confidence': {'key': 'confidence', 'type': 'float'},
+ 'provider_name': {'key': 'providerName', 'type': 'str'},
+ 'report_link': {'key': 'reportLink', 'type': 'str'},
+ 'threat_description': {'key': 'threatDescription', 'type': 'str'},
+ 'threat_name': {'key': 'threatName', 'type': 'str'},
+ 'threat_type': {'key': 'threatType', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ **kwargs
+ ):
+ super(ThreatIntelligence, self).__init__(**kwargs)
+ self.confidence = None
+ self.provider_name = None
+ self.report_link = None
+ self.threat_description = None
+ self.threat_name = None
+ self.threat_type = None
+
+
+class TIDataConnector(DataConnector):
+ """Represents threat intelligence data connector.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "AzureActiveDirectory", "AzureSecurityCenter", "MicrosoftCloudAppSecurity",
+ "ThreatIntelligence", "Office365", "AmazonWebServicesCloudTrail",
+ "AzureAdvancedThreatProtection", "MicrosoftDefenderAdvancedThreatProtection".
+ :type kind: str or ~security_insights.models.DataConnectorKind
+ :param tenant_id: The tenant id to connect to, and get the data from.
+ :type tenant_id: str
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'tenant_id': {'key': 'properties.tenantId', 'type': 'str'},
+ 'state': {'key': 'dataTypes.indicators.state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ tenant_id: Optional[str] = None,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(TIDataConnector, self).__init__(etag=etag, **kwargs)
+ self.kind = 'ThreatIntelligence' # type: str
+ self.tenant_id = tenant_id
+ self.state = state
+
+
+class TIDataConnectorDataTypesIndicators(DataConnectorDataTypeCommon):
+ """Data type for indicators connection.
+
+ :param state: Describe whether this data type connection is enabled or not. Possible values
+ include: "Enabled", "Disabled".
+ :type state: str or ~security_insights.models.DataTypeState
+ """
+
+ _attribute_map = {
+ 'state': {'key': 'state', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ state: Optional[Union[str, "DataTypeState"]] = None,
+ **kwargs
+ ):
+ super(TIDataConnectorDataTypesIndicators, self).__init__(state=state, **kwargs)
+
+
+class ToggleSettings(Settings):
+ """Settings with single toggle.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ :param is_enabled: Determines whether the setting is enable or disabled.
+ :type is_enabled: bool
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'is_enabled': {'key': 'properties.isEnabled', 'type': 'bool'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ is_enabled: Optional[bool] = None,
+ **kwargs
+ ):
+ super(ToggleSettings, self).__init__(etag=etag, **kwargs)
+ self.kind = 'ToggleSettings' # type: str
+ self.is_enabled = is_enabled
+
+
+class UebaSettings(Settings):
+ """Represents settings for User and Entity Behavior Analytics enablement.
+
+ Variables are only populated by the server, and will be ignored when sending a request.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :ivar id: Azure resource Id.
+ :vartype id: str
+ :ivar name: Azure resource name.
+ :vartype name: str
+ :ivar type: Azure resource type.
+ :vartype type: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param kind: Required. The data connector kind.Constant filled by server. Possible values
+ include: "UebaSettings", "ToggleSettings".
+ :type kind: str or ~security_insights.models.SettingKind
+ :ivar atp_license_status: Determines whether the tenant has ATP (Advanced Threat Protection)
+ license. Possible values include: "Enabled", "Disabled".
+ :vartype atp_license_status: str or ~security_insights.models.LicenseStatus
+ :param is_enabled: Determines whether User and Entity Behavior Analytics is enabled for this
+ workspace.
+ :type is_enabled: bool
+ :ivar status_in_mcas: Determines whether User and Entity Behavior Analytics is enabled from
+ MCAS (Microsoft Cloud App Security). Possible values include: "Enabled", "Disabled".
+ :vartype status_in_mcas: str or ~security_insights.models.StatusInMCAS
+ """
+
+ _validation = {
+ 'id': {'readonly': True},
+ 'name': {'readonly': True},
+ 'type': {'readonly': True},
+ 'kind': {'required': True},
+ 'atp_license_status': {'readonly': True},
+ 'status_in_mcas': {'readonly': True},
+ }
+
+ _attribute_map = {
+ 'id': {'key': 'id', 'type': 'str'},
+ 'name': {'key': 'name', 'type': 'str'},
+ 'type': {'key': 'type', 'type': 'str'},
+ 'etag': {'key': 'etag', 'type': 'str'},
+ 'kind': {'key': 'kind', 'type': 'str'},
+ 'atp_license_status': {'key': 'properties.atpLicenseStatus', 'type': 'str'},
+ 'is_enabled': {'key': 'properties.isEnabled', 'type': 'bool'},
+ 'status_in_mcas': {'key': 'properties.statusInMcas', 'type': 'str'},
+ }
+
+ def __init__(
+ self,
+ *,
+ etag: Optional[str] = None,
+ is_enabled: Optional[bool] = None,
+ **kwargs
+ ):
+ super(UebaSettings, self).__init__(etag=etag, **kwargs)
+ self.kind = 'UebaSettings' # type: str
+ self.atp_license_status = None
+ self.is_enabled = is_enabled
+ self.status_in_mcas = None
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_security_insights_enums.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_security_insights_enums.py
new file mode 100644
index 00000000000..ff1e2d1db57
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/models/_security_insights_enums.py
@@ -0,0 +1,182 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from enum import Enum, EnumMeta
+from six import with_metaclass
+
+class _CaseInsensitiveEnumMeta(EnumMeta):
+ def __getitem__(self, name):
+ return super().__getitem__(name.upper())
+
+ def __getattr__(cls, name):
+ """Return the enum member matching `name`
+ We use __getattr__ instead of descriptors or inserting into the enum
+ class' __dict__ in order to support `name` and `value` being both
+ properties for enum members (which live in the class' __dict__) and
+ enum members themselves.
+ """
+ try:
+ return cls._member_map_[name.upper()]
+ except KeyError:
+ raise AttributeError(name)
+
+
+class AlertRuleKind(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The kind of the alert rule
+ """
+
+ SCHEDULED = "Scheduled"
+ MICROSOFT_SECURITY_INCIDENT_CREATION = "MicrosoftSecurityIncidentCreation"
+ FUSION = "Fusion"
+
+class AlertSeverity(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The severity of the alert
+ """
+
+ HIGH = "High" #: High severity.
+ MEDIUM = "Medium" #: Medium severity.
+ LOW = "Low" #: Low severity.
+ INFORMATIONAL = "Informational" #: Informational severity.
+
+class AttackTactic(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The severity for alerts created by this alert rule.
+ """
+
+ INITIAL_ACCESS = "InitialAccess"
+ EXECUTION = "Execution"
+ PERSISTENCE = "Persistence"
+ PRIVILEGE_ESCALATION = "PrivilegeEscalation"
+ DEFENSE_EVASION = "DefenseEvasion"
+ CREDENTIAL_ACCESS = "CredentialAccess"
+ DISCOVERY = "Discovery"
+ LATERAL_MOVEMENT = "LateralMovement"
+ COLLECTION = "Collection"
+ EXFILTRATION = "Exfiltration"
+ COMMAND_AND_CONTROL = "CommandAndControl"
+ IMPACT = "Impact"
+
+class CaseSeverity(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The severity of the incident
+ """
+
+ CRITICAL = "Critical" #: Critical severity.
+ HIGH = "High" #: High severity.
+ MEDIUM = "Medium" #: Medium severity.
+ LOW = "Low" #: Low severity.
+ INFORMATIONAL = "Informational" #: Informational severity.
+
+class DataConnectorKind(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The kind of the data connector
+ """
+
+ AZURE_ACTIVE_DIRECTORY = "AzureActiveDirectory"
+ AZURE_SECURITY_CENTER = "AzureSecurityCenter"
+ MICROSOFT_CLOUD_APP_SECURITY = "MicrosoftCloudAppSecurity"
+ THREAT_INTELLIGENCE = "ThreatIntelligence"
+ OFFICE365 = "Office365"
+ AMAZON_WEB_SERVICES_CLOUD_TRAIL = "AmazonWebServicesCloudTrail"
+ AZURE_ADVANCED_THREAT_PROTECTION = "AzureAdvancedThreatProtection"
+ MICROSOFT_DEFENDER_ADVANCED_THREAT_PROTECTION = "MicrosoftDefenderAdvancedThreatProtection"
+
+class DataTypeState(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """Describe whether this data type connection is enabled or not.
+ """
+
+ ENABLED = "Enabled"
+ DISABLED = "Disabled"
+
+class IncidentClassification(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The reason the incident was closed
+ """
+
+ UNDETERMINED = "Undetermined" #: Incident classification was undetermined.
+ TRUE_POSITIVE = "TruePositive" #: Incident was true positive.
+ BENIGN_POSITIVE = "BenignPositive" #: Incident was benign positive.
+ FALSE_POSITIVE = "FalsePositive" #: Incident was false positive.
+
+class IncidentClassificationReason(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The classification reason the incident was closed with
+ """
+
+ SUSPICIOUS_ACTIVITY = "SuspiciousActivity" #: Classification reason was suspicious activity.
+ SUSPICIOUS_BUT_EXPECTED = "SuspiciousButExpected" #: Classification reason was suspicious but expected.
+ INCORRECT_ALERT_LOGIC = "IncorrectAlertLogic" #: Classification reason was incorrect alert logic.
+ INACCURATE_DATA = "InaccurateData" #: Classification reason was inaccurate data.
+
+class IncidentLabelType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The type of the label
+ """
+
+ USER = "User" #: Label manually created by a user.
+ SYSTEM = "System" #: Label automatically created by the system.
+
+class IncidentSeverity(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The severity of the incident
+ """
+
+ HIGH = "High" #: High severity.
+ MEDIUM = "Medium" #: Medium severity.
+ LOW = "Low" #: Low severity.
+ INFORMATIONAL = "Informational" #: Informational severity.
+
+class IncidentStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The status of the incident
+ """
+
+ NEW = "New" #: An active incident which isn't being handled currently.
+ ACTIVE = "Active" #: An active incident which is being handled.
+ CLOSED = "Closed" #: A non-active incident.
+
+class LicenseStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """Determines whether the tenant has ATP (Advanced Threat Protection) license.
+ """
+
+ ENABLED = "Enabled"
+ DISABLED = "Disabled"
+
+class MicrosoftSecurityProductName(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The alerts' productName on which the cases will be generated
+ """
+
+ MICROSOFT_CLOUD_APP_SECURITY = "Microsoft Cloud App Security"
+ AZURE_SECURITY_CENTER = "Azure Security Center"
+ AZURE_ADVANCED_THREAT_PROTECTION = "Azure Advanced Threat Protection"
+ AZURE_ACTIVE_DIRECTORY_IDENTITY_PROTECTION = "Azure Active Directory Identity Protection"
+ AZURE_SECURITY_CENTER_FOR_IO_T = "Azure Security Center for IoT"
+
+class SettingKind(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The kind of the setting
+ """
+
+ UEBA_SETTINGS = "UebaSettings"
+ TOGGLE_SETTINGS = "ToggleSettings"
+
+class StatusInMCAS(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """Determines whether User and Entity Behavior Analytics is enabled from MCAS (Microsoft Cloud App
+ Security).
+ """
+
+ ENABLED = "Enabled"
+ DISABLED = "Disabled"
+
+class TemplateStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The alert rule template status.
+ """
+
+ INSTALLED = "Installed" #: Alert rule template installed. and can not use more then once.
+ AVAILABLE = "Available" #: Alert rule template is available.
+ NOT_AVAILABLE = "NotAvailable" #: Alert rule template is not available.
+
+class TriggerOperator(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
+ """The operation against the threshold that triggers alert rule.
+ """
+
+ GREATER_THAN = "GreaterThan"
+ LESS_THAN = "LessThan"
+ EQUAL = "Equal"
+ NOT_EQUAL = "NotEqual"
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/__init__.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/__init__.py
new file mode 100644
index 00000000000..5e67996dcd4
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/__init__.py
@@ -0,0 +1,27 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+
+from ._operation_operations import OperationOperations
+from ._alert_rule_operations import AlertRuleOperations
+from ._action_operations import ActionOperations
+from ._alert_rule_template_operations import AlertRuleTemplateOperations
+from ._bookmark_operations import BookmarkOperations
+from ._data_connector_operations import DataConnectorOperations
+from ._incident_operations import IncidentOperations
+from ._incident_comment_operations import IncidentCommentOperations
+
+__all__ = [
+ 'OperationOperations',
+ 'AlertRuleOperations',
+ 'ActionOperations',
+ 'AlertRuleTemplateOperations',
+ 'BookmarkOperations',
+ 'DataConnectorOperations',
+ 'IncidentOperations',
+ 'IncidentCommentOperations',
+]
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_action_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_action_operations.py
new file mode 100644
index 00000000000..a0eaa43cf9a
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_action_operations.py
@@ -0,0 +1,126 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class ActionOperations(object):
+ """ActionOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list_by_alert_rule(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.ActionsList"]
+ """Gets all actions of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either ActionsList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.ActionsList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionsList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list_by_alert_rule.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('ActionsList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list_by_alert_rule.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_operations.py
new file mode 100644
index 00000000000..f91eef2b673
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_operations.py
@@ -0,0 +1,546 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar, Union
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class AlertRuleOperations(object):
+ """AlertRuleOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.AlertRulesList"]
+ """Gets all alert rules.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either AlertRulesList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.AlertRulesList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRulesList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('AlertRulesList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.AlertRule"
+ """Gets the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRule, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRule
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRule"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ def create_or_update(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ alert_rule, # type: "models.AlertRule"
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.AlertRule"
+ """Creates or updates the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param alert_rule: The alert rule.
+ :type alert_rule: ~security_insights.models.AlertRule
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRule, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRule
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRule"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(alert_rule, 'AlertRule')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('AlertRule', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ def delete(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ """Delete the alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}'} # type: ignore
+
+ def get_action(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ action_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.ActionResponse"
+ """Gets the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: ActionResponse, or the result of cls(response)
+ :rtype: ~security_insights.models.ActionResponse
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionResponse"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
+
+ def create_or_update_action(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ action_id, # type: str
+ etag=None, # type: Optional[str]
+ logic_app_resource_id=None, # type: Optional[str]
+ trigger_uri=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.ActionResponse"
+ """Creates or updates the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param logic_app_resource_id: Logic App Resource Id, /subscriptions/{my-
+ subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-
+ workflow-id}.
+ :type logic_app_resource_id: str
+ :param trigger_uri: Logic App Callback URL for this specific workflow.
+ :type trigger_uri: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: ActionResponse, or the result of cls(response)
+ :rtype: ~security_insights.models.ActionResponse
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.ActionResponse"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ action = models.ActionRequest(etag=etag, logic_app_resource_id=logic_app_resource_id, trigger_uri=trigger_uri)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(action, 'ActionRequest')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('ActionResponse', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
+
+ def delete_action(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ rule_id, # type: str
+ action_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ """Delete the action of alert rule.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param rule_id: Alert rule ID.
+ :type rule_id: str
+ :param action_id: Action ID.
+ :type action_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete_action.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'ruleId': self._serialize.url("rule_id", rule_id, 'str'),
+ 'actionId': self._serialize.url("action_id", action_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete_action.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRules/{ruleId}/actions/{actionId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_template_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_template_operations.py
new file mode 100644
index 00000000000..2dad458b3f7
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_alert_rule_template_operations.py
@@ -0,0 +1,186 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class AlertRuleTemplateOperations(object):
+ """AlertRuleTemplateOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.AlertRuleTemplatesList"]
+ """Gets all alert rule templates.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either AlertRuleTemplatesList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.AlertRuleTemplatesList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRuleTemplatesList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('AlertRuleTemplatesList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRuleTemplates'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ alert_rule_template_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.AlertRuleTemplate"
+ """Gets the alert rule template.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param alert_rule_template_id: Alert rule template ID.
+ :type alert_rule_template_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: AlertRuleTemplate, or the result of cls(response)
+ :rtype: ~security_insights.models.AlertRuleTemplate
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.AlertRuleTemplate"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'alertRuleTemplateId': self._serialize.url("alert_rule_template_id", alert_rule_template_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('AlertRuleTemplate', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRuleTemplates/{alertRuleTemplateId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_bookmark_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_bookmark_operations.py
new file mode 100644
index 00000000000..0121790c420
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_bookmark_operations.py
@@ -0,0 +1,353 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+import datetime
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, List, Optional, TypeVar, Union
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class BookmarkOperations(object):
+ """BookmarkOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.BookmarkList"]
+ """Gets all bookmarks.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either BookmarkList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.BookmarkList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.BookmarkList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('BookmarkList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ bookmark_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.Bookmark"
+ """Gets a bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Bookmark, or the result of cls(response)
+ :rtype: ~security_insights.models.Bookmark
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Bookmark"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
+
+ def create_or_update(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ bookmark_id, # type: str
+ etag=None, # type: Optional[str]
+ created=None, # type: Optional[datetime.datetime]
+ display_name=None, # type: Optional[str]
+ labels=None, # type: Optional[List[str]]
+ notes=None, # type: Optional[str]
+ query=None, # type: Optional[str]
+ query_result=None, # type: Optional[str]
+ updated=None, # type: Optional[datetime.datetime]
+ incident_info=None, # type: Optional["models.IncidentInfo"]
+ object_id=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.Bookmark"
+ """Creates or updates the bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param created: The time the bookmark was created.
+ :type created: ~datetime.datetime
+ :param display_name: The display name of the bookmark.
+ :type display_name: str
+ :param labels: List of labels relevant to this bookmark.
+ :type labels: list[str]
+ :param notes: The notes of the bookmark.
+ :type notes: str
+ :param query: The query of the bookmark.
+ :type query: str
+ :param query_result: The query result of the bookmark.
+ :type query_result: str
+ :param updated: The last time the bookmark was updated.
+ :type updated: ~datetime.datetime
+ :param incident_info: Describes an incident that relates to bookmark.
+ :type incident_info: ~security_insights.models.IncidentInfo
+ :param object_id: The object id of the user.
+ :type object_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Bookmark, or the result of cls(response)
+ :rtype: ~security_insights.models.Bookmark
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Bookmark"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ bookmark = models.Bookmark(etag=etag, created=created, display_name=display_name, labels=labels, notes=notes, query=query, query_result=query_result, updated=updated, incident_info=incident_info, object_id_updated_by_object_id=object_id)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(bookmark, 'Bookmark')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('Bookmark', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
+
+ def delete(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ bookmark_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ """Delete the bookmark.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param bookmark_id: Bookmark ID.
+ :type bookmark_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'bookmarkId': self._serialize.url("bookmark_id", bookmark_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/bookmarks/{bookmarkId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_data_connector_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_data_connector_operations.py
new file mode 100644
index 00000000000..8fd8df7be38
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_data_connector_operations.py
@@ -0,0 +1,323 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar, Union
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class DataConnectorOperations(object):
+ """DataConnectorOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.DataConnectorList"]
+ """Gets all data connectors.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either DataConnectorList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.DataConnectorList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnectorList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('DataConnectorList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ data_connector_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.DataConnector"
+ """Gets a data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: DataConnector, or the result of cls(response)
+ :rtype: ~security_insights.models.DataConnector
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnector"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
+
+ def create_or_update(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ data_connector_id, # type: str
+ data_connector, # type: "models.DataConnector"
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.DataConnector"
+ """Creates or updates the data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :param data_connector: The data connector.
+ :type data_connector: ~security_insights.models.DataConnector
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: DataConnector, or the result of cls(response)
+ :rtype: ~security_insights.models.DataConnector
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.DataConnector"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(data_connector, 'DataConnector')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('DataConnector', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
+
+ def delete(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ data_connector_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ """Delete the data connector.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param data_connector_id: Connector ID.
+ :type data_connector_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'dataConnectorId': self._serialize.url("data_connector_id", data_connector_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/dataConnectors/{dataConnectorId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_comment_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_comment_operations.py
new file mode 100644
index 00000000000..ebed41e74ae
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_comment_operations.py
@@ -0,0 +1,294 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class IncidentCommentOperations(object):
+ """IncidentCommentOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list_by_incident(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ filter=None, # type: Optional[str]
+ orderby=None, # type: Optional[str]
+ top=None, # type: Optional[int]
+ skip_token=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.IncidentCommentList"]
+ """Gets all incident comments.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param filter: Filters the results, based on a Boolean condition. Optional.
+ :type filter: str
+ :param orderby: Sorts the results. Optional.
+ :type orderby: str
+ :param top: Returns only the first n results. Optional.
+ :type top: int
+ :param skip_token: Skiptoken is only used if a previous operation returned a partial result. If
+ a previous response contains a nextLink element, the value of the nextLink element will include
+ a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.
+ :type skip_token: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either IncidentCommentList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.IncidentCommentList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentCommentList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list_by_incident.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+ if filter is not None:
+ query_parameters['$filter'] = self._serialize.query("filter", filter, 'str')
+ if orderby is not None:
+ query_parameters['$orderby'] = self._serialize.query("orderby", orderby, 'str')
+ if top is not None:
+ query_parameters['$top'] = self._serialize.query("top", top, 'int')
+ if skip_token is not None:
+ query_parameters['$skipToken'] = self._serialize.query("skip_token", skip_token, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('IncidentCommentList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list_by_incident.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ incident_comment_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.IncidentComment"
+ """Gets an incident comment.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param incident_comment_id: Incident comment ID.
+ :type incident_comment_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: IncidentComment, or the result of cls(response)
+ :rtype: ~security_insights.models.IncidentComment
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentComment"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ 'incidentCommentId': self._serialize.url("incident_comment_id", incident_comment_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('IncidentComment', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments/{incidentCommentId}'} # type: ignore
+
+ def create_comment(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ incident_comment_id, # type: str
+ message=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.IncidentComment"
+ """Creates the incident comment.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param incident_comment_id: Incident comment ID.
+ :type incident_comment_id: str
+ :param message: The comment message.
+ :type message: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: IncidentComment, or the result of cls(response)
+ :rtype: ~security_insights.models.IncidentComment
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentComment"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ incident_comment = models.IncidentComment(message=message)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_comment.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ 'incidentCommentId': self._serialize.url("incident_comment_id", incident_comment_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(incident_comment, 'IncidentComment')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('IncidentComment', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_comment.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}/comments/{incidentCommentId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_operations.py
new file mode 100644
index 00000000000..0a2071ac198
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_incident_operations.py
@@ -0,0 +1,381 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+import datetime
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, List, Optional, TypeVar, Union
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class IncidentOperations(object):
+ """IncidentOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ filter=None, # type: Optional[str]
+ orderby=None, # type: Optional[str]
+ top=None, # type: Optional[int]
+ skip_token=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.IncidentList"]
+ """Gets all incidents.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param filter: Filters the results, based on a Boolean condition. Optional.
+ :type filter: str
+ :param orderby: Sorts the results. Optional.
+ :type orderby: str
+ :param top: Returns only the first n results. Optional.
+ :type top: int
+ :param skip_token: Skiptoken is only used if a previous operation returned a partial result. If
+ a previous response contains a nextLink element, the value of the nextLink element will include
+ a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.
+ :type skip_token: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either IncidentList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.IncidentList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.IncidentList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+ if filter is not None:
+ query_parameters['$filter'] = self._serialize.query("filter", filter, 'str')
+ if orderby is not None:
+ query_parameters['$orderby'] = self._serialize.query("orderby", orderby, 'str')
+ if top is not None:
+ query_parameters['$top'] = self._serialize.query("top", top, 'int')
+ if skip_token is not None:
+ query_parameters['$skipToken'] = self._serialize.query("skip_token", skip_token, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('IncidentList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents'} # type: ignore
+
+ def get(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.Incident"
+ """Gets an incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Incident, or the result of cls(response)
+ :rtype: ~security_insights.models.Incident
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Incident"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.get.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ get.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
+
+ def create_or_update(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ etag=None, # type: Optional[str]
+ classification=None, # type: Optional[Union[str, "models.IncidentClassification"]]
+ classification_comment=None, # type: Optional[str]
+ classification_reason=None, # type: Optional[Union[str, "models.IncidentClassificationReason"]]
+ description=None, # type: Optional[str]
+ first_activity_time_utc=None, # type: Optional[datetime.datetime]
+ labels=None, # type: Optional[List["models.IncidentLabel"]]
+ last_activity_time_utc=None, # type: Optional[datetime.datetime]
+ owner=None, # type: Optional["models.IncidentOwnerInfo"]
+ severity=None, # type: Optional[Union[str, "models.IncidentSeverity"]]
+ status=None, # type: Optional[Union[str, "models.IncidentStatus"]]
+ title=None, # type: Optional[str]
+ **kwargs # type: Any
+ ):
+ # type: (...) -> "models.Incident"
+ """Creates or updates the incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :param etag: Etag of the azure resource.
+ :type etag: str
+ :param classification: The reason the incident was closed.
+ :type classification: str or ~security_insights.models.IncidentClassification
+ :param classification_comment: Describes the reason the incident was closed.
+ :type classification_comment: str
+ :param classification_reason: The classification reason the incident was closed with.
+ :type classification_reason: str or ~security_insights.models.IncidentClassificationReason
+ :param description: The description of the incident.
+ :type description: str
+ :param first_activity_time_utc: The time of the first activity in the incident.
+ :type first_activity_time_utc: ~datetime.datetime
+ :param labels: List of labels relevant to this incident.
+ :type labels: list[~security_insights.models.IncidentLabel]
+ :param last_activity_time_utc: The time of the last activity in the incident.
+ :type last_activity_time_utc: ~datetime.datetime
+ :param owner: Describes a user that the incident is assigned to.
+ :type owner: ~security_insights.models.IncidentOwnerInfo
+ :param severity: The severity of the incident.
+ :type severity: str or ~security_insights.models.IncidentSeverity
+ :param status: The status of the incident.
+ :type status: str or ~security_insights.models.IncidentStatus
+ :param title: The title of the incident.
+ :type title: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: Incident, or the result of cls(response)
+ :rtype: ~security_insights.models.Incident
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.Incident"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+
+ incident = models.Incident(etag=etag, classification=classification, classification_comment=classification_comment, classification_reason=classification_reason, description=description, first_activity_time_utc=first_activity_time_utc, labels=labels, last_activity_time_utc=last_activity_time_utc, owner=owner, severity=severity, status=status, title=title)
+ api_version = "2020-01-01"
+ content_type = kwargs.pop("content_type", "application/json")
+ accept = "application/json"
+
+ # Construct URL
+ url = self.create_or_update.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ body_content_kwargs = {} # type: Dict[str, Any]
+ body_content = self._serialize.body(incident, 'Incident')
+ body_content_kwargs['content'] = body_content
+ request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 201]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if response.status_code == 200:
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if response.status_code == 201:
+ deserialized = self._deserialize('Incident', pipeline_response)
+
+ if cls:
+ return cls(pipeline_response, deserialized, {})
+
+ return deserialized
+ create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
+
+ def delete(
+ self,
+ resource_group_name, # type: str
+ workspace_name, # type: str
+ incident_id, # type: str
+ **kwargs # type: Any
+ ):
+ # type: (...) -> None
+ """Delete the incident.
+
+ :param resource_group_name: The name of the resource group within the user's subscription. The
+ name is case insensitive.
+ :type resource_group_name: str
+ :param workspace_name: The name of the workspace.
+ :type workspace_name: str
+ :param incident_id: Incident ID.
+ :type incident_id: str
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: None, or the result of cls(response)
+ :rtype: None
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType[None]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ # Construct URL
+ url = self.delete.metadata['url'] # type: ignore
+ path_format_arguments = {
+ 'subscriptionId': self._serialize.url("self._config.subscription_id", self._config.subscription_id, 'str', pattern=r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'),
+ 'resourceGroupName': self._serialize.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
+ 'workspaceName': self._serialize.url("workspace_name", workspace_name, 'str', max_length=90, min_length=1),
+ 'incidentId': self._serialize.url("incident_id", incident_id, 'str'),
+ }
+ url = self._client.format_url(url, **path_format_arguments)
+
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ request = self._client.delete(url, query_parameters, header_parameters)
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 204]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ if cls:
+ return cls(pipeline_response, None, {})
+
+ delete.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/incidents/{incidentId}'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_operation_operations.py b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_operation_operations.py
new file mode 100644
index 00000000000..b1d3c09bbf3
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/operations/_operation_operations.py
@@ -0,0 +1,109 @@
+# coding=utf-8
+# --------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# Code generated by Microsoft (R) AutoRest Code Generator.
+# Changes may cause incorrect behavior and will be lost if the code is regenerated.
+# --------------------------------------------------------------------------
+from typing import TYPE_CHECKING
+import warnings
+
+from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
+from azure.core.paging import ItemPaged
+from azure.core.pipeline import PipelineResponse
+from azure.core.pipeline.transport import HttpRequest, HttpResponse
+from azure.mgmt.core.exceptions import ARMErrorFormat
+
+from .. import models
+
+if TYPE_CHECKING:
+ # pylint: disable=unused-import,ungrouped-imports
+ from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar
+
+ T = TypeVar('T')
+ ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
+
+class OperationOperations(object):
+ """OperationOperations operations.
+
+ You should not instantiate this class directly. Instead, you should create a Client instance that
+ instantiates it for you and attaches it as an attribute.
+
+ :ivar models: Alias to model classes used in this operation group.
+ :type models: ~security_insights.models
+ :param client: Client for service requests.
+ :param config: Configuration of service client.
+ :param serializer: An object model serializer.
+ :param deserializer: An object model deserializer.
+ """
+
+ models = models
+
+ def __init__(self, client, config, serializer, deserializer):
+ self._client = client
+ self._serialize = serializer
+ self._deserialize = deserializer
+ self._config = config
+
+ def list(
+ self,
+ **kwargs # type: Any
+ ):
+ # type: (...) -> Iterable["models.OperationsList"]
+ """Lists all operations available Azure Security Insights Resource Provider.
+
+ :keyword callable cls: A custom type or function that will be passed the direct response
+ :return: An iterator like instance of either OperationsList or the result of cls(response)
+ :rtype: ~azure.core.paging.ItemPaged[~security_insights.models.OperationsList]
+ :raises: ~azure.core.exceptions.HttpResponseError
+ """
+ cls = kwargs.pop('cls', None) # type: ClsType["models.OperationsList"]
+ error_map = {
+ 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
+ }
+ error_map.update(kwargs.pop('error_map', {}))
+ api_version = "2020-01-01"
+ accept = "application/json"
+
+ def prepare_request(next_link=None):
+ # Construct headers
+ header_parameters = {} # type: Dict[str, Any]
+ header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')
+
+ if not next_link:
+ # Construct URL
+ url = self.list.metadata['url'] # type: ignore
+ # Construct parameters
+ query_parameters = {} # type: Dict[str, Any]
+ query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str')
+
+ request = self._client.get(url, query_parameters, header_parameters)
+ else:
+ url = next_link
+ query_parameters = {} # type: Dict[str, Any]
+ request = self._client.get(url, query_parameters, header_parameters)
+ return request
+
+ def extract_data(pipeline_response):
+ deserialized = self._deserialize('OperationsList', pipeline_response)
+ list_of_elem = deserialized.value
+ if cls:
+ list_of_elem = cls(list_of_elem)
+ return deserialized.next_link or None, iter(list_of_elem)
+
+ def get_next(next_link=None):
+ request = prepare_request(next_link)
+
+ pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ map_error(status_code=response.status_code, response=response, error_map=error_map)
+ raise HttpResponseError(response=response, error_format=ARMErrorFormat)
+
+ return pipeline_response
+
+ return ItemPaged(
+ get_next, extract_data
+ )
+ list.metadata = {'url': '/providers/Microsoft.SecurityInsights/operations'} # type: ignore
diff --git a/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/py.typed b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/py.typed
new file mode 100644
index 00000000000..e5aff4f83af
--- /dev/null
+++ b/src/securityinsight/azext_sentinel/vendored_sdks/securityinsight/py.typed
@@ -0,0 +1 @@
+# Marker file for PEP 561.
\ No newline at end of file
diff --git a/src/securityinsight/gen.zip b/src/securityinsight/gen.zip
new file mode 100644
index 00000000000..a6dbc93f1dd
Binary files /dev/null and b/src/securityinsight/gen.zip differ
diff --git a/src/securityinsight/report.md b/src/securityinsight/report.md
new file mode 100644
index 00000000000..d2f533d3f36
--- /dev/null
+++ b/src/securityinsight/report.md
@@ -0,0 +1,610 @@
+# Azure CLI Module Creation Report
+
+## EXTENSION
+|CLI Extension|Command Groups|
+|---------|------------|
+|az sentinel|[groups](#CommandGroups)
+
+## GROUPS
+### Command groups in `az sentinel` extension
+|CLI Command Group|Group Swagger name|Commands|
+|---------|------------|--------|
+|az sentinel alert-rule|AlertRules|[commands](#CommandsInAlertRules)|
+|az sentinel action|Actions|[commands](#CommandsInActions)|
+|az sentinel alert-rule-template|AlertRuleTemplates|[commands](#CommandsInAlertRuleTemplates)|
+|az sentinel bookmark|Bookmarks|[commands](#CommandsInBookmarks)|
+|az sentinel data-connector|DataConnectors|[commands](#CommandsInDataConnectors)|
+|az sentinel incident|Incidents|[commands](#CommandsInIncidents)|
+|az sentinel incident-comment|IncidentComments|[commands](#CommandsInIncidentComments)|
+
+## COMMANDS
+### Commands in `az sentinel action` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel action list](#ActionsListByAlertRule)|ListByAlertRule|[Parameters](#ParametersActionsListByAlertRule)|[Example](#ExamplesActionsListByAlertRule)|
+
+### Commands in `az sentinel alert-rule` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel alert-rule list](#AlertRulesList)|List|[Parameters](#ParametersAlertRulesList)|[Example](#ExamplesAlertRulesList)|
+|[az sentinel alert-rule show](#AlertRulesGet)|Get|[Parameters](#ParametersAlertRulesGet)|[Example](#ExamplesAlertRulesGet)|
+|[az sentinel alert-rule create](#AlertRulesCreateOrUpdateAction)|CreateOrUpdateAction|[Parameters](#ParametersAlertRulesCreateOrUpdateAction)|[Example](#ExamplesAlertRulesCreateOrUpdateAction)|
+|[az sentinel alert-rule create](#AlertRulesCreateOrUpdate#Create)|CreateOrUpdate#Create|[Parameters](#ParametersAlertRulesCreateOrUpdate#Create)|[Example](#ExamplesAlertRulesCreateOrUpdate#Create)|
+|[az sentinel alert-rule update](#AlertRulesCreateOrUpdate#Update)|CreateOrUpdate#Update|[Parameters](#ParametersAlertRulesCreateOrUpdate#Update)|Not Found|
+|[az sentinel alert-rule delete](#AlertRulesDeleteAction)|DeleteAction|[Parameters](#ParametersAlertRulesDeleteAction)|[Example](#ExamplesAlertRulesDeleteAction)|
+|[az sentinel alert-rule delete](#AlertRulesDelete)|Delete|[Parameters](#ParametersAlertRulesDelete)|[Example](#ExamplesAlertRulesDelete)|
+|[az sentinel alert-rule get-action](#AlertRulesGetAction)|GetAction|[Parameters](#ParametersAlertRulesGetAction)|[Example](#ExamplesAlertRulesGetAction)|
+
+### Commands in `az sentinel alert-rule-template` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel alert-rule-template list](#AlertRuleTemplatesList)|List|[Parameters](#ParametersAlertRuleTemplatesList)|[Example](#ExamplesAlertRuleTemplatesList)|
+|[az sentinel alert-rule-template show](#AlertRuleTemplatesGet)|Get|[Parameters](#ParametersAlertRuleTemplatesGet)|[Example](#ExamplesAlertRuleTemplatesGet)|
+
+### Commands in `az sentinel bookmark` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel bookmark list](#BookmarksList)|List|[Parameters](#ParametersBookmarksList)|[Example](#ExamplesBookmarksList)|
+|[az sentinel bookmark show](#BookmarksGet)|Get|[Parameters](#ParametersBookmarksGet)|[Example](#ExamplesBookmarksGet)|
+|[az sentinel bookmark create](#BookmarksCreateOrUpdate#Create)|CreateOrUpdate#Create|[Parameters](#ParametersBookmarksCreateOrUpdate#Create)|[Example](#ExamplesBookmarksCreateOrUpdate#Create)|
+|[az sentinel bookmark update](#BookmarksCreateOrUpdate#Update)|CreateOrUpdate#Update|[Parameters](#ParametersBookmarksCreateOrUpdate#Update)|Not Found|
+|[az sentinel bookmark delete](#BookmarksDelete)|Delete|[Parameters](#ParametersBookmarksDelete)|[Example](#ExamplesBookmarksDelete)|
+
+### Commands in `az sentinel data-connector` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel data-connector list](#DataConnectorsList)|List|[Parameters](#ParametersDataConnectorsList)|[Example](#ExamplesDataConnectorsList)|
+|[az sentinel data-connector show](#DataConnectorsGet)|Get|[Parameters](#ParametersDataConnectorsGet)|[Example](#ExamplesDataConnectorsGet)|
+|[az sentinel data-connector create](#DataConnectorsCreateOrUpdate#Create)|CreateOrUpdate#Create|[Parameters](#ParametersDataConnectorsCreateOrUpdate#Create)|[Example](#ExamplesDataConnectorsCreateOrUpdate#Create)|
+|[az sentinel data-connector update](#DataConnectorsCreateOrUpdate#Update)|CreateOrUpdate#Update|[Parameters](#ParametersDataConnectorsCreateOrUpdate#Update)|Not Found|
+|[az sentinel data-connector delete](#DataConnectorsDelete)|Delete|[Parameters](#ParametersDataConnectorsDelete)|[Example](#ExamplesDataConnectorsDelete)|
+
+### Commands in `az sentinel incident` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel incident list](#IncidentsList)|List|[Parameters](#ParametersIncidentsList)|[Example](#ExamplesIncidentsList)|
+|[az sentinel incident show](#IncidentsGet)|Get|[Parameters](#ParametersIncidentsGet)|[Example](#ExamplesIncidentsGet)|
+|[az sentinel incident create](#IncidentsCreateOrUpdate#Create)|CreateOrUpdate#Create|[Parameters](#ParametersIncidentsCreateOrUpdate#Create)|[Example](#ExamplesIncidentsCreateOrUpdate#Create)|
+|[az sentinel incident update](#IncidentsCreateOrUpdate#Update)|CreateOrUpdate#Update|[Parameters](#ParametersIncidentsCreateOrUpdate#Update)|Not Found|
+|[az sentinel incident delete](#IncidentsDelete)|Delete|[Parameters](#ParametersIncidentsDelete)|[Example](#ExamplesIncidentsDelete)|
+
+### Commands in `az sentinel incident-comment` group
+|CLI Command|Operation Swagger name|Parameters|Examples|
+|---------|------------|--------|-----------|
+|[az sentinel incident-comment list](#IncidentCommentsListByIncident)|ListByIncident|[Parameters](#ParametersIncidentCommentsListByIncident)|[Example](#ExamplesIncidentCommentsListByIncident)|
+|[az sentinel incident-comment show](#IncidentCommentsGet)|Get|[Parameters](#ParametersIncidentCommentsGet)|[Example](#ExamplesIncidentCommentsGet)|
+|[az sentinel incident-comment create](#IncidentCommentsCreateComment)|CreateComment|[Parameters](#ParametersIncidentCommentsCreateComment)|[Example](#ExamplesIncidentCommentsCreateComment)|
+
+
+## COMMAND DETAILS
+
+### group `az sentinel action`
+#### Command `az sentinel action list`
+
+##### Example
+```
+az sentinel action list --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name \
+"myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+
+### group `az sentinel alert-rule`
+#### Command `az sentinel alert-rule list`
+
+##### Example
+```
+az sentinel alert-rule list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+
+#### Command `az sentinel alert-rule show`
+
+##### Example
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "myFirstFusionRule" --workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "microsoftSecurityIncidentCreationRuleExample" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel alert-rule show --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name \
+"myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+
+#### Command `az sentinel alert-rule create`
+
+##### Example
+```
+az sentinel alert-rule create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --logic-app-resource-id \
+"/subscriptions/d0cfe6b2-9ac0-4464-9919-dccaee2e48c0/resourceGroups/myRg/providers/Microsoft.Logic/workflows/MyAlerts" \
+--trigger-uri "https://prod-31.northcentralus.logic.azure.com:443/workflows/cd3765391efd48549fd7681ded1d48d7/triggers/m\
+anual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=signature" --action-id \
+"912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+|**--action-id**|string|Action ID|action_id|actionId|
+|**--etag**|string|Etag of the azure resource|etag|etag|
+|**--logic-app-resource-id**|string|Logic App Resource Id, /subscriptions/{my-subscription}/resourceGroups/{my-resource-group}/providers/Microsoft.Logic/workflows/{my-workflow-id}.|logic_app_resource_id|logicAppResourceId|
+|**--trigger-uri**|string|Logic App Callback URL for this specific workflow.|trigger_uri|triggerUri|
+
+#### Command `az sentinel alert-rule create`
+
+##### Example
+```
+az sentinel alert-rule create --fusion-alert-rule etag="3d00c3ca-0000-0100-0000-5d42d5010000" \
+alert-rule-template-name="f71aba3d-28fb-450b-b192-4e76a83015c8" enabled=true --resource-group "myRg" --rule-id \
+"myFirstFusionRule" --workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel alert-rule create --microsoft-security-incident-creation-alert-rule etag="\\"260097e0-0000-0d00-0000-5d6fa8\
+8f0000\\"" product-filter="Microsoft Cloud App Security" display-name="testing displayname" enabled=true \
+--resource-group "myRg" --rule-id "microsoftSecurityIncidentCreationRuleExample" --workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel alert-rule create --scheduled-alert-rule etag="\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+query="ProtectionStatus | extend HostCustomEntity = Computer | extend IPCustomEntity = ComputerIP_Hidden" \
+query-frequency="PT1H" query-period="P2DT1H30M" severity="High" trigger-operator="GreaterThan" trigger-threshold=0 \
+description="" display-name="Rule2" enabled=true suppression-duration="PT1H" suppression-enabled=false \
+tactics="Persistence" tactics="LateralMovement" --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5\
+" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--fusion-alert-rule**|object|Represents Fusion alert rule.|fusion_alert_rule|FusionAlertRule|
+|**--microsoft-security-incident-creation-alert-rule**|object|Represents MicrosoftSecurityIncidentCreation rule.|microsoft_security_incident_creation_alert_rule|MicrosoftSecurityIncidentCreationAlertRule|
+|**--scheduled-alert-rule**|object|Represents scheduled alert rule.|scheduled_alert_rule|ScheduledAlertRule|
+
+#### Command `az sentinel alert-rule update`
+
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+|**--fusion-alert-rule**|object|Represents Fusion alert rule.|fusion_alert_rule|FusionAlertRule|
+|**--microsoft-security-incident-creation-alert-rule**|object|Represents MicrosoftSecurityIncidentCreation rule.|microsoft_security_incident_creation_alert_rule|MicrosoftSecurityIncidentCreationAlertRule|
+|**--scheduled-alert-rule**|object|Represents scheduled alert rule.|scheduled_alert_rule|ScheduledAlertRule|
+
+#### Command `az sentinel alert-rule delete`
+
+##### Example
+```
+az sentinel alert-rule delete --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" --rule-id \
+"73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+|**--action-id**|string|Action ID|action_id|actionId|
+
+#### Command `az sentinel alert-rule delete`
+
+##### Example
+```
+az sentinel alert-rule delete --resource-group "myRg" --rule-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+#### Command `az sentinel alert-rule get-action`
+
+##### Example
+```
+az sentinel alert-rule get-action --action-id "912bec42-cb66-4c03-ac63-1761b6898c3e" --resource-group "myRg" --rule-id \
+"73e01a99-5cd7-4139-a149-9f2736ff2ab5" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--rule-id**|string|Alert rule ID|rule_id|ruleId|
+|**--action-id**|string|Action ID|action_id|actionId|
+
+### group `az sentinel alert-rule-template`
+#### Command `az sentinel alert-rule-template list`
+
+##### Example
+```
+az sentinel alert-rule-template list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+
+#### Command `az sentinel alert-rule-template show`
+
+##### Example
+```
+az sentinel alert-rule-template show --alert-rule-template-id "65360bb0-8986-4ade-a89d-af3cf44d28aa" --resource-group \
+"myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--alert-rule-template-id**|string|Alert rule template ID|alert_rule_template_id|alertRuleTemplateId|
+
+### group `az sentinel bookmark`
+#### Command `az sentinel bookmark list`
+
+##### Example
+```
+az sentinel bookmark list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+
+#### Command `az sentinel bookmark show`
+
+##### Example
+```
+az sentinel bookmark show --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--bookmark-id**|string|Bookmark ID|bookmark_id|bookmarkId|
+
+#### Command `az sentinel bookmark create`
+
+##### Example
+```
+az sentinel bookmark create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --created "2019-01-01T13:15:30Z" \
+--display-name "My bookmark" --labels "Tag1" --labels "Tag2" --notes "Found a suspicious activity" --query \
+"SecurityEvent | where TimeGenerated > ago(1d) and TimeGenerated < ago(2d)" --query-result "Security Event query \
+result" --updated "2019-01-01T13:15:30Z" --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--bookmark-id**|string|Bookmark ID|bookmark_id|bookmarkId|
+|**--etag**|string|Etag of the azure resource|etag|etag|
+|**--created**|date-time|The time the bookmark was created|created|created|
+|**--display-name**|string|The display name of the bookmark|display_name|displayName|
+|**--labels**|array|List of labels relevant to this bookmark|labels|labels|
+|**--notes**|string|The notes of the bookmark|notes|notes|
+|**--query**|string|The query of the bookmark.|query|query|
+|**--query-result**|string|The query result of the bookmark.|query_result|queryResult|
+|**--updated**|date-time|The last time the bookmark was updated|updated|updated|
+|**--incident-info**|object|Describes an incident that relates to bookmark|incident_info|incidentInfo|
+|**--updated-by-object-id**|uuid|The object id of the user.|object_id|objectId|
+
+#### Command `az sentinel bookmark update`
+
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--bookmark-id**|string|Bookmark ID|bookmark_id|bookmarkId|
+|**--etag**|string|Etag of the azure resource|etag|etag|
+|**--created**|date-time|The time the bookmark was created|created|created|
+|**--display-name**|string|The display name of the bookmark|display_name|displayName|
+|**--labels**|array|List of labels relevant to this bookmark|labels|labels|
+|**--notes**|string|The notes of the bookmark|notes|notes|
+|**--query**|string|The query of the bookmark.|query|query|
+|**--query-result**|string|The query result of the bookmark.|query_result|queryResult|
+|**--updated**|date-time|The last time the bookmark was updated|updated|updated|
+|**--incident-info**|object|Describes an incident that relates to bookmark|incident_info|incidentInfo|
+|**--updated-by-object-id**|uuid|The object id of the user.|object_id|objectId|
+
+#### Command `az sentinel bookmark delete`
+
+##### Example
+```
+az sentinel bookmark delete --bookmark-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--bookmark-id**|string|Bookmark ID|bookmark_id|bookmarkId|
+
+### group `az sentinel data-connector`
+#### Command `az sentinel data-connector list`
+
+##### Example
+```
+az sentinel data-connector list --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+
+#### Command `az sentinel data-connector show`
+
+##### Example
+```
+az sentinel data-connector show --data-connector-id "763f9fa1-c2d3-4fa2-93e9-bccd4899aa12" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "b96d014d-b5c2-4a01-9aba-a8058f629d42" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "06b3ccb8-1384-4bcc-aec7-852f6d57161b" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "f0cd27d2-5f03-4c06-ba31-d2dc82dcb51d" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "07e42cb3-e658-4e90-801c-efa0f29d3d44" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "c345bf40-8509-4ed2-b947-50cb773aaf04" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Example
+```
+az sentinel data-connector show --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--data-connector-id**|string|Connector ID|data_connector_id|dataConnectorId|
+
+#### Command `az sentinel data-connector create`
+
+##### Example
+```
+az sentinel data-connector create --office-data-connector etag="\\"0300bf09-0000-0000-0000-5c37296e0000\\"" \
+tenant-id="2070ecc9-b4d5-4ae4-adaa-936fa1954fa8" --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" \
+--resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--data-connector-id**|string|Connector ID|data_connector_id|dataConnectorId|
+|**--aad-data-connector**|object|Represents AAD (Azure Active Directory) data connector.|aad_data_connector|AADDataConnector|
+|**--aatp-data-connector**|object|Represents AATP (Azure Advanced Threat Protection) data connector.|aatp_data_connector|AATPDataConnector|
+|**--asc-data-connector**|object|Represents ASC (Azure Security Center) data connector.|asc_data_connector|ASCDataConnector|
+|**--aws-cloud-trail-data-connector**|object|Represents Amazon Web Services CloudTrail data connector.|aws_cloud_trail_data_connector|AwsCloudTrailDataConnector|
+|**--mcas-data-connector**|object|Represents MCAS (Microsoft Cloud App Security) data connector.|mcas_data_connector|MCASDataConnector|
+|**--mdatp-data-connector**|object|Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector.|mdatp_data_connector|MDATPDataConnector|
+|**--office-data-connector**|object|Represents office data connector.|office_data_connector|OfficeDataConnector|
+|**--ti-data-connector**|object|Represents threat intelligence data connector.|ti_data_connector|TIDataConnector|
+
+#### Command `az sentinel data-connector update`
+
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--data-connector-id**|string|Connector ID|data_connector_id|dataConnectorId|
+|**--aad-data-connector**|object|Represents AAD (Azure Active Directory) data connector.|aad_data_connector|AADDataConnector|
+|**--aatp-data-connector**|object|Represents AATP (Azure Advanced Threat Protection) data connector.|aatp_data_connector|AATPDataConnector|
+|**--asc-data-connector**|object|Represents ASC (Azure Security Center) data connector.|asc_data_connector|ASCDataConnector|
+|**--aws-cloud-trail-data-connector**|object|Represents Amazon Web Services CloudTrail data connector.|aws_cloud_trail_data_connector|AwsCloudTrailDataConnector|
+|**--mcas-data-connector**|object|Represents MCAS (Microsoft Cloud App Security) data connector.|mcas_data_connector|MCASDataConnector|
+|**--mdatp-data-connector**|object|Represents MDATP (Microsoft Defender Advanced Threat Protection) data connector.|mdatp_data_connector|MDATPDataConnector|
+|**--office-data-connector**|object|Represents office data connector.|office_data_connector|OfficeDataConnector|
+|**--ti-data-connector**|object|Represents threat intelligence data connector.|ti_data_connector|TIDataConnector|
+
+#### Command `az sentinel data-connector delete`
+
+##### Example
+```
+az sentinel data-connector delete --data-connector-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--data-connector-id**|string|Connector ID|data_connector_id|dataConnectorId|
+
+### group `az sentinel incident`
+#### Command `az sentinel incident list`
+
+##### Example
+```
+az sentinel incident list --orderby "properties/createdTimeUtc desc" --top 1 --resource-group "myRg" --workspace-name \
+"myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--filter**|string|Filters the results, based on a Boolean condition. Optional.|filter|$filter|
+|**--orderby**|string|Sorts the results. Optional.|orderby|$orderby|
+|**--top**|integer|Returns only the first n results. Optional.|top|$top|
+|**--skip-token**|string|Skiptoken is only used if a previous operation returned a partial result. If a previous response contains a nextLink element, the value of the nextLink element will include a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.|skip_token|$skipToken|
+
+#### Command `az sentinel incident show`
+
+##### Example
+```
+az sentinel incident show --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+
+#### Command `az sentinel incident create`
+
+##### Example
+```
+az sentinel incident create --etag "\\"0300bf09-0000-0000-0000-5c37296e0000\\"" --description "This is a demo \
+incident" --classification "FalsePositive" --classification-comment "Not a malicious activity" --classification-reason \
+"IncorrectAlertLogic" --first-activity-time-utc "2019-01-01T13:00:30Z" --last-activity-time-utc "2019-01-01T13:05:30Z" \
+--owner object-id="2046feea-040d-4a46-9e2b-91c2941bfa70" --severity "High" --status "Closed" --title "My incident" \
+--incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+|**--etag**|string|Etag of the azure resource|etag|etag|
+|**--classification**|choice|The reason the incident was closed|classification|classification|
+|**--classification-comment**|string|Describes the reason the incident was closed|classification_comment|classificationComment|
+|**--classification-reason**|choice|The classification reason the incident was closed with|classification_reason|classificationReason|
+|**--description**|string|The description of the incident|description|description|
+|**--first-activity-time-utc**|date-time|The time of the first activity in the incident|first_activity_time_utc|firstActivityTimeUtc|
+|**--labels**|array|List of labels relevant to this incident|labels|labels|
+|**--last-activity-time-utc**|date-time|The time of the last activity in the incident|last_activity_time_utc|lastActivityTimeUtc|
+|**--owner**|object|Describes a user that the incident is assigned to|owner|owner|
+|**--severity**|choice|The severity of the incident|severity|severity|
+|**--status**|choice|The status of the incident|status|status|
+|**--title**|string|The title of the incident|title|title|
+
+#### Command `az sentinel incident update`
+
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+|**--etag**|string|Etag of the azure resource|etag|etag|
+|**--classification**|choice|The reason the incident was closed|classification|classification|
+|**--classification-comment**|string|Describes the reason the incident was closed|classification_comment|classificationComment|
+|**--classification-reason**|choice|The classification reason the incident was closed with|classification_reason|classificationReason|
+|**--description**|string|The description of the incident|description|description|
+|**--first-activity-time-utc**|date-time|The time of the first activity in the incident|first_activity_time_utc|firstActivityTimeUtc|
+|**--labels**|array|List of labels relevant to this incident|labels|labels|
+|**--last-activity-time-utc**|date-time|The time of the last activity in the incident|last_activity_time_utc|lastActivityTimeUtc|
+|**--owner**|object|Describes a user that the incident is assigned to|owner|owner|
+|**--severity**|choice|The severity of the incident|severity|severity|
+|**--status**|choice|The status of the incident|status|status|
+|**--title**|string|The title of the incident|title|title|
+
+#### Command `az sentinel incident delete`
+
+##### Example
+```
+az sentinel incident delete --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+
+### group `az sentinel incident-comment`
+#### Command `az sentinel incident-comment list`
+
+##### Example
+```
+az sentinel incident-comment list --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" \
+--workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+|**--filter**|string|Filters the results, based on a Boolean condition. Optional.|filter|$filter|
+|**--orderby**|string|Sorts the results. Optional.|orderby|$orderby|
+|**--top**|integer|Returns only the first n results. Optional.|top|$top|
+|**--skip-token**|string|Skiptoken is only used if a previous operation returned a partial result. If a previous response contains a nextLink element, the value of the nextLink element will include a skiptoken parameter that specifies a starting point to use for subsequent calls. Optional.|skip_token|$skipToken|
+
+#### Command `az sentinel incident-comment show`
+
+##### Example
+```
+az sentinel incident-comment show --incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da0014" --incident-id \
+"73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+|**--incident-comment-id**|string|Incident comment ID|incident_comment_id|incidentCommentId|
+
+#### Command `az sentinel incident-comment create`
+
+##### Example
+```
+az sentinel incident-comment create --message "Some message" --incident-comment-id "4bb36b7b-26ff-4d1c-9cbe-0d8ab3da001\
+4" --incident-id "73e01a99-5cd7-4139-a149-9f2736ff2ab5" --resource-group "myRg" --workspace-name "myWorkspace"
+```
+##### Parameters
+|Option|Type|Description|Path (SDK)|Swagger name|
+|------|----|-----------|----------|------------|
+|**--resource-group-name**|string|The name of the resource group within the user's subscription. The name is case insensitive.|resource_group_name|resourceGroupName|
+|**--workspace-name**|string|The name of the workspace.|workspace_name|workspaceName|
+|**--incident-id**|string|Incident ID|incident_id|incidentId|
+|**--incident-comment-id**|string|Incident comment ID|incident_comment_id|incidentCommentId|
+|**--message**|string|The comment message|message|message|
diff --git a/src/securityinsight/setup.cfg b/src/securityinsight/setup.cfg
new file mode 100644
index 00000000000..2fdd96e5d39
--- /dev/null
+++ b/src/securityinsight/setup.cfg
@@ -0,0 +1 @@
+#setup.cfg
\ No newline at end of file
diff --git a/src/securityinsight/setup.py b/src/securityinsight/setup.py
new file mode 100644
index 00000000000..ee9e18c7003
--- /dev/null
+++ b/src/securityinsight/setup.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+
+from codecs import open
+from setuptools import setup, find_packages
+
+# HISTORY.rst entry.
+VERSION = '0.1.0'
+try:
+ from azext_sentinel.manual.version import VERSION
+except ImportError:
+ pass
+
+# The full list of classifiers is available at
+# https://pypi.python.org/pypi?%3Aaction=list_classifiers
+CLASSIFIERS = [
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'License :: OSI Approved :: MIT License',
+]
+
+DEPENDENCIES = []
+
+try:
+ from azext_sentinel.manual.dependency import DEPENDENCIES
+except ImportError:
+ pass
+
+with open('README.md', 'r', encoding='utf-8') as f:
+ README = f.read()
+with open('HISTORY.rst', 'r', encoding='utf-8') as f:
+ HISTORY = f.read()
+
+setup(
+ name='sentinel',
+ version=VERSION,
+ description='Microsoft Azure Command-Line Tools SecurityInsights Extension',
+ author='Microsoft Corporation',
+ author_email='azpycli@microsoft.com',
+ url='https://github.com/Azure/azure-cli-extensions/tree/master/src/sentinel',
+ long_description=README + '\n\n' + HISTORY,
+ license='MIT',
+ classifiers=CLASSIFIERS,
+ packages=find_packages(),
+ install_requires=DEPENDENCIES,
+ package_data={'azext_sentinel': ['azext_metadata.json']},
+)