mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 18:52:18 +01:00
added documetation
This commit is contained in:
@@ -1,105 +1,294 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Exports comprehensive Azure Alert Rules inventory across all enabled subscriptions with associated action groups and configuration details.
|
||||
|
||||
.DESCRIPTION
|
||||
This script performs a complete audit of Azure Alert Rules across multiple alert types and all enabled subscriptions.
|
||||
It inventories Smart Detector Alert Rules, Scheduled Query Rules, Metric Alerts, and Activity Log Alerts,
|
||||
including their associated Action Groups, receivers, and tag information.
|
||||
|
||||
The script processes four main types of Azure alerts:
|
||||
- Smart Detector Alert Rules (Application Insights anomaly detection)
|
||||
- Scheduled Query Rules (Log Analytics/KQL-based alerts)
|
||||
- Metric Alert Rules (Resource metric-based alerts)
|
||||
- Activity Log Alert Rules (Azure Activity Log event alerts)
|
||||
|
||||
For each alert rule, the script captures detailed information including:
|
||||
- Alert configuration and state
|
||||
- Associated Action Groups and their receivers
|
||||
- Tag information for governance tracking
|
||||
- Subscription and resource group context
|
||||
|
||||
.PARAMETER None
|
||||
This script does not accept parameters. It processes all enabled Azure subscriptions accessible to the current user.
|
||||
|
||||
.OUTPUTS
|
||||
CSV file named with timestamp pattern: "yyyy-MM-dd HHmm alert rules.csv"
|
||||
Also displays results in formatted table output to console.
|
||||
|
||||
CSV contains columns for alert details, action group information, and governance tags.
|
||||
|
||||
.EXAMPLE
|
||||
.\AlertRules.ps1
|
||||
|
||||
Exports all alert rules from all enabled subscriptions to a timestamped CSV file and displays results.
|
||||
|
||||
.NOTES
|
||||
Author: Cloud Engineering Team
|
||||
Version: 1.0
|
||||
Created: 2024
|
||||
|
||||
Prerequisites:
|
||||
- Azure PowerShell module (Az) must be installed
|
||||
- User must be authenticated (Connect-AzAccount)
|
||||
- Requires read permissions on Azure Monitor, Action Groups, and resource tags across all subscriptions
|
||||
- Tenant ID is hardcoded and may need adjustment for different environments
|
||||
|
||||
Security Considerations:
|
||||
- Script uses Azure access tokens for REST API authentication
|
||||
- Requires permissions to read alert rules and action groups across all subscriptions
|
||||
- Output file contains sensitive alerting configuration information
|
||||
|
||||
Performance Notes:
|
||||
- Processing time varies based on number of subscriptions and alert rules
|
||||
- Script processes all enabled subscriptions sequentially
|
||||
- REST API calls for Smart Detector rules add processing time
|
||||
|
||||
Alert Types Covered:
|
||||
- microsoft.alertsmanagement/smartdetectoralertrules (Application Insights anomalies)
|
||||
- microsoft.insights/scheduledqueryrules (Log Analytics queries)
|
||||
- Microsoft.Insights/metricAlerts (Resource metrics)
|
||||
- Microsoft.Insights/ActivityLogAlerts (Activity log events)
|
||||
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/azure/azure-monitor/alerts/
|
||||
https://docs.microsoft.com/en-us/azure/azure-monitor/alerts/action-groups
|
||||
#>
|
||||
|
||||
#Requires -Modules Az
|
||||
#Connect-AzAccount
|
||||
|
||||
$access_token = (Get-AzAccessToken -TenantId "e9792fd7-4044-47e7-a40d-3fba46f1cd09").Token
|
||||
# Get Azure access token for REST API calls (required for Smart Detector rules)
|
||||
# Note: Tenant ID is hardcoded and should be updated for different environments
|
||||
$access_token_secure = (Get-AzAccessToken -TenantId "e9792fd7-4044-47e7-a40d-3fba46f1cd09").Token
|
||||
$access_token = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($access_token_secure))
|
||||
|
||||
# Set output field separator for array-to-string conversion
|
||||
$ofs = ', '
|
||||
|
||||
function GetSmartDetectorActionGroupIds {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves Action Group IDs and details for Smart Detector Alert Rules using Azure Management REST API.
|
||||
|
||||
.DESCRIPTION
|
||||
This function queries the Azure Management REST API to retrieve detailed information about Smart Detector Alert Rules,
|
||||
including their associated Action Groups. Smart Detector rules are used for Application Insights anomaly detection
|
||||
and require REST API calls as they're not fully supported by PowerShell cmdlets.
|
||||
|
||||
.PARAMETER alertRuleName
|
||||
The name of the Smart Detector Alert Rule to query.
|
||||
|
||||
.PARAMETER resourceGroupName
|
||||
The resource group containing the Smart Detector Alert Rule.
|
||||
|
||||
.PARAMETER subscriptionId
|
||||
The subscription ID containing the alert rule.
|
||||
|
||||
.OUTPUTS
|
||||
Returns an array of custom objects containing alert rule details and associated Action Group IDs.
|
||||
|
||||
.EXAMPLE
|
||||
GetSmartDetectorActionGroupIds -alertRuleName "Failure Anomalies - authorization-functions-v2" -resourceGroupName "authorization" -subscriptionId "3190b0fd-4a66-4636-a204-5b9f18be78a6"
|
||||
|
||||
Retrieves Action Group details for the specified Smart Detector Alert Rule.
|
||||
|
||||
.NOTES
|
||||
- Uses REST API version 2019-06-01 for Smart Detector Alert Rules
|
||||
- Requires valid Azure access token for authentication
|
||||
- URL-encodes alert rule names to handle special characters
|
||||
#>
|
||||
function GetSmartDetectorActionGroupIds {
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $alertRuleName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $resourceGroupName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $subscriptionId
|
||||
)
|
||||
|
||||
## example : GetSmartDetectorActionGroupIds -alertRuleName "Failure Anomalies - authorization-functions-v2" -resourceGroupName "authorization" -subscriptionId "3190b0fd-4a66-4636-a204-5b9f18be78a6"
|
||||
|
||||
$escapedAlertRuleName = [uri]::EscapeDataString($alertRuleName)
|
||||
$url = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/microsoft.alertsManagement/smartDetectorAlertRules/$escapedAlertRuleName`?api-version=2019-06-01"
|
||||
$head = @{ Authorization =" Bearer $access_token" }
|
||||
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $head
|
||||
$response | ForEach-Object {
|
||||
$alert = $_
|
||||
$alert.properties.actionGroups
|
||||
| ForEach-Object {
|
||||
$actionGroup = $_
|
||||
$_.groupIds | ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
Id = $alert.id
|
||||
Name = $alert.name
|
||||
Description = $alert.properties.description
|
||||
State = $alert.properties.state
|
||||
Alert = $alert.properties
|
||||
ActionGroups = $alert.actionGroups
|
||||
ActionGroup = $actionGroup
|
||||
ActionGroupId = $_
|
||||
try {
|
||||
# URL-encode the alert rule name to handle special characters
|
||||
$escapedAlertRuleName = [uri]::EscapeDataString($alertRuleName)
|
||||
|
||||
# Construct REST API URL for Smart Detector Alert Rule
|
||||
$url = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/microsoft.alertsManagement/smartDetectorAlertRules/$escapedAlertRuleName`?api-version=2019-06-01"
|
||||
|
||||
# Create authorization header with bearer token
|
||||
$head = @{ Authorization = " Bearer $access_token" }
|
||||
|
||||
# Execute REST API call to retrieve Smart Detector rule details
|
||||
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $head
|
||||
|
||||
# Process response and extract Action Group information
|
||||
$response | ForEach-Object {
|
||||
$alert = $_
|
||||
|
||||
# Process each Action Group associated with the alert rule
|
||||
$alert.properties.actionGroups | ForEach-Object {
|
||||
$actionGroup = $_
|
||||
|
||||
# Extract individual Action Group IDs
|
||||
$_.groupIds | ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
Id = $alert.id
|
||||
Name = $alert.name
|
||||
Description = $alert.properties.description
|
||||
State = $alert.properties.state
|
||||
Alert = $alert.properties
|
||||
ActionGroups = $alert.actionGroups
|
||||
ActionGroup = $actionGroup
|
||||
ActionGroupId = $_
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Failed to retrieve Smart Detector Alert Rule: $alertRuleName in $resourceGroupName. Error: $($_.Exception.Message)"
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sanitizes alert rule descriptions for CSV export by removing newline characters.
|
||||
|
||||
.DESCRIPTION
|
||||
This utility function cleans up alert rule descriptions by replacing newline and carriage return
|
||||
characters with hyphens to ensure proper CSV formatting. It also removes duplicate hyphens
|
||||
that might result from the replacement process.
|
||||
|
||||
.PARAMETER description
|
||||
The description string to sanitize. Can be null or empty.
|
||||
|
||||
.OUTPUTS
|
||||
Returns a cleaned description string suitable for CSV export, or empty string if input is null.
|
||||
|
||||
.EXAMPLE
|
||||
GetDecentDescription -description "Line 1`nLine 2`rLine 3"
|
||||
|
||||
Returns "Line 1 - Line 2 - Line 3"
|
||||
|
||||
.NOTES
|
||||
- Handles null input gracefully
|
||||
- Replaces both Unix (`n) and Windows (`r) newline characters
|
||||
- Removes duplicate hyphens that may result from consecutive newlines
|
||||
#>
|
||||
function GetDecentDescription {
|
||||
param (
|
||||
[AllowEmptyString()]
|
||||
[string] $description
|
||||
)
|
||||
|
||||
if ($null -eq $description) {
|
||||
""
|
||||
# Handle null or empty descriptions
|
||||
if ($null -eq $description -or $description -eq "") {
|
||||
return ""
|
||||
}
|
||||
else {
|
||||
$description.Replace("`n"," - ").Replace("`r"," - ").Replace(" - - "," - ")
|
||||
# Replace newline characters with hyphens and clean up duplicates
|
||||
return $description.Replace("`n", " - ").Replace("`r", " - ").Replace(" - - ", " - ")
|
||||
}
|
||||
}
|
||||
|
||||
# Main script execution begins
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "Starting comprehensive Azure Alert Rules inventory across all enabled subscriptions."
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
# Generate timestamped filename for CSV export
|
||||
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
|
||||
$fileName = ".\$date alert rules.csv"
|
||||
$fileName = ".\$date alert rules.csv"
|
||||
Write-Host "Output file: $fileName"
|
||||
|
||||
# Retrieve all enabled Azure subscriptions
|
||||
Write-Host "Retrieving enabled subscriptions..."
|
||||
$subscriptions = Get-AzSubscription | Where-Object State -eq "Enabled"
|
||||
Write-Host "Found $($subscriptions.Count) enabled subscription(s) to process."
|
||||
|
||||
# Class definition for structured alert rule data
|
||||
class AlertRule {
|
||||
[string] $SubscriptionId = ""
|
||||
[string] $SubscriptionName = ""
|
||||
[string] $Id = ""
|
||||
[string] $ResourceGroupName = ""
|
||||
[string] $Type = ""
|
||||
[string] $Name = ""
|
||||
[string] $Description = ""
|
||||
[string] $State = ""
|
||||
[string] $ActionGroupId = ""
|
||||
[string] $ActionGroupName = ""
|
||||
[string] $ActionGroupResourceGroupName = ""
|
||||
[string] $ActionGroupEnabled = ""
|
||||
[string] $ActionGroupArmRoleReceivers = ""
|
||||
[string] $ActionGroupEmailReceivers = ""
|
||||
[string] $AzureFunctionReceivers = ""
|
||||
[string] $Tag_Team = ""
|
||||
[string] $Tag_Product = ""
|
||||
[string] $Tag_Environment = ""
|
||||
[string] $Tag_Data = ""
|
||||
[string] $Tag_CreatedOnDate = ""
|
||||
[string] $Tag_Deployment = ""
|
||||
# Subscription and resource context
|
||||
[string] $SubscriptionId = "" # Azure subscription GUID
|
||||
[string] $SubscriptionName = "" # Subscription display name
|
||||
[string] $Id = "" # Full Azure resource ID of the alert rule
|
||||
[string] $ResourceGroupName = "" # Resource group containing the alert rule
|
||||
[string] $Type = "" # Azure resource type of the alert rule
|
||||
[string] $Name = "" # Alert rule name
|
||||
|
||||
# Alert rule configuration
|
||||
[string] $Description = "" # Alert rule description (sanitized for CSV)
|
||||
[string] $State = "" # Alert rule state (Enabled/Disabled)
|
||||
|
||||
# Action Group associations
|
||||
[string] $ActionGroupId = "" # Associated Action Group resource ID
|
||||
[string] $ActionGroupName = "" # Action Group name
|
||||
[string] $ActionGroupResourceGroupName = "" # Resource group containing the Action Group
|
||||
[string] $ActionGroupEnabled = "" # Action Group enabled status
|
||||
|
||||
# Action Group receiver details
|
||||
[string] $ActionGroupArmRoleReceivers = "" # ARM role-based receivers (comma-separated)
|
||||
[string] $ActionGroupEmailReceivers = "" # Email receivers (comma-separated)
|
||||
[string] $AzureFunctionReceivers = "" # Azure Function receivers (comma-separated)
|
||||
|
||||
# Governance and metadata tags
|
||||
[string] $Tag_Team = "" # Team responsible for the alert
|
||||
[string] $Tag_Product = "" # Product/service associated with the alert
|
||||
[string] $Tag_Environment = "" # Environment (dev, test, prod, etc.)
|
||||
[string] $Tag_Data = "" # Data classification tag
|
||||
[string] $Tag_CreatedOnDate = "" # Creation date tag
|
||||
[string] $Tag_Deployment = "" # Deployment pipeline tag
|
||||
}
|
||||
|
||||
[Microsoft.Azure.Commands.Insights.OutputClasses.PSActionGroupResource[]]$actionGroups = @()
|
||||
foreach ($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzContext -SubscriptionId $subscription.Id | out-null
|
||||
# Pre-load all Action Groups from all subscriptions for efficient lookup
|
||||
Write-Host "Pre-loading Action Groups from all subscriptions for efficient processing..."
|
||||
[Microsoft.Azure.PowerShell.Cmdlets.Monitor.ActionGroup.Models.IActionGroupResource[]]$actionGroups = @()
|
||||
|
||||
foreach ($subscription in $subscriptions) {
|
||||
Write-Host " Loading Action Groups from subscription: $($subscription.Name)"
|
||||
Set-AzContext -SubscriptionId $subscription.Id | Out-Null
|
||||
$actionGroups += Get-AzActionGroup
|
||||
}
|
||||
|
||||
Write-Host "Loaded $($actionGroups.Count) Action Group(s) across all subscriptions."
|
||||
Write-Host ""
|
||||
|
||||
# Initialize result collection for all alert rules
|
||||
[AlertRule[]]$Result = @()
|
||||
|
||||
foreach ($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzContext -SubscriptionId $subscription.Id
|
||||
# Process each subscription for alert rules
|
||||
foreach ($subscription in $subscriptions) {
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "Processing subscription: [$($subscription.Name)] - $($subscription.Id)"
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
# Set Azure context to current subscription
|
||||
Set-AzContext -SubscriptionId $subscription.Id | Out-Null
|
||||
|
||||
# Process Smart Detector Alert Rules (Application Insights anomaly detection)
|
||||
Write-Host "Processing Smart Detector Alert Rules..."
|
||||
$smartDetectorRules = Get-AzResource -ResourceType "microsoft.alertsmanagement/smartdetectoralertrules"
|
||||
foreach ($smartDetectorRule in $smartDetectorRules)
|
||||
{
|
||||
Write-Host " Found $($smartDetectorRules.Count) Smart Detector Alert Rule(s)"
|
||||
|
||||
foreach ($smartDetectorRule in $smartDetectorRules) {
|
||||
# Retrieve Action Group details for the Smart Detector rule via REST API
|
||||
$actions = GetSmartDetectorActionGroupIds -alertRuleName $smartDetectorRule.Name -resourceGroupName $smartDetectorRule.ResourceGroupName -subscriptionId $subscription.Id
|
||||
|
||||
# Handle Smart Detector rules without Action Groups
|
||||
if (($null -eq $actions) -or ($actions.Length -eq 0)) {
|
||||
# Create alert rule entry without Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
@@ -108,6 +297,8 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.Name = $smartDetectorRule.Name
|
||||
$AlertRule.Type = $smartDetectorRule.ResourceType
|
||||
$AlertRule.ResourceGroupName = $smartDetectorRule.ResourceGroupName
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $smartDetectorRule.Tags.team
|
||||
$AlertRule.Tag_Product = $smartDetectorRule.Tags.product
|
||||
$AlertRule.Tag_Environment = $smartDetectorRule.Tags.environment
|
||||
@@ -118,11 +309,15 @@ foreach ($subscription in $subscriptions)
|
||||
$Result += $AlertRule
|
||||
}
|
||||
else {
|
||||
foreach($action in $actions) {
|
||||
# Process Smart Detector rules with Action Groups
|
||||
foreach ($action in $actions) {
|
||||
# Create alert rule entry with Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
|
||||
$actionGroup = $actionGroups | where { $_.id -eq [uri]::UnescapeDataString($action.ActionGroupId) }
|
||||
# Find corresponding Action Group from pre-loaded collection
|
||||
$actionGroup = $actionGroups | Where-Object { $_.id -eq [uri]::UnescapeDataString($action.ActionGroupId) }
|
||||
|
||||
# Populate basic alert rule information
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
$AlertRule.Id = $smartDetectorRule.Id
|
||||
@@ -133,15 +328,19 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.State = $action.State
|
||||
$AlertRule.ActionGroupId = $action.ActionGroupId
|
||||
|
||||
# Populate Action Group details if found
|
||||
if ($null -ne $actionGroup) {
|
||||
$AlertRule.ActionGroupName = $actionGroup.Name
|
||||
$AlertRule.ActionGroupResourceGroupName = $actionGroup.ResourceGroupName
|
||||
$AlertRule.ActionGroupEnabled = $actionGroup.Enabled
|
||||
|
||||
# Extract receiver information (convert arrays to comma-separated strings)
|
||||
$AlertRule.ActionGroupArmRoleReceivers = [string] ( $actionGroup.ArmRoleReceivers | ForEach-Object { $_.Name } )
|
||||
$AlertRule.ActionGroupEmailReceivers = [string] ( $actionGroup.EmailReceivers | ForEach-Object { $_.EmailAddress } )
|
||||
$AlertRule.AzureFunctionReceivers = [string] ($actionGroup.AzureFunctionReceivers | ForEach-Object { $_.FunctionName } )
|
||||
}
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $smartDetectorRule.Tags.team
|
||||
$AlertRule.Tag_Product = $smartDetectorRule.Tags.product
|
||||
$AlertRule.Tag_Environment = $smartDetectorRule.Tags.environment
|
||||
@@ -154,14 +353,19 @@ foreach ($subscription in $subscriptions)
|
||||
}
|
||||
}
|
||||
|
||||
# microsoft.insights/scheduledqueryrules
|
||||
# Process Scheduled Query Rules (Log Analytics/KQL-based alerts)
|
||||
Write-Host "Processing Scheduled Query Rules (Log Analytics alerts)..."
|
||||
$scheduledQueryRules = Get-AzScheduledQueryRule
|
||||
$scheduledQueryRulesResources = Get-AzResource -ResourceType "microsoft.insights/scheduledqueryrules"
|
||||
foreach($scheduledQueryRule in $scheduledQueryRules) {
|
||||
$resource = $scheduledQueryRulesResources | where { $_.id -eq $scheduledQueryRule.Id }
|
||||
Write-Host " Found $($scheduledQueryRules.Count) Scheduled Query Rule(s)"
|
||||
|
||||
foreach ($scheduledQueryRule in $scheduledQueryRules) {
|
||||
# Get corresponding resource for tag information
|
||||
$resource = $scheduledQueryRulesResources | Where-Object { $_.id -eq $scheduledQueryRule.Id }
|
||||
|
||||
if (($null -eq $scheduledQueryRule.ActionGroup) -or ($scheduledQueryRule.ActionGroup.Length -eq 0))
|
||||
{
|
||||
# Handle Scheduled Query Rules without Action Groups
|
||||
if (($null -eq $scheduledQueryRule.ActionGroup) -or ($scheduledQueryRule.ActionGroup.Length -eq 0)) {
|
||||
# Create alert rule entry without Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
@@ -171,57 +375,71 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.ResourceGroupName = $resource.ResourceGroupName
|
||||
$AlertRule.Description = GetDecentDescription $scheduledQueryRule.Description
|
||||
$AlertRule.State = $scheduledQueryRule.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
$AlertRule.Tag_Team = $smartDetectorRule.Tags.team
|
||||
$AlertRule.Tag_Product = $smartDetectorRule.Tags.product
|
||||
$AlertRule.Tag_Environment = $smartDetectorRule.Tags.environment
|
||||
$AlertRule.Tag_Data = $smartDetectorRule.Tags.data
|
||||
$AlertRule.Tag_CreatedOnDate = $smartDetectorRule.Tags.CreatedOnDate
|
||||
$AlertRule.Tag_Deployment = $smartDetectorRule.Tags.drp_deployment
|
||||
|
||||
# Extract governance tags from the resource (note: using $resource instead of $smartDetectorRule)
|
||||
$AlertRule.Tag_Team = $resource.Tags.team
|
||||
$AlertRule.Tag_Product = $resource.Tags.product
|
||||
$AlertRule.Tag_Environment = $resource.Tags.environment
|
||||
$AlertRule.Tag_Data = $resource.Tags.data
|
||||
$AlertRule.Tag_CreatedOnDate = $resource.Tags.CreatedOnDate
|
||||
$AlertRule.Tag_Deployment = $resource.Tags.drp_deployment
|
||||
|
||||
$Result += $AlertRule
|
||||
}
|
||||
else {
|
||||
foreach($action in $scheduledQueryRule.ActionGroup) {
|
||||
# Process Scheduled Query Rules with Action Groups
|
||||
foreach ($action in $scheduledQueryRule.ActionGroup) {
|
||||
# Create alert rule entry with Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
|
||||
$actionGroup = $actionGroups | where { $_.id -eq [uri]::UnescapeDataString($action) }
|
||||
# Find corresponding Action Group from pre-loaded collection
|
||||
$actionGroup = $actionGroups | Where-Object { $_.id -eq [uri]::UnescapeDataString($action) }
|
||||
|
||||
# Populate basic alert rule information
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
$AlertRule.Id = $scheduledQueryRule.Id
|
||||
$AlertRule.Name = $scheduledQueryRule.Name
|
||||
$AlertRule.Type = $scheduledQueryRule.Type
|
||||
$AlertRule.ResourceGroupName = $resource.ResourceGroupName
|
||||
$AlertRule.Description = GetDecentDescription $scheduledQueryRule.Description
|
||||
$AlertRule.Description = GetDecentDescription $scheduledQueryRule.Description
|
||||
$AlertRule.State = $scheduledQueryRule.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
$AlertRule.ActionGroupId = $action
|
||||
|
||||
# Populate Action Group details if found
|
||||
if ($null -ne $actionGroup) {
|
||||
$AlertRule.ActionGroupName = $actionGroup.Name
|
||||
$AlertRule.ActionGroupResourceGroupName = $actionGroup.ResourceGroupName
|
||||
$AlertRule.ActionGroupEnabled = $actionGroup.Enabled
|
||||
|
||||
# Extract receiver information (convert arrays to comma-separated strings)
|
||||
$AlertRule.ActionGroupArmRoleReceivers = [string] ( $actionGroup.ArmRoleReceivers | ForEach-Object { $_.Name } )
|
||||
$AlertRule.ActionGroupEmailReceivers = [string] ( $actionGroup.EmailReceivers | ForEach-Object { $_.EmailAddress } )
|
||||
$AlertRule.AzureFunctionReceivers = [string] ($actionGroup.AzureFunctionReceivers | ForEach-Object { $_.FunctionName } )
|
||||
}
|
||||
|
||||
$AlertRule.Tag_Team = $smartDetectorRule.Tags.team
|
||||
$AlertRule.Tag_Product = $smartDetectorRule.Tags.product
|
||||
$AlertRule.Tag_Environment = $smartDetectorRule.Tags.environment
|
||||
$AlertRule.Tag_Data = $smartDetectorRule.Tags.data
|
||||
$AlertRule.Tag_CreatedOnDate = $smartDetectorRule.Tags.CreatedOnDate
|
||||
$AlertRule.Tag_Deployment = $smartDetectorRule.Tags.drp_deployment
|
||||
# Extract governance tags from the resource
|
||||
$AlertRule.Tag_Team = $resource.Tags.team
|
||||
$AlertRule.Tag_Product = $resource.Tags.product
|
||||
$AlertRule.Tag_Environment = $resource.Tags.environment
|
||||
$AlertRule.Tag_Data = $resource.Tags.data
|
||||
$AlertRule.Tag_CreatedOnDate = $resource.Tags.CreatedOnDate
|
||||
$AlertRule.Tag_Deployment = $resource.Tags.drp_deployment
|
||||
|
||||
$Result += $AlertRule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Microsoft.Insights/metricAlerts
|
||||
# Process Metric Alert Rules (Resource metric-based alerts)
|
||||
Write-Host "Processing Metric Alert Rules..."
|
||||
$metricAlerts = Get-AzMetricAlertRuleV2
|
||||
foreach($metricAlert in $metricAlerts) {
|
||||
if (($null -eq $metricAlert.Actions) -or ($metricAlert.Actions.Length -eq 0))
|
||||
{
|
||||
Write-Host " Found $($metricAlerts.Count) Metric Alert Rule(s)"
|
||||
|
||||
foreach ($metricAlert in $metricAlerts) {
|
||||
# Handle Metric Alerts without Action Groups
|
||||
if (($null -eq $metricAlert.Actions) -or ($metricAlert.Actions.Length -eq 0)) {
|
||||
# Create alert rule entry without Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
@@ -231,6 +449,8 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.ResourceGroupName = $metricAlert.ResourceGroup
|
||||
$AlertRule.Description = GetDecentDescription $metricAlert.Description
|
||||
$AlertRule.State = $metricAlert.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $metricAlert.Tags.team
|
||||
$AlertRule.Tag_Product = $metricAlert.Tags.product
|
||||
$AlertRule.Tag_Environment = $metricAlert.Tags.environment
|
||||
@@ -241,11 +461,15 @@ foreach ($subscription in $subscriptions)
|
||||
$Result += $AlertRule
|
||||
}
|
||||
else {
|
||||
foreach($action in $metricAlert.Actions) {
|
||||
# Process Metric Alerts with Action Groups
|
||||
foreach ($action in $metricAlert.Actions) {
|
||||
# Create alert rule entry with Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
|
||||
$actionGroup = $actionGroups | where { $_.id -eq [uri]::UnescapeDataString($action.ActionGroupId) }
|
||||
# Find corresponding Action Group from pre-loaded collection
|
||||
$actionGroup = $actionGroups | Where-Object { $_.id -eq [uri]::UnescapeDataString($action.ActionGroupId) }
|
||||
|
||||
# Populate basic alert rule information
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
$AlertRule.Id = $metricAlert.Id
|
||||
@@ -256,15 +480,19 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.State = $metricAlert.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
$AlertRule.ActionGroupId = $action.ActionGroupId
|
||||
|
||||
# Populate Action Group details if found
|
||||
if ($null -ne $actionGroup) {
|
||||
$AlertRule.ActionGroupName = $actionGroup.Name
|
||||
$AlertRule.ActionGroupResourceGroupName = $actionGroup.ResourceGroupName
|
||||
$AlertRule.ActionGroupEnabled = $actionGroup.Enabled
|
||||
|
||||
# Extract receiver information (convert arrays to comma-separated strings)
|
||||
$AlertRule.ActionGroupArmRoleReceivers = [string] ( $actionGroup.ArmRoleReceivers | ForEach-Object { $_.Name } )
|
||||
$AlertRule.ActionGroupEmailReceivers = [string] ( $actionGroup.EmailReceivers | ForEach-Object { $_.EmailAddress } )
|
||||
$AlertRule.AzureFunctionReceivers = [string] ($actionGroup.AzureFunctionReceivers | ForEach-Object { $_.FunctionName } )
|
||||
}
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $metricAlert.Tags.team
|
||||
$AlertRule.Tag_Product = $metricAlert.Tags.product
|
||||
$AlertRule.Tag_Environment = $metricAlert.Tags.environment
|
||||
@@ -277,13 +505,15 @@ foreach ($subscription in $subscriptions)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Microsoft.Insights/ActivityLogAlerts
|
||||
# Process Activity Log Alert Rules (Azure Activity Log event alerts)
|
||||
Write-Host "Processing Activity Log Alert Rules..."
|
||||
$activityLogAlerts = Get-AzActivityLogAlert
|
||||
foreach($activityLogAlert in $activityLogAlerts) {
|
||||
|
||||
if (($null -eq $activityLogAlert.ActionGroup) -or ($activityLogAlert.ActionGroup.Length -eq 0))
|
||||
{
|
||||
Write-Host " Found $($activityLogAlerts.Count) Activity Log Alert Rule(s)"
|
||||
|
||||
foreach ($activityLogAlert in $activityLogAlerts) {
|
||||
# Handle Activity Log Alerts without Action Groups
|
||||
if (($null -eq $activityLogAlert.ActionGroup) -or ($activityLogAlert.ActionGroup.Length -eq 0)) {
|
||||
# Create alert rule entry without Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
@@ -293,6 +523,8 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.ResourceGroupName = $activityLogAlert.ResourceGroupName
|
||||
$AlertRule.Description = GetDecentDescription $activityLogAlert.Description
|
||||
$AlertRule.State = $activityLogAlert.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $activityLogAlert.Tags.team
|
||||
$AlertRule.Tag_Product = $activityLogAlert.Tags.product
|
||||
$AlertRule.Tag_Environment = $activityLogAlert.Tags.environment
|
||||
@@ -303,11 +535,15 @@ foreach ($subscription in $subscriptions)
|
||||
$Result += $AlertRule
|
||||
}
|
||||
else {
|
||||
foreach($action in $activityLogAlert.ActionGroup) {
|
||||
# Process Activity Log Alerts with Action Groups
|
||||
foreach ($action in $activityLogAlert.ActionGroup) {
|
||||
# Create alert rule entry with Action Group details
|
||||
[AlertRule] $AlertRule = [AlertRule]::new()
|
||||
|
||||
$actionGroup = $actionGroups | where { $_.id -eq [uri]::UnescapeDataString($action.Id) }
|
||||
# Find corresponding Action Group from pre-loaded collection
|
||||
$actionGroup = $actionGroups | Where-Object { $_.id -eq [uri]::UnescapeDataString($action.Id) }
|
||||
|
||||
# Populate basic alert rule information
|
||||
$AlertRule.SubscriptionId = $subscription.Id
|
||||
$AlertRule.SubscriptionName = $subscription.Name
|
||||
$AlertRule.Id = $activityLogAlert.Id
|
||||
@@ -318,15 +554,19 @@ foreach ($subscription in $subscriptions)
|
||||
$AlertRule.State = $activityLogAlert.Enabled -eq $true ? "Enabled" : "Disabled"
|
||||
$AlertRule.ActionGroupId = $action.Id
|
||||
|
||||
# Populate Action Group details if found
|
||||
if ($null -ne $actionGroup) {
|
||||
$AlertRule.ActionGroupName = $actionGroup.Name
|
||||
$AlertRule.ActionGroupResourceGroupName = $actionGroup.ResourceGroupName
|
||||
$AlertRule.ActionGroupEnabled = $actionGroup.Enabled
|
||||
|
||||
# Extract receiver information (convert arrays to comma-separated strings)
|
||||
$AlertRule.ActionGroupArmRoleReceivers = [string] ( $actionGroup.ArmRoleReceivers | ForEach-Object { $_.Name } )
|
||||
$AlertRule.ActionGroupEmailReceivers = [string] ( $actionGroup.EmailReceivers | ForEach-Object { $_.EmailAddress } )
|
||||
$AlertRule.AzureFunctionReceivers = [string] ($actionGroup.AzureFunctionReceivers | ForEach-Object { $_.FunctionName } )
|
||||
}
|
||||
|
||||
# Extract governance tags
|
||||
$AlertRule.Tag_Team = $activityLogAlert.Tags.team
|
||||
$AlertRule.Tag_Product = $activityLogAlert.Tags.product
|
||||
$AlertRule.Tag_Environment = $activityLogAlert.Tags.environment
|
||||
@@ -338,8 +578,54 @@ foreach ($subscription in $subscriptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Completed processing subscription: $($subscription.Name)"
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Export results and display summary
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "Exporting results and generating summary..."
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
# Export comprehensive alert rules data to CSV
|
||||
$Result | Export-Csv -Path $fileName -NoTypeInformation -Force
|
||||
|
||||
$Result | ft
|
||||
# Generate summary statistics
|
||||
$summaryStats = @{
|
||||
TotalAlertRules = $Result.Count
|
||||
SmartDetectorRules = ($Result | Where-Object { $_.Type -eq "microsoft.alertsmanagement/smartdetectoralertrules" }).Count
|
||||
ScheduledQueryRules = ($Result | Where-Object { $_.Type -eq "microsoft.insights/scheduledqueryrules" }).Count
|
||||
MetricAlerts = ($Result | Where-Object { $_.Type -eq "Microsoft.Insights/metricAlerts" }).Count
|
||||
ActivityLogAlerts = ($Result | Where-Object { $_.Type -eq "Microsoft.Insights/ActivityLogAlerts" }).Count
|
||||
EnabledRules = ($Result | Where-Object { $_.State -eq "Enabled" }).Count
|
||||
DisabledRules = ($Result | Where-Object { $_.State -eq "Disabled" }).Count
|
||||
RulesWithActionGroups = ($Result | Where-Object { $_.ActionGroupId -ne "" }).Count
|
||||
RulesWithoutActionGroups = ($Result | Where-Object { $_.ActionGroupId -eq "" }).Count
|
||||
}
|
||||
|
||||
Write-Host "Alert Rules Inventory Summary:"
|
||||
Write-Host "==============================="
|
||||
Write-Host "Total Alert Rules Found: $($summaryStats.TotalAlertRules)"
|
||||
Write-Host ""
|
||||
Write-Host "By Alert Type:"
|
||||
Write-Host " Smart Detector Rules: $($summaryStats.SmartDetectorRules)"
|
||||
Write-Host " Scheduled Query Rules (Log Analytics): $($summaryStats.ScheduledQueryRules)"
|
||||
Write-Host " Metric Alert Rules: $($summaryStats.MetricAlerts)"
|
||||
Write-Host " Activity Log Alert Rules: $($summaryStats.ActivityLogAlerts)"
|
||||
Write-Host ""
|
||||
Write-Host "By State:"
|
||||
Write-Host " Enabled Rules: $($summaryStats.EnabledRules)"
|
||||
Write-Host " Disabled Rules: $($summaryStats.DisabledRules)"
|
||||
Write-Host ""
|
||||
Write-Host "By Action Group Association:"
|
||||
Write-Host " Rules with Action Groups: $($summaryStats.RulesWithActionGroups)"
|
||||
Write-Host " Rules without Action Groups: $($summaryStats.RulesWithoutActionGroups)"
|
||||
Write-Host ""
|
||||
Write-Host "Results exported to: $fileName"
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
# Display formatted table output to console
|
||||
Write-Host ""
|
||||
Write-Host "Detailed Alert Rules (displaying first 50 rows):"
|
||||
$Result | Select-Object -First 50 | Format-Table -AutoSize
|
||||
Reference in New Issue
Block a user