Added PowerShell that creates alert rules from rule templates for all configured data sources
This commit is contained in:
Родитель
fbe8b107ba
Коммит
e5a4b7bce8
|
@ -0,0 +1,178 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
This command creates Sentinel Alert Rules from all available alert rule templates for which data connectors are configured.
|
||||
.DESCRIPTION
|
||||
This command creates Sentinel Alert Rules from all available alert rule templates for which data connectors are configured.
|
||||
.PARAMETER WorkSpaceName
|
||||
Enter the Log Analytics workspace name (required)
|
||||
.PARAMETER ResourceGroupName
|
||||
Enter the Resource Group name of Log Analytics workspace (required)
|
||||
.NOTES
|
||||
AUTHOR: Tobias Kritten
|
||||
LASTEDIT: 14 Feb 2021
|
||||
.EXAMPLE
|
||||
Create-AzSentinelAnalyticsRulesFromTemplates -WorkspaceName "workspacename" -ResourceGroupName "rgname"
|
||||
The script will create Azure Sentinel Alert Rules in Workspace "workspacename"
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WorkSpaceName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ResourceGroupName
|
||||
|
||||
)
|
||||
|
||||
Function Get-AzSentinelAnalyticsRuleTemplates ($workspaceName, $resourceGroupName) {
|
||||
# Configure the authentication header needed for REST calls
|
||||
$context = Get-AzContext
|
||||
$profile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
|
||||
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($profile)
|
||||
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId)
|
||||
$SubscriptionId = (Get-AzContext).Subscription.Id
|
||||
|
||||
$authHeader = @{
|
||||
'Content-Type' = 'application/json'
|
||||
'Authorization' = 'Bearer ' + $token.AccessToken
|
||||
}
|
||||
|
||||
$urlTemplates = "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.OperationalInsights/workspaces/$($workspaceName)/providers/Microsoft.SecurityInsights/alertruletemplates?api-version=2019-01-01-preview"
|
||||
$urlDataConnectors = "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.OperationalInsights/workspaces/$($workspaceName)/providers/Microsoft.SecurityInsights/dataConnectors?api-version=2019-01-01-preview"
|
||||
|
||||
Write-Host -ForegroundColor Cyan "Fetching configured Data Connectors"
|
||||
$resultDataConnectors = (Invoke-RestMethod -Method "GET" -Uri $urlDataConnectors -Headers $authHeader ).value
|
||||
|
||||
Write-Host -ForegroundColor Cyan "Fetching Alert Templates"
|
||||
$resultAlertTemplates = (Invoke-RestMethod -Method "GET" -Uri $urlTemplates -Headers $authHeader ).value
|
||||
|
||||
foreach ($template in $resultAlertTemplates) {
|
||||
# skip if Alert has already been created from this template
|
||||
if($template.properties.alertRulesCreatedByTemplateCount -gt 0)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
# add only alerts for configured DataConnectors
|
||||
$dcExist = $false
|
||||
foreach($requiredDC in $template.properties.requiredDataConnectors)
|
||||
{
|
||||
foreach($existingDC in $resultDataConnectors)
|
||||
{
|
||||
if($requiredDC.connectorId -eq $existingDC.kind)
|
||||
{
|
||||
$dcExist = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($dcExist)
|
||||
{
|
||||
[void]$alertCreationTemplates.Add($template)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function New-AzSentinelAnalyticsRulesFromTemplate ($workspaceName, $resourceGroupName, $templates) {
|
||||
# Configure the authentication header needed for REST calls
|
||||
$context = Get-AzContext
|
||||
$profile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
|
||||
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($profile)
|
||||
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId)
|
||||
$SubscriptionId = (Get-AzContext).Subscription.Id
|
||||
|
||||
$authHeader = @{
|
||||
'Content-Type' = 'application/json'
|
||||
'Authorization' = 'Bearer ' + $token.AccessToken
|
||||
}
|
||||
|
||||
# Iterate through all alert templates
|
||||
foreach($template in $templates)
|
||||
{
|
||||
$body = ""
|
||||
#Depending on the type of alert we are creating, the body has different parameters
|
||||
switch ($template.kind) {
|
||||
"MicrosoftSecurityIncidentCreation" {
|
||||
$body = @{
|
||||
"kind" = "MicrosoftSecurityIncidentCreation"
|
||||
"properties" = @{
|
||||
"enabled" = "true"
|
||||
"productFilter" = $template.properties.productFilter
|
||||
"displayName" = $template.properties.displayName
|
||||
}
|
||||
}
|
||||
}
|
||||
"Scheduled" {
|
||||
$body = @{
|
||||
"kind" = "Scheduled"
|
||||
"properties" = @{
|
||||
"enabled" = "true"
|
||||
"alertRuleTemplateName" = $template.name
|
||||
"displayName" = $template.properties.displayName
|
||||
"description" = $template.properties.description
|
||||
"severity" = $template.properties.severity
|
||||
"tactics" = $template.properties.tactics
|
||||
"query" = $template.properties.query
|
||||
"queryFrequency" = $template.properties.queryFrequency
|
||||
"queryPeriod" = $template.properties.queryPeriod
|
||||
"triggerOperator" = $template.properties.triggerOperator
|
||||
"triggerThreshold" = $template.properties.triggerThreshold
|
||||
"suppressionDuration" = "PT5H" #Azure Sentinel requires a value here, although suppression is disabled
|
||||
"suppressionEnabled" = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
"MLBehaviorAnalytics" {
|
||||
if ($template.properties.status -eq "Available") {
|
||||
$body = @{
|
||||
"kind" = "MLBehaviorAnalytics"
|
||||
"properties" = @{
|
||||
"enabled" = "true"
|
||||
"alertRuleTemplateName" = $template.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"Fusion" {
|
||||
if ($template.properties.status -eq "Available") {
|
||||
$body = @{
|
||||
"kind" = "Fusion"
|
||||
"properties" = @{
|
||||
"enabled" = "true"
|
||||
"alertRuleTemplateName" = $template.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Default { }
|
||||
}
|
||||
#If we have created the body...
|
||||
if ("" -ne $body) {
|
||||
#Create the GUId for the alert and create it.
|
||||
$guid = (New-Guid).Guid
|
||||
#Create the URI we need to create the alert.
|
||||
$uri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.OperationalInsights/workspaces/$($workspaceName)/providers/Microsoft.SecurityInsights/alertRules/$($guid)?api-version=2019-01-01-preview"
|
||||
try {
|
||||
Write-Host -ForegroundColor Cyan "Attempting to create rule $($template.properties.displayName)"
|
||||
$verdict = Invoke-RestMethod -Uri $uri -Method Put -Headers $authHeader -Body ($body | ConvertTo-Json -EnumsAsStrings)
|
||||
Write-Host -ForegroundColor Green "Succeeded"
|
||||
}
|
||||
catch {
|
||||
#The most likely error is that there is a missing dataset. There is a new
|
||||
#addition to the REST API to check for the existance of a dataset but
|
||||
#it only checks certain ones. Hope to modify this to do the check
|
||||
#before trying to create the alert.
|
||||
$errorReturn = $_
|
||||
Write-Error $errorReturn
|
||||
}
|
||||
#This pauses for 2 second so that we don't overload the workspace.
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$alertCreationTemplates = [System.Collections.ArrayList]@()
|
||||
|
||||
Get-AzSentinelAnalyticsRuleTemplates -workspaceName $workspaceName -resourceGroupName $resourceGroupName
|
||||
New-AzSentinelAnalyticsRulesFromTemplate -workspaceName $workspaceName -resourceGroupName $resourceGroupName -templates $alertCreationTemplates
|
Загрузка…
Ссылка в новой задаче