public/New-AzureMonitorDeployment.ps1

function New-AzureMonitorDeployment {

<#
 
.SYNOPSIS
 
Deploy new azure monitor [metric] alerts.
 
.DESCRIPTION
 
Deploy new azure monitor [metric] alerts.
 
.PARAMETER webhookUri
URI to configure for alert webhooks.
 
.PARAMETER jsonObject
 
Defines the alerts that will be associated to/configured for all corresponding Azure resource types:
 
$jsonParams = @"
{
 
    "alerts": [
 
 
 
        {
            alertClass: "Microsoft.Compute/VirtualMachines",
            priority: "P1"
            "metricName": "Network Out",
            "Operator": "GreaterThan",
            "Threshold": "15",
            "windowSize" : "00:05:00",
            "timeAggregationOpeartor" : "Total",
            "Description": "network out",
            "Name": "network15 out test"
        }
 
    ]
}
"@
 
 
 
.PARAMETER customerName
Will add the customer's name as a tag in the webhook payload.
 
.EXAMPLE
 
$output = New-AzureMonitorDeployment -webhookUri <webhookuri> -jsonObject <jsondata> -customerName <customer name> -Verbose
 
#>


[CmdletBinding()]

    Param (

        
        [Parameter(Mandatory=$true)]
        [string]$webhookUri,

        [Parameter(Mandatory=$true)]
        [object]$jsonObject,

        [Parameter(Mandatory=$true)]
        [string]$customerName

    
    )

    Process {


        # Convert json object to psobject
        try {
            $alertData = $jsonObject | ConvertFrom-Json -ErrorAction Stop -Verbose
        }
        catch {
            throw "Unable to convert json objct to pscustomobject, error was : $($error[0].Exception)"
        }


        # check to see if local token exists (ran Login-AzureRMAccount)
        if (($null -eq (Get-AzureRmContext).Account)) {
            throw "No authentication token found, run < Login-AzureRMAccount > to proceed...exiting."
        } 

   
        # check if subscription has been selected
        if (($null -eq (Get-AzureRmContext).subscription)) {
            throw "No subscrition selected, run < Select-AzureRMSubscription -subscriptionID 'id of target subscription' >...exiting."
        } 

        # Get resource groups, itterate through and remove all alerts.
        Try {
            $resourceGroups = Get-AzureRmResourceGroup -Verbose -ErrorAction Stop
        }
        Catch {
            $error[0].Exception
            break
        }

        foreach ($rg in $resourceGroups) {
            $alerts = Get-AzureRmAlertRule -ResourceGroup $rg.resourcegroupname -Verbose -ErrorAction Stop
            $alerts | ForEach-Object {
                try {
                    Remove-AzureRmAlertRule -ResourceGroup $rg.resourcegroupname -Name $_.Name -Verbose -ErrorAction Stop | Out-Null
                    Write-Verbose "Removing alert rulewith name '$($_.name)' from resource group '$($rg.resourcegroupname)'."

                }
                catch {
                    $error[0].Exception
                }
            }
        }
        
        # declare cols for returned object/ouput (add entire resource object)
        $output = @()

        
        # find unique alert classes
        $knownAlertClasses = $alertData.alerts.alertclass | select -Unique
        Write-Verbose "Found following alert classes: $($knownAlertClasses -join (','))."

        foreach ($alertClass in $knownAlertClasses) {
            # find azure resources of matching alertClass
            try {
                $resources = Find-AzureRmResource -ResourceType $alertClass -ErrorAction Stop -Verbose
                
                if ($null -eq $resources) {
                    Write-Verbose "No resources of resourceType matching $alertClass"
                }

                # find alerts for corresponding alert class
                $alertsToConfigure = $alertData.alerts.Where({$_.alertClass -eq $alertClass})

                # loops through all resources matching alertClass and add metric alerts
                foreach ($resource in $resources) {
                    
                    Write-Verbose "Working on $($resource.name)"

                    if (($null -eq $resource.tags.'Resource Class')) {
                        Write-Warning "No 'Resource Class' tag found on resource: $($resource.name)"
                        
                        $status = New-Object -TypeName psobject
                        $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                        $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                        $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "No 'Resource Class' found"

                        $output += $status
                    }
                    else {
                        # replace space with underscore
                        try {
                            $ErrorActionPreference = 'stop'
                            $parsedTag = $($resource.tags.'Resource Class') -replace ' ', '_'
                        }
                        Catch {
                            $error[0].Exception
                            
                            $status = New-Object -TypeName psobject
                            $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                            $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                            $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                            $output += $status
                            break
                        }
                        finally {
                            $ErrorActionPreference = 'Continue'
                        }

                        # Remove existing alerts (only alerts in template should exist).


                        foreach ($alert in $alertsToConfigure) {

                            # determine alert severity and register webhook
                            if (($alert.priority -eq 'P1') -and ($resource.tags.'Resource Class' -eq 'Class A')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Urgent';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P1') -and ($resource.tags.'Resource Class' -eq 'Class B')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'High';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P1') -and ($resource.tags.'Resource Class' -eq 'Class C')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Normal';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P2') -and ($resource.tags.'Resource Class' -eq 'Class A')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'High';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P2') -and ($resource.tags.'Resource Class' -eq 'Class B')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Normal';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P2') -and ($resource.tags.'Resource Class' -eq 'Class C')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Low';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P3') -and ($resource.tags.'Resource Class' -eq 'Class A')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Normal';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P3') -and ($resource.tags.'Resource Class' -eq 'Class B')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Low';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            elseif (($alert.priority -eq 'P3') -and ($resource.tags.'Resource Class' -eq 'Class C')) {
                                try {
                                    $actionWebhook = New-AzureRmAlertRuleWebhook -ServiceUri $webhookUri -Properties @{'severity' = 'Low';'CustomerName' = "$customerName"} -ErrorAction Stop -Verbose
                                }
                                catch {
                                    throw "Unable to register webhook, error was: $($error[0].exception)"

                                    $status = New-Object -TypeName psobject
                                    $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                    $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                    $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                    $output += $status

                                }
                            }

                            else {
                                Write-Warning "Failed to determine alert severity."
                                $status = New-Object -TypeName psobject
                                $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Failed to determine alert severity"

                                $output += $status

                                break

                            }

                        
                            # build params to splat
                            $parms = @{
                                WindowSize = $alert.windowsize;
                                Operator   = $alert.operator;
                                Threshold  = $alert.threshold;
                                TargetResourceID = $resource.resourceID;
                                MetricName = $alert.metricName;
                                TimeAggregationOperator = $alert.timeAggregationOpeartor;
                                Description = $alert.description;
                                Name = "$($resource.name)" + ' - ' + "$($alert.Name)";
                                Action = $actionWebhook;
                                Location = $resource.location;
                                ResourceGroup = $resource.resourceGroupName;
                                ErrorAction = 'Continue'
                            }

                            try {
                                # don't worry about validating if it already exists, cmdlet gracefully handles that (or so it seems)
                                Add-AzureRmMetricAlertRule @parms -Verbose
                                
                                $status = New-Object -TypeName psobject
                                $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'success'
                                $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Successfully configured alert: $($alert.name)"

                                $output += $status

                            }
                            catch {
                                Write-Error "Failed to configure alert $($alert.name) for resource $($resource.name). Error was: $($error[0].exception)"
                                
                                $status = New-Object -TypeName psobject
                                $status | Add-Member -MemberType NoteProperty -Name 'nodeName' -Value "$($resource.name)"
                                $status | Add-Member -MemberType NoteProperty -Name 'status' -Value 'failed'
                                $status | Add-Member -MemberType NoteProperty -Name 'statusMessage' -Value "Exception: $($error[0].Exception)"

                                $output += $status

                                continue
                            }
                        }
                    
                    }

                }

            }
            catch {
                throw "Unable to retreive resources indexed by resourceType: $alertClass. Error was: $($error[0].Exception)"
            }
        }
        
        return $output
    }

}