How To Enable Microsoft Sentinel Analytics Rules at Scale (In Bulk)

11 Min. Read

Updated – 13/08/2025 – The tool below has been updated to fix the incident and grouping configuration for the analytic rule template to validate the time span value in ISO 8601 format.

Updated – 06/05/2025 – The tool below has been updated to include a new option that excludes Preview and Deprecated Rule Templates from deployment and activation.

Updated – 01/05/2025 – The tool below has been updated to include a new option that allows you to exclude specific rule template names from deployment and activation.

Updated – 22/05/2024 – The tool below has been updated to include the MITRE ATT&CK “Sub techniques” for the analytic rule, which requires a preview API version in addition to the “Tactics” and “Techniques“.

Updated – 27/12/2023 – The tool below has been updated to identify all installed solutions; you need to enter and pass the name of the solution(s) [Content title] as shown in the Content Hub blade.

Updated – 25/10/2023 – The tool below has been updated to identify all installed solutions, despite the discrepancy between the solution name that you see in the Microsoft Sentinel portal and the API.

Updated – 15/10/2023 – The tool below has been updated to incorporate the recent API changes for Content Hub.

Updated – 28/07/2023 – The tool below has been updated to leverage Content Hub GA changes. The Resource Graph is being deprecated by Microsoft and replaced by the REST API.

Microsoft Sentinel comes with analytics rules built-in templates that you can turn into active analytics rules by effectively creating a copy of them – that’s what happens when you create a rule from a template.

What if you have a large number of analytics rule templates?

In this article, we will share with you how to create and enable Microsoft Sentinel Analytics Rules at scale using PowerShell. This is very useful if you have many Analytics Rule templates and you want to enable them at once; this will save thousands of mouse clicks.

Introduction

Microsoft Sentinel is a cloud-native Security Information Event Management (SIEM) and Security Orchestration Automated Response (SOAR) solution. Microsoft Sentinel delivers intelligent security analytics and threat intelligence across the enterprise, providing a single solution for alert detection, threat visibility, proactive hunting, and threat response.

Microsoft Sentinel Analytics Rules templates were designed by Microsoft’s team of security experts and analysts based on known threats, common attack vectors, and suspicious activity escalation chains. Many of these templates can be customized to search for activities or filter them out, according to your needs.

Solutions in Microsoft Sentinel Content Hub provide a consolidated way to acquire Microsoft Sentinel content, like data connectors, workbooks, analytics, and automation, in your workspace with a single deployment step.

The question that often comes is, what if we have imported a solution from Content Hub that has more than 50 Analytics rules, and we need to create rules from these templates?

Analytics Rules get created when the solution is installed.
Analytics Rules are created when the solution is installed.

As you probably know, this is a tedious operation to do in the Azure and Defender portal. Let’s see how to automate this process and detect threats faster by creating and enabling the Microsoft Sentinel built-in rules at scale.

Prerequisites

To follow this article, you need to have the following:

1) Azure subscription – If you don’t have an Azure subscription, you can create a free one here.

2) Log Analytics workspace – To create a new workspace, follow the instructions to create a Log Analytics workspace.

3) Enable Microsoft Sentinel at no additional cost on an Azure Monitor Log Analytics workspace for the first 31 days, follow the instructions here. Once Microsoft Sentinel is enabled on your Azure Monitor Log Analytics workspace, every GB of data ingested into the workspace can be retained at no charge for 90 days. You need to have at least Microsoft Sentinel Contributor rights.

4) Azure PowerShell installed locally on your machine or using the Cloud Shell.

5) The Azure Resource Graph module for PowerShell. Please note that this module can be used with locally installed PowerShell, with Azure Cloud Shell, or with the PowerShell Docker image.

To install the Azure Accounts PowerShell modules on your machine, you can run the following command:

# Install and update to the latest Az PowerShell module
Install-Module -Name Az.Accounts -AllowClobber -Force

# Check Az PowerShell modules version installed
Get-Module -Name Az.Accounts -ListAvailable | Select Name, Version

6) Make sure that the solution is installed from Content Hub first before you run the script described below. However, some default Analytics rules already exist without installing any solution from Content Hub. In this case, you can also run the script by targeting the Source name that you see in the Rule Templates tab under the Analytics page as shown in the figure below.

Microsoft Sentinel | Analytics | Rule templates > Source name
Microsoft Sentinel | Analytics | Rule templates > Source name

Enable Gallery Content Analytics Rules

If you are interested in enabling and activating the default built-in rules, which are listed under the “galleryContent” as a source, then you need to use the native Microsoft Azure PowerShell – Microsoft Sentinel cmdlets (Az.SecurityInsights) in Windows PowerShell and PowerShell Core.

Here is an example of how you can enable the default Analytics Rules from the Gallery Content. Please note that for the solution(s) that you import from Content Hub, please refer to the next section.

#! Install Az Module If Needed
function Install-Module-If-Needed {
    param([string]$ModuleName)
 
    if (Get-Module -ListAvailable -Name $ModuleName) {
        Write-Host "Module '$($ModuleName)' already exists, continue..." -ForegroundColor Green
    } 
    else {
        Write-Host "Module '$($ModuleName)' does not exist, installing..." -ForegroundColor Yellow
        Install-Module $ModuleName -Force  -AllowClobber -ErrorAction Stop
        Write-Host "Module '$($ModuleName)' installed." -ForegroundColor Green
    }
}

#! Install Az Security Insights Module If Needed
Install-Module-If-Needed Az.SecurityInsights

#! Install Az Accounts Module If Needed
Install-Module-If-Needed Az.Accounts

#! Check Azure Connection
Try { 
Write-Verbose "Connecting to Azure Cloud..." 
Connect-AzAccount -ErrorAction Stop | Out-Null 
}
Catch { 
Write-Warning "Cannot connect to Azure Cloud. Please check your credentials. Exiting!" 
Break 
}

#! For the Built-in Scheduled Analytics Rule Type, you can run the following command:
#! Get the list of all built-in Scheduled Analytics Rule Type 
$scheduledRules = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> | where Kind -EQ "Scheduled"

#! For the Built-in Microsoft Security Analytics Rule Type, you can run the following command:
#! Get the list of all built-in Microsoft Security Analytics Rule Type
$securityRules = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> | where Kind -EQ "MicrosoftSecurityIncidentCreation"

#! For the Built-in Near Real-Time (NRT) Analytics Rule Type, you can run the following command:
#! Get the list of all built-in Near Real-Time (NRT) Analytics Rule Type
$nrtRules = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> | where Kind -EQ "NRT"

#! For the Built-in Threat Intelligence Analytics Rule Type, you can run the following command:
#! Get the list of all built-in Threat Intelligence Analytics Rule Type
$tiRules = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> | where Kind -EQ "ThreatIntelligence"

#! For the Built-in ML Behavior Analytics Rule Type, you can run the following command:
#! Get the list of all built-in ML Behavior Analytics Rule Type
$mlRules = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> | where Kind -EQ "MLBehaviorAnalytics"

Let’s suppose you want to enable a specific built-in [Scheduled] – [Microsoft Defender XDR] Analytics Rule from the [Gallery Content], called “Multiple Teams deleted by a single user“, for example.

First, you need to identify the Alert Rule Template name, which is in GUID. You run the following command to get the GUID name:

#! Get the Alert GUID for "Multiple Teams deleted by a single user"
$AlertRuleTemplateName = Get-AzSentinelAlertRuleTemplate -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> `
 | where DisplayName -eq "Multiple Teams deleted by a single user"

#! Display the GUID Name
$AlertRuleTemplateName
Get Microsoft Sentinel Built-in Analytic Rule GUID Name
Get Microsoft Sentinel Built-in Analytic Rule GUID Name

Then you run the following PowerShell command to create and activate the “Scheduled” rule. Note that you need to pass the rule type (Kind), the rule template name (GUID), the severity, the KQL query, the frequency, and so on.

#! Create a Scheduled Analytics Rule "Multiple Teams deleted by a single user"
New-AzSentinelAlertRule -ResourceGroupName <RG-Name> -WorkspaceName <LogAnalytics-Name> `
 -Kind $AlertRuleTemplateName.Kind -AlertRuleTemplateName $AlertRuleTemplateName.Name -enabled `
 -Query $AlertRuleTemplateName.Query -Severity $AlertRuleTemplateName.Severity `
 -DisplayName $AlertRuleTemplateName.DisplayName -QueryFrequency $AlertRuleTemplateName.QueryFrequency `
 -QueryPeriod $AlertRuleTemplateName.QueryPeriod -TriggerOperator $AlertRuleTemplateName.TriggerOperator `
 -TriggerThreshold $AlertRuleTemplateName.TriggerThreshold
Create a Built-in Scheduled Analytics Rule with PowerShell
Create a Built-in Scheduled Analytics Rule with PowerShell

Of course, you can build upon it and enable multiple built-in Analytics Rules from the Gallery Content. Please refer to the official documentation to see other examples of how to create or update the built-in Analytics Rule from the Gallery Content.

Enable Microsoft Sentinel Analytics Rules

This section will describe how to enable Microsoft Sentinel Analytics Rules for the solution(s) you import from Content Hub.

You have a couple of options to run the script: You can either use Azure Cloud Shell, Visual Studio Code, or Windows Terminal. The Script works with PowerShell 5.1 or PowerShell 7 (core) with the Az module.

.EXAMPLE-1

.\Set-AnalyticsRules.ps1 `
    -SubscriptionId "xxxxxxxx-aaaa-bbbb-cccc-zzzzzzzzzzzz" `
    -ResourceGroup "RG-Name" `
    -WorkspaceName "Log-Analytics-Name" `
    -SolutionName "Microsoft Entra ID" `
    -enableRules Yes -Verbose

.EXAMPLE-2

.\Set-AnalyticsRules.ps1 `
    -SubscriptionId "xxxxxxxx-aaaa-bbbb-cccc-zzzzzzzzzzzz" `
    -ResourceGroup "RG-Name" `
    -WorkspaceName "Log-Analytics-Name" `
    -SolutionName "Azure SQL database" `
    -enableRules Yes -Verbose

.EXAMPLE-3

.\Set-AnalyticsRules.ps1 `
    -SubscriptionId "xxxxxxxx-aaaa-bbbb-cccc-zzzzzzzzzzzz" `
    -ResourceGroup "RG-Name" `
    -WorkspaceName "Log-Analytics-Name" `
    -SolutionName "Windows Security Events" `
    -enableRules Yes -Verbose

To supply the list of rule template names to exclude when running the script, you can pass the  -excludeRuleTemplates parameter as an array of strings. This ensures the script receives the array of rule template names to exclude. Here’s how you can do it:

.EXAMPLE-4

.\Set-AnalyticsRules.ps1 `
    -subscriptionId "xxxxxxxx-aaaa-bbbb-cccc-zzzzzzzzzzzz" `
    -resourceGroupName "RG-Name" `
    -workspaceName "Log-Analytics-Name" `
    -solutionName "Azure Activity" `
    -excludeRuleTemplates @("New CloudShell User", "Creation of expensive computes in Azure") ` 
    -enableRules Yes -Verbose

To exclude the Preview and Deprecated Rule Templates when running the script, you can pass the -excludePreviewDeprecated parameter as a switch [Yes/No]. Here’s how you can do it:

.EXAMPLE-5

.\Set-AnalyticsRules.ps1 `
    -subscriptionId "xxxxxxxx-aaaa-bbbb-cccc-zzzzzzzzzzzz" `
    -resourceGroupName "RG-Name" `
    -workspaceName "Log-Analytics-Name" `
    -solutionName "Microsoft Entra ID" `
    -excludePreviewDeprecated Yes ` 
    -enableRules Yes -Verbose

This example will connect to your Azure account using the subscription ID specified, and then create all analytics rules from templates for the specified Microsoft Sentinel content solution name. Please note that you need to enter and pass the name of the solution(s) [Content title] as shown in the Content hub blade in the figure below (E.g. Microsoft Entra ID, Azure SQL Database, DNS Essentials, Windows Security Events, Azure Activity, SAP applications, etc.) – Case-insensitive.

Microsoft Sentinel | Content Hub - Content title
Microsoft Sentinel | Content Hub – Content title

By default, all of the rules will be created in a Disabled state, however, you have the option to enable the rules at creation time as well by setting the parameter (enable rules) to Yes.

Here is an example of the output once you run this tool:

Microsoft Sentinel: Creating Analytics Rules from Templates
Microsoft Sentinel: Creating Analytics Rules from Templates

PowerShell Code

Updated – 13/08/2025 – The tool below has been updated to fix the incident and grouping configuration for the analytic rule template to validate the time span value in ISO 8601 format.

Updated – 06/05/2025 – The tool below has been updated to include a new option that excludes Preview and Deprecated Rule Templates from deployment and activation.

Updated – 01/05/2025 – The tool below has been updated to include a new option that allows you to exclude specific rule template names from deployment and activation.

Updated – 22/05/2024 – The tool below has been updated to include the MITRE ATT&CK “Sub techniques” for the analytic rule, which requires a preview API version in addition to the “Tactics” and “Techniques“.

Updated – 27/12/2023 – The tool below has been updated to identify all installed solutions. You need to enter and pass the name of the solution(s) [Content title] as shown in the Content hub blade.

Updated – 25/10/2023 – The tool below has been updated to identify all installed solutions, despite the discrepancy between the solution name that you see in the Microsoft Sentinel portal and the API.

Updated – 15/10/2023 – The tool below has been updated to incorporate the recent API changes for Content Hub.

Updated – 28/07/2023 – The tool below has been updated to leverage Content Hub GA changes. The Resource Graph is being deprecated by Microsoft and replaced by the REST API.

The complete script is detailed below to automate the entire process of creating and activating the Analytics Rules content pack:

<#
.SYNOPSIS
Enable Microsoft Sentinel Analytics Rules at Scale.

.DESCRIPTION
How to create and enable Microsoft Sentinel Analytics Rules at Scale using PowerShell.

.NOTES
File Name : Set-AnalyticsRules.ps1
Author    : Microsoft MVP/MCT - Charbel Nemnom
Version   : 3.1
Date      : 24-October-2022
Updated   : 13-August-2025
Requires  : PowerShell 7.4.x (Core)
Module    : Az Module

.LINK
To provide feedback or for further assistance please visit:
 https://charbelnemnom.com 

.EXAMPLE
.\Set-AnalyticsRules.ps1 -SubscriptionId "SUB-ID" -ResourceGroup "RG-NAME" -WorkspaceName "Log-Analytics" -SolutionName "Source-Name" -enableRules [Yes] -Verbose
This example will connect to your Azure account using the subscription Id specified, and then create all analytics rules from templates for the specified Microsoft Sentinel solution.
By default, all of the rules will be created in a Disabled state, however, you have the option to enable the rules at creation time by setting the parameter -enableRules [Yes].
You also have the option to exclude specific rule templates by using the -excludeRuleTemplates parameter, and you can specify the names of the templates you want to exclude.
The "Preview" and "Deprecated" rule templates can be also excluded by setting the -excludePreviewDeprecated parameter to [Yes]. This option is set to [Yes] by default.
#>

param (
    [Parameter(Position = 0, Mandatory = $true, HelpMessage = 'Enter Azure Subscription ID')]
    [string]$subscriptionId,
    [Parameter(Position = 1, Mandatory = $true, HelpMessage = 'Enter Resource Group Name where Microsoft Sentinel is deployed')]
    [string]$resourceGroupName,
    [Parameter(Position = 2, Mandatory = $true, HelpMessage = 'Enter Log Analytics Workspace Name')]
    [string]$workspaceName,    
    [Parameter(Position = 3, Mandatory = $true, HelpMessage = 'Enter Microsoft Sentinel Content Hub Solution Name')]
    [string]$solutionName,
    [Parameter(Position = 4, Mandatory = $false, HelpMessage = 'Exclude Rule Templates Names i.e: @("ABC","DEF")')]
    [ValidateNotNullOrEmpty()]
    [array]$excludeRuleTemplates,
    [Parameter(Position = 5, Mandatory = $false, HelpMessage = 'Exclude [Preview] and [Deprecated] Rule Templates [Yes/No]')]
    [ValidateNotNullOrEmpty()]
    [ValidateSet("Yes", "No")]
    [String]$excludePreviewDeprecated = 'Yes',
    [Parameter(Position = 6, Mandatory = $false, HelpMessage = 'Enable Rules at Creation Time [Yes/No]')]
    [ValidateNotNullOrEmpty()]
    [ValidateSet("Yes", "No")]
    [String]$enableRules = 'No'
)

#! Install Az Module If Needed
function Install-Module-If-Needed {
    param([string]$ModuleName)
 
    if (Get-Module -ListAvailable -Name $ModuleName) {
        Write-Host "Module '$($ModuleName)' already exists, continue..." -ForegroundColor Green
    } 
    else {
        Write-Host "Module '$($ModuleName)' does not exist, installing..." -ForegroundColor Yellow
        Install-Module $ModuleName -Force  -AllowClobber -ErrorAction Stop
        Write-Host "Module '$($ModuleName)' installed." -ForegroundColor Green
    }
}

#! Install Az Accounts Module If Needed
Install-Module-If-Needed Az.Accounts

#! Check Azure Connection
Try { 
    Write-Verbose "Connecting to Azure Cloud..." 
    Connect-AzAccount -ErrorAction Stop | Out-Null 
}
Catch { 
    Write-Warning "Cannot connect to Azure Cloud. Please check your credentials. Exiting!" 
    Break 
}

# Define the Preview API Version to use for Microsoft Sentinel
# The Preview API Version is needed to include the MITRE ATT&CK "Sub techniques"
$apiVersion = "?api-version=2025-01-01-preview"

# Create the authentication access token
Write-Verbose "Creating authentication access token..."
$context = Get-AzContext
if (-not $context) {
    throw "No Azure context found. Please re-authenticate."
} 
$tokenRequest = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id, $null, "Never", $null, "https://management.azure.com/")
if (-not $tokenRequest) {
    throw "Failed to obtain access token. Please check your authentication."
}
$AzureAccessToken = $tokenRequest.AccessToken
$authHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$authHeader.Add("Content-Type", "application/json")
$authHeader.Add("Authorization", "Bearer $AzureAccessToken")

# Get Content Product Packages
$contentURI = "https://management.azure.com/subscriptions/$subscriptionid/resourceGroups/$resourceGroupName/providers/Microsoft.OperationalInsights/workspaces/$workspaceName/providers/Microsoft.SecurityInsights/contentProductPackages$($apiVersion)"
$contentResponse = (Invoke-RestMethod $contentURI -Method 'GET' -Headers $authHeader).value
$solutions = $contentResponse | Where-Object { $null -ne $_.properties.version }
$solution = ($solutions | Where-Object { $_.properties.displayName -eq "$solutionName" }).properties.contentId

# Get Content Templates
$contentURI = "https://management.azure.com/subscriptions/$subscriptionid/resourceGroups/$resourceGroupName/providers/Microsoft.OperationalInsights/workspaces/$workspaceName/providers/Microsoft.SecurityInsights/contentTemplates$($apiVersion)"
$contentResponse = (Invoke-RestMethod $contentURI -Method 'GET' -Headers $authHeader).value

try {
    $contentTemplates = $contentResponse | Where-Object { $_.properties.packageId -eq $solution -and $_.properties.contentKind -eq "AnalyticsRule" }
    if ($contentTemplates.count -eq 0) {
        throw "Solution Name: [$solutionName] cannot be found. Please check the solution name and Install it from the Content Hub blade"
    }
}
catch {
    Write-Error $_ -ErrorAction Stop
}

if ($excludePreviewDeprecated -eq 'Yes') {
    Write-Verbose "Excluding Preview and Deprecated Rule Templates"

    $contentTemplatesExcluded = $contentTemplates | Where-Object {
        $_.properties.displayName -notmatch '^(Preview|Deprecated)' -and
        $_.properties.displayName -notmatch '\[Preview\]' -and
        $_.properties.displayName -notmatch '\[Deprecated\]'
    }

    if ($contentTemplatesExcluded.Count -ne $contentTemplates.Count) {
        Write-Verbose "$($contentTemplates.Count - $contentTemplatesExcluded.Count) Analytic Rule(s) were excluded for: [$solutionName]"
        $contentTemplates = $contentTemplatesExcluded
    }
    else {
        Write-Verbose "No Preview and Deprecated Analytic Rules were excluded for: [$solutionName]"
    }
}

if ($excludeRuleTemplates) {
    Write-Verbose "Excluding Rule Templates: $($excludeRuleTemplates -join ', ')"
    foreach ($ruleTemplate in $excludeRuleTemplates) {
        $contentTemplates = $contentTemplates | Where-Object { $_.properties.displayname -ne "$ruleTemplate" }
    }
}

Write-Verbose "$($contentTemplates.count) Analytic Rules found for: [$solutionName]"

foreach ($contentTemplate in $contentTemplates) {
    $ruleName = $contentTemplate.name
    $ruleTemplateURI = "https://management.azure.com/subscriptions/$subscriptionid/resourceGroups/$resourceGroupName/providers/Microsoft.OperationalInsights/workspaces/$workspaceName/providers/Microsoft.SecurityInsights/contentTemplates/$($ruleName)$($apiVersion)"
    $ruleResponse = Invoke-RestMethod $ruleTemplateURI -Method 'GET' -Headers $authHeader -Verbose:$false    
        
    $ruleProperties = $ruleResponse.properties.mainTemplate.resources | Where-Object type -eq 'Microsoft.OperationalInsights/workspaces/providers/metadata' | Select-Object properties     
    $ruleProperties.properties = $ruleProperties.properties | Select-Object * -ExcludeProperty description, parentId 

    $rule = $ruleResponse.properties.mainTemplate.resources | Where-Object type -eq 'Microsoft.SecurityInsights/AlertRuleTemplates'
    $rule.properties | Add-Member -NotePropertyName alertRuleTemplateName -NotePropertyValue $rule.name
    $rule.properties | Add-Member -NotePropertyName templateVersion -NotePropertyValue $ruleResponse.properties.version    

    # Fix Grouping Configuration 
    if ($rule.properties.PSObject.Properties.Name -contains "incidentConfiguration") {
        if ($rule.properties.incidentConfiguration.PSObject.Properties.Name -contains "groupingConfiguration") {
            if (-not $rule.properties.incidentConfiguration.groupingConfiguration) {
                $rule.properties.incidentConfiguration | Add-Member -NotePropertyName "groupingConfiguration" -NotePropertyValue @{
                    matchingMethod   = "AllEntities"
                    lookbackDuration = "PT1H"
                }
            }
            else {
                # Ensure `matchingMethod` exists
                if (-not ($rule.properties.incidentConfiguration.groupingConfiguration.PSObject.Properties.Name -contains "matchingMethod")) {
                    $rule.properties.incidentConfiguration.groupingConfiguration | Add-Member -NotePropertyName "matchingMethod" -NotePropertyValue "AllEntities"
                }

                # Ensure `lookbackDuration` is in ISO 8601 format
                if ($rule.properties.incidentConfiguration.groupingConfiguration.PSObject.Properties.Name -contains "lookbackDuration") {
                    $lookbackDuration = $rule.properties.incidentConfiguration.groupingConfiguration.lookbackDuration
                    if ($lookbackDuration -match "^(\d+)(h|d|m)$") {
                        $timeValue = $matches[1]
                        $timeUnit = $matches[2]
                        switch ($timeUnit) {
                            "h" { $isoDuration = "PT${timeValue}H" }
                            "d" { $isoDuration = "P${timeValue}D" }
                            "m" { $isoDuration = "PT${timeValue}M" }
                        }
                        $rule.properties.incidentConfiguration.groupingConfiguration.lookbackDuration = $isoDuration
                    }
                }
            }
        }
    }

    If ($enableRules -eq "Yes") {
        $rule.properties.enabled = $true
    }    

    $rulePayload = $rule | ConvertTo-Json -EnumsAsStrings -Depth 50
    $ruleURI = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.OperationalInsights/workspaces/$workspaceName/providers/Microsoft.SecurityInsights/alertRules/$($rule.name)$($apiVersion)"    
    try {        
        $ruleResult = Invoke-AzRestMethod -Method PUT -path $ruleURI -Payload $rulePayload -Verbose:$false

        If (!($ruleResult.StatusCode -in 200, 201)) {
            Write-Host $ruleResult.StatusCode
            Write-Host $ruleResult.Content
            throw "Error when enabling Analytics rule: $($rule.properties.displayName)"
        }        
        If ($enableRules -eq "Yes") {
            Write-Verbose "Creating and Enabling Analytic rule: $($rule.properties.displayName)"
        }
        Else {
            Write-Verbose "Creating Analytic rule: $($rule.properties.displayName)"
        }
        
    }
    catch {
        Write-Error $_ -ErrorAction Continue
    }
    
    If ($ruleResult.StatusCode -in 200, 201) {
        $ruleResult = $ruleResult.Content | ConvertFrom-Json        
        $ruleProperties.properties | Add-Member -NotePropertyName parentId -NotePropertyValue $ruleResult.id 
        $metadataURI = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.OperationalInsights/workspaces/$workspaceName/providers/Microsoft.SecurityInsights/metadata/analyticsrule-$($rule.name)$($apiVersion)"
        $metadataPayload = $ruleProperties | ConvertTo-Json -EnumsAsStrings -Depth 50
        try {
            $resultMetadata = Invoke-AzRestMethod -Method PUT -path $metadataURI -Payload $metadataPayload -Verbose:$false
            if (!($resultMetadata.StatusCode -in 200, 201)) {
                Write-Host $resultMetadata.StatusCode
                Write-Host $resultMetadata.Content
                throw "Error when updating Metadata for Analytic rule: $($rule.properties.displayName)"
            }
            Write-Verbose "Updating Metadata for Analytic rule: $($rule.properties.displayName)"
        }
        catch {
            Write-Error $_ -ErrorAction Continue

        }
    }   
}

Before running the tool, we can see that we don’t have any active rules created in the Disabled state. In this example, we have 15 Active rules only.

Microsoft Sentinel | Analytics
Microsoft Sentinel | Analytics

Once you run this tool, you can refresh the Analytics rules page and check all the rules are created in the Disabled state. In this example, we have 58 Active rules.

Microsoft Sentinel | Analytics Rules Creation
Microsoft Sentinel | Analytics Rules Creation

That’s it, there you have it. Happy Analytics Rules creation with Microsoft Sentinel!

If you have any feedback or changes that everyone should receive, please feel free to leave a comment below.

Summary

This article showed you how to create and enable Microsoft Sentinel Analytics Rules at scale using PowerShell, this is very useful if you have many Analytics Rule templates as part of a Content Hub solution and you want to enable them at once.

Analytics rules search for specific events or sets of events across your environment, alert you when certain event thresholds or conditions are reached, generate incidents for your SOC to triage and investigate, and respond to threats with automated tracking and remediation processes.

This is one of the many features in Microsoft Sentinel that can be utilized to provide immense value to threat detection out-of-the-box.

The power of Microsoft Sentinel comes from the ability to detect, investigate, respond to, and remediate threats.

__
Thank you for reading my blog.

If you have any questions or feedback, please leave a comment.

-Charbel Nemnom-

Previous

What Is Cloudflare Rocket Loader? A Complete Guide Is Here

How To Set Up Cloudflare DNS? Easily

Next

61 thoughts on “How To Enable Microsoft Sentinel Analytics Rules at Scale (In Bulk)”

Leave a comment...

  1. Hello,

    This looks very interesting. I tried to run the script however it returns no results.

    With all the Microsoft changes, I was wondering if the script still works.

    Thank you.

  2. Hello Csaba, thank you for the comment!
    Yes, the script is still working 100 percent. I just tested it again and I confirm that it’s working.
    If you could provide more details so I can help.
    Which Solution Name are you trying to enable the Analytic Rules for?
    Thanks!

  3. Hello,

    thank you for your reply. I am getting the following result when trying to run the script:
    (I have edited some of the information with REDACTED)

    resources
    | where type =~ ‘Microsoft.Resources/templateSpecs/versions’
    | where tags[‘hidden-sentinelContentType’] =~ ‘AnalyticsRule’ and tags[‘hidden-sentinelWorkspaceId’] =~ ‘/subscriptions/REDACTED/resourceGroups/REDACTED/providers/Microsoft.OperationalInsights/workspaces/REDACTED’
    | extend workspaceName = strcat(split(‘/subscriptions/REDACTED/resourceGroups/REDACTED/providers/Microsoft.OperationalInsights/workspaces/REDACTED’, “/”)[-1],’-‘)
    | extend versionArray=split(id, “/”)
    | extend content_kind = tags[‘hidden-sentinelContentType’]
    | extend version = name
    | extend parsed_version = parse_version(version)
    | extend resources = parse_json(parse_json(parse_json(properties).template).resources)
    | extend metadata = parse_json(resources[array_length(resources)-1].properties)
    | extend contentId=tostring(metadata.contentId)
    | summarize arg_max(parsed_version, version, properties) by contentId
    | project contentId, version, properties
    | mv-expand solution = properties.template.resources
    | where solution.properties.source.name == ‘Azure Active Directory’
    | project-away solution
    VERBOSE: Sent top=100 skip=0 skipToken=
    VERBOSE: Received results: 0
    C:\Tools\Sentinel\Set-AnalyticsRules.ps1 : Resource Graph query error
    At line:1 char:1
    + .\Set-AnalyticsRules.ps1 -subscriptionId REDACTED …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-AnalyticsRules.ps1

    Thank you.

  4. Hello Csaba, thanks for sharing the details!
    I have noticed that you are trying to enable the “Azure Active Directory” Analytics Rules as a solution from Content Hub, right?
    I just exactly simulated your scenario and I was able to create all the 48 Analytics rules for “Azure Active Directory” successfully as shown in the screenshot below.
    Create Azure Active Directory Analytics Rules in Microsoft Sentinel
    What I see based on the error you shared above, it looks like you have a write permissions issue.
    I supposed that you launched PowerShell with admin rights as well.
    Could you please verify your Azure and Microsoft Sentinel permissions?
    Hope it helps!

  5. Hello, I tried this from the Azure Cloud Shell, however, it errors with:

    Exception: Resource Graph query error.

    I ran:
    clouddrive> ./enableanalytics.ps1 -SubscriptionId “REMOVED” -ResourceGroup “my-sandbox” -WorkspaceName “sentineltest” -SolutionName “Azure Active Directory” -Verbose

    I did also run:

    Install-Module -Name Az.Accounts, Az.ResourceGraph -AllowClobber -Force

    Get-Module -Name Az.Accounts, Az.ResourceGraph -ListAvailable | Select Name, Version
    Name Version
    —- ——-
    Az.Accounts 2.11.1
    Az.Accounts 2.9.1
    Az.ResourceGraph 0.13.0
    Az.Accounts 2.11.0

    Have you seen the same error?

  6. Hello Darren, thanks for the comment!
    I am seen that you are running this from Azure Cloud Shell.
    Are you using the Sandbox environment from Microsoft Learn to test this, or do you have a private subscription from Sentinel?
    Could you please try to run it from your local machine instead of using Cloud Shell?
    Let me know if it works.

  7. Hey there, this solution seems to work consistently for the Azure Active Directory connector, however, trying to enable rules for any other data connector seems to fail. Office 365 for example, or even Microsoft Defender for Cloud or any other Microsoft Data Connector.

    Is there perhaps something in the code that is specifically pointed at Azure Active Directory Data Connector?

  8. Hello Nick, thanks for the comment!
    Please note that this solution works consistently on any source name that you provide in Sentinel.
    I am using the code exactly as provided in this article.
    I have just tested it with the Source name “Microsoft 365 Defender”, and “Dynamics 365” solutions. It’s working flawlessly.
    Please find below screenshots for your reference confirming the same.
    1) Running the script to create “Microsoft 365 Defender” Analytic Rules.
    Creating Microsoft 365 Defender Rules in Microsoft Sentinel
    2) Confirming “Microsoft 365 Defender” Analytic Rules are created in a Disabled state.
    Confirming Microsoft 365 Defender Rules in Microsoft Sentinel
    Hope it helps!

  9. Hi,

    What if I wanted to enable all 483 default Rule templates from Gallery Content?

    The Source name for these, are known as “Gallery Content”

    .\Set-AnalyticsRules.ps1 -SubscriptionId “xxxxxxxxxxxxxxxxxx” -ResourceGroupName “SOC” -WorkspaceName “SOC-AZURE” -SolutionName “Gallery Content” -enableRules No -Verbose

  10. Hello Yap, thanks for the comment!
    I’ve checked the Rule templates in the Gallery Content, and the source name is called “galleryContent” one word.
    Could you please retry using the following command:

    .\Set-AnalyticsRules.ps1 -SubscriptionId "xxxxxxxxxxxxxxxxxx" -ResourceGroupName "SOC" -WorkspaceName "SOC-AZURE" -SolutionName "galleryContent" -enableRules No -Verbose

    Let me know if it works for you.

  11. I am getting an error “Exception: Resource Graph query error”
    not sure where is failing. I am following the script, trying ‘Azure Active Directory’ or ‘Azure Firewall’ – the same.

    Any help on this?
    Much appreciated

  12. Hello Ermir, thanks for the comment! This is really very strange.
    I just ran the same script now and I was able to create all the 48 Analytics Rules of ‘Azure Active Directory’.
    What is the version of the Az.ResourceGraph loaded on your machine?

    Get-Module -Name Az.ResourceGraph -ListAvailable

    I have version 0.13.0 installed.
    I would suggest that you run the script manually portion by portion and see where it’s failing.
    Let me know if it works for you.

  13. Hi Charbel,

    Thanks for your great work – I really enjoy reading your blog posts.

    I’m just wondering whether you know of any solution/script capable of:
    – automatically deploying all of the “analytic rule templates” which come with MS Sentinel, by default.

    Ideally- the script/solution would have the ability to either:
    – Take 1 or more template IDs parameters- to deploy only a subset of the total templates, OR
    – Pass in a “data connector” parameter- which would only deploy analytic rules- associated with that data connector?

    —————————
    Alternatively – do you know of any way to automate the “updating” of existing analytic rules- when Microsoft updates the KQL?

    Thanks in advance,
    Ryan

  14. Hi Charbel, thanks very much for this script, it has helped a lot on a few engagements to date.

    As Ermir mentioned, I also had the same error. The missing piece for me was to make sure that the solution is installed from Content Hub.

    In my case, I had been enabling rules for a colleague who had already installed the solutions. On this occasion I had done the full deployment, therefore missed installing the solution itself – if that makes sense?

  15. Hello Stuart, thanks for the comment and feedback!
    Yes, you are right. You need to have the solution in question installed from Content Hub first before you run the script.
    However, there are some default Analytics rules that already exist without installing any solution from Content Hub.
    In this case, you can also run the script by targeting the Source name that you see in the Rule templates tab under Analytics.
    I have updated the article to clarify that point as prerequisite #6.
    Thanks!

  16. Hello Ryan O, thanks for the comment and feedback!
    I am happy to hear that you’re enjoying reading my blog posts.

    Yes, there is a PowerShell script that you can use to automate the “UPDATE AVAILABLE” of existing analytic rules – when Microsoft updates the KQL.
    This script was written by a Microsoft Team Member in Customer Experience Engineering (CxE) Team.
    I just tested it and it works. You can access it on this page.

    Disclaimer before you use it: This will update ALL the analytic rules where the rule template has been updated, and be aware if you have some custom modifications in those templates. They might get overwritten. So, use it at your own risk!

    This script will update all the Analytic rules that come from a rule template that has been updated and they are enabled (active).
    Now you can go a step further instead of running this script manually every time, you can use Azure Automation and schedule the script to run automatically twice per month for example, to update all your rules.
    —————————
    In regards to your other questions:
    – automatically deploying all of the “analytic rule templates” which come with MS Sentinel, by default.
    Yes, you can use my script as described in this article and pass the -SolutionName as “galleryContent” one word.
    Hope it helps and let me know if it works for you!

  17. ***Slight amendment to my original reply sent about 5 mins before this one*** where I accidentally typed “Gallery Content” instead of “galleryContent” when indicating the failed command I ran

    Hi Charbel,

    Thanks for responding so quickly.

    Your script seems to work perfectly when I use: i) “Azure Active Directory” or ii) “Microsoft 365 Defender” as the -SolutionName. However, it does not work for me when I try using -SolutionName “galleryContent” to install “all” the analytic rules templates.

    The full (redacted) command I tried was: `.\Set-AnalyticRules.ps1 -SubscriptionId -ResourceGroup -WorkspaceName -SolutionName “galleryContent” -enableRules No -Verbose `

    Note 1: I have also tried: i) -SolutionName “Gallery Content”, ii) -SolutionName “GalleryContent” and both of these also fail
    Note 2: I have also tried excluding the – enableRules parameter – and this also didn’t work

    ————————–
    Q1) Similarly to how I had to install the “Azure Active Directory” and “Microsoft 365 Defender” solutions before running the command for these solutions- is there anything I need to install as a pre-requisite before running the -SolutionName “galleryContent” cmd?

    Q2) Do you have any other ideas on why this may be failing. (The account I’m using to authenticate to Azure AD has global admin permissions in the tenant, and then: i) “owner”, ii) “Sentinel Contributor” and iii) “Sentinel Automation Contributor” permissions on the resource group

  18. Hello Ryan,
    Please note that you need to have the solution in question installed from Content Hub first before you run the script.
    You mentioned that when you use: i) “Azure Active Directory” or ii) “Microsoft 365 Defender” as the -SolutionName it works.
    Did you try to install any other solution from Content Hub and then try to target that solution specifically?
    I need to double-check the “galleryContent” as a solution if it works, but for any other solution that you install from Content Hub, it should work without any issues.
    Thanks!

  19. Hi Charbel,

    – I also tried -SolutionName “Syslog”. This worked perfectly
    – I also tried -SolutionName “Cisco Umbrella”. This failed. However, it worked when I used -SolutionName “CiscoUmbrella”.

    From this- I can deduce:
    1. That naming convention matters. And therefore- you need some way of knowing/guessing how the SolutionName should be formatted. For example, the -SolutionName for any Microsoft solutions is straightforward because they appear to exactly match the solution name in the Content hub. However, for Cisco- the content hub solution name is “Cisco Umbrella” which is a space in between. However, in your script the -SolutionName needs to be “CiscoUmbrella” without the space in between.
    2. Based on the above- I suspect that -SolutionName “galleryContent” is might be failing because the formatting/casing of “galleryContent” may be incorrect.

    Let me know what you think?
    Cheers,
    Ryan

  20. Hello Ryan, I looked at this more deeply.
    Unfortunately, the default “galleryContent” as a solution cannot be activated/enabled today using this script.
    Those are not coming from a Content Hub solution, therefore we cannot find them in Resource Graph as templates.
    I am still looking for a solution to this.
    —————
    Now about your second question ‘naming convention’, I checked it and you can get the correct Solution Name by looking at the Rule Templates tab, and filtering by Source Name as you can see in the screenshot below “CiscoUmbrella” without any spaces.
    Microsoft Sentinel - Rule Templates | Source Name
    Once you identify the desired source name, then you can run the script and it should work 100%.
    Hope it helps!

Let us know what you think, or ask a question...