Public/Deploy/Core/monitoring/New-CmAzCoreMonitor.ps1
function New-CmAzCoreMonitor { <# .Synopsis Deploys monitoring for core resources. .Description Completes the following: * Deploys log analytics, app insights and storage accountp. * Deploys management solutions for keyvaults, subscription activity, agent health, updates and VM insights. * Deploys action groups and alerts for service health, keyvault admin and resource health for applicable core resources. .Parameter SettingsFile File path for the settings file to be converted into a settings object. .Parameter SettingsObject Object containing the configuration values required to run this cmdlet. .Parameter TagSettingsFile File path for settings containing tags definition. .Component Core .Example New-CmAzCoreMonitor -SettingsFile "c:/directory/settingsFile.yml" .Example New-CmAzCoreMonitor -SettingsObject $settings #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] param( [parameter(Mandatory = $true, ParameterSetName = "Settings File")] [string]$SettingsFile, [parameter(Mandatory = $true, ParameterSetName = "Settings Object")] [object]$SettingsObject, [AllowEmptyString()] [String]$TagSettingsFile ) $ErrorActionPreference = "Stop" try { Get-InvocationInfo -CommandName $MyInvocation.MyCommand.Name if ($PSCmdlet.ShouldProcess((Get-CmAzSubscriptionName), "Deploy Core Monitoring")) { if ($SettingsFile -and -not $SettingsObject) { $SettingsObject = Get-CmAzSettingsFile -Path $SettingsFile } elseif (-not $SettingsFile -and -not $SettingsObject) { Write-Error "No valid input settings." -Category InvalidArgument -CategoryTargetName "SettingsObject" } if (!$SettingsObject.name) { Write-Error "Please provide a valid name." -Category InvalidArgument -CategoryTargetName "Name" } if (!$SettingsObject.location) { Write-Error "Please provide a valid location." -Category InvalidArgument -CategoryTargetName "Location" } if (!$SettingsObject.actionGroups) { Write-Error "Please provide at least one action group." -Category InvalidArgument -CategoryTargetName "ActionGroups" } foreach ($key in $SettingsObject.alerts.keys) { $alert = $SettingsObject.alerts[$key] if (($SettingsObject.actionGroups | Where-Object { $_.name -eq $alert.actionGroupName}).count -eq 0 ) { Write-Error "Action group $($alert.actionGroupName) not found in settings." -Category InvalidArgument -CategoryTargetName "actionGroupName" } } $appInsights = Get-CmAzResourceName -Resource "ApplicationInsights" -Architecture "Core" -Region $SettingsObject.location -Name $SettingsObject.name $workspace = Get-CmAzResourceName -Resource "LogAnalyticsWorkspace" -Architecture "Core" -Region $SettingsObject.location -Name $SettingsObject.name Write-Verbose "Formatting action group receivers..." $receiverTypes = @("armRoles", "emails", "functions", "itsm", "logicApps", "notifications", "runbooks", "sms", "voice", "webhooks") $nameKey = "name" foreach ($actionGroup in $SettingsObject.actionGroups) { if(!$actionGroup.name -or !$actionGroup.shortName) { Write-Error "Please ensure a action group has a name, a shortname and at least one receiver." -Category InvalidArgument -CategoryTargetName "ActionGroups" } foreach ($receiverType in $receiverTypes) { $receivers = $actionGroup[$receiverType] if (!$receivers) { $actionGroup[$receiverType] = @() continue } for ($j = 0; $j -lt $receivers.count; $j++) { $receivers[$j][$nameKey] = Get-CmAzResourceName -Resource "ActionGroupReceiver" -Architecture "Core" -Region $SettingsObject.Location -Name "$($actionGroup[$nameKey])$($receiverType)-$($j)" } } $actionGroup[$nameKey] = Get-CmAzResourceName -Resource "ActionGroup" -Architecture "Core" -Region $SettingsObject.Location -Name $actionGroup[$nameKey] Set-GlobalServiceValues -GlobalServiceContainer $SettingsObject -ServiceKey "actionGroup" -ResourceServiceContainer $actiongroup } Write-Verbose "Setting alerts..." $keyvaultAdminAlert = @{ $nameKey = Get-CmAzResourceName -Resource "Alert" -Architecture "Core" -Region "Global"-Name "$($SettingsObject.name)-KeyvaultAdmin"; "actionGroupName" = Get-CmAzResourceName -Resource "ActionGroup" -Architecture "Core" -Region $SettingsObject.Location -Name $SettingsObject.alerts.keyvaultAdmin.actionGroupName; "enabled" = $SettingsObject.alerts.keyvaultAdmin.enabled ??= $false; "servicePublish" = $SettingsObject.service.publish.keyvaultAdminAlert; "conditions" = @( @{ "field" = "category"; "equals" = "Administrative"; }, @{ "field" = "resourceType"; "equals" = "Microsoft.Keyvault/Vaults"; } ); } $resourceHealthAlert = @{ $nameKey = Get-CmAzResourceName -Resource "Alert" -Architecture "Core" -Region "Global"-Name "$($SettingsObject.name)-ResourceHealth"; "actionGroupName" = Get-CmAzResourceName -Resource "ActionGroup" -Architecture "Core" -Region $SettingsObject.Location -Name $SettingsObject.alerts.resourceHealth.actionGroupName; "enabled" = $SettingsObject.alerts.resourceHealth.enabled ??= $false; "servicePublish" = $SettingsObject.service.publish.resourceHealthAlert; "conditions" = @( @{ "field" = "category"; "equals" = "ResourceHealth"; }, @{ "field" = "resourceType"; "equals" = "Microsoft.Keyvault/Vaults"; }, @{ "field" = "resourceType"; "equals" = "Microsoft.OperationalInsights/Workspaces"; }, @{ "field" = "resourceType"; "equals" = "Microsoft.Storage/StorageAccounts"; } ); } $serviceHealthAlert = @{ $nameKey = Get-CmAzResourceName -Resource "Alert" -Architecture "Core" -Region "Global"-Name "$($SettingsObject.name)-ServiceHealth"; "actionGroupName" = Get-CmAzResourceName -Resource "ActionGroup" -Architecture "Core" -Region $SettingsObject.Location -Name $SettingsObject.alerts.serviceHealth.actionGroupName; "enabled" = $SettingsObject.alerts.serviceHealth.enabled ??= $false; "servicePublish" = $SettingsObject.service.publish.serviceHealthAlert; "conditions" = @( @{ "field" = "category"; "equals" = "ServiceHealth"; }, @{ "field" = "properties.impactedServices[*].ImpactedRegions[*].RegionName"; "containsAny" = $SettingsObject.alerts.serviceHealth.impactedLocations ?? @($SettingsObject.location); } ); } $SettingsObject.alerts = @($keyvaultAdminAlert, $resourceHealthAlert, $serviceHealthAlert) Write-Verbose "Generating resource names..." $resourceGroupName = Get-CmAzResourceName -Resource "ResourceGroup" -Architecture "Core" -Region $SettingsObject.Location -Name $SettingsObject.name Write-Verbose "Deploying resource group ($resourceGroupName)..." New-AzResourceGroup ` -Name $resourceGroupName ` -Location $SettingsObject.location ` -Tag @{ "cm-service" = $SettingsObject.service.publish.resourceGroup } ` -Force Write-Verbose "Deploying storage..." $storageObject = @{ location = $SettingsObject.location; service = @{ dependencies = @{ ResourceGroup = $SettingsObject.service.publish.resourceGroup }; publish = @{ storage = $SettingsObject.service.publish.storage } } storageAccounts = @(@{ storageAccountName = $SettingsObject.name; accountType = "Standard"; blobContainer = @( @{ name = "insights-logs-addonazurebackuppolicy"}, @{ name = "insights-logs-azurebackupreport"}, @{ name = "insights-logs-coreazurebackup"}, @{ name = "insights-logs-networksecuritygroupflowevent"} ) }) } New-CmAzIaasStorage -SettingsObject $storageObject -OmitTags Write-Verbose "Deploying monitor resources..." New-AzResourceGroupDeployment ` -ResourceGroupName $resourceGroupName ` -TemplateFile "$PSScriptRoot/New-CmAzCoreMonitor.json" ` -ActionGroups $SettingsObject.actionGroups ` -Alerts $SettingsObject.alerts ` -AppInsightsName $appInsights ` -ServiceContainer $SettingsObject.service.publish ` -WorkspaceName $workspace ` -Force Write-Verbose "Setting advisor configuration cpu threshold..." if(!$SettingsObject.AdvisorLowCPUThresholdPercentage -or @(0, 5, 10, 15, 20) -NotContains $SettingsObject.AdvisorLowCPUThresholdPercentage) { Write-Error "Please provide a valid low cpu threshold percentage, valid percentages are 0, 5, 10, 15, 20." -Category InvalidArgument -CategoryTargetName "AdvisorLowCPUThresholdPercentage" } Set-AzAdvisorConfiguration -LowCpuThreshold $SettingsObject.AdvisorLowCPUThresholdPercentage Set-DeployedResourceTags -TagSettingsFile $TagSettingsFile -ResourceGroupIds @($resourceGroupName) Write-Verbose "Finished!" } } catch { $PSCmdlet.ThrowTerminatingError($PSItem); } } |