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." } # 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' } 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 = $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 | Out-Null $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 } } |