Azure Monitor Alert Rules: Ontwerp, Implementatie En Governance

💼 Management Samenvatting

Azure Monitor-alertregels vormen het zenuwstelsel van een moderne cloudomgeving: zij vertalen technische signalen naar concrete acties zodat incidenten vroegtijdig worden opgemerkt en gestructureerd worden opgevolgd. Zonder goed ontworpen en beheerde alert rules blijft monitoring een berg ruwe data zonder richting of handelingsperspectief.

Aanbeveling
IMPLEMENT
Risico zonder
High
Risk Score
8/10
Implementatie
24u (tech: 16u)
Van toepassing op:
Azure
Hybride omgevingen

Veel Nederlandse overheidsorganisaties beschikken intussen over uitgebreide logging in Azure, maar hebben de stap naar volwassen monitoring en alertering nog niet volledig gezet. In de praktijk zien we twee uitersten: aan de ene kant omgevingen zonder kritieke alerts, waardoor serieuze beveiligings- of beschikbaarheidsincidenten pas laat worden ontdekt; aan de andere kant tenants met honderden generieke alerts die continu afgaan en leiden tot alert-moeheid bij beheerders. In beide gevallen is de uitkomst hetzelfde: incidenten worden te laat of helemaal niet opgepakt, escalatieketens werken niet, en bestuurders krijgen geen betrouwbaar beeld van de werkelijke risico’s. Dit is extra problematisch in de publieke sector, waar uitval van digitale diensten direct impact heeft op burgers, bedrijven en ketenpartners, en waar toezichthouders steeds vaker aantoonbare monitoring en alertering eisen in het kader van BIO, NIS2 en sectorspecifieke regelgeving.

PowerShell Modules Vereist
Primary API: Azure Monitor
Connection: Connect-AzAccount
Required Modules: Az.Accounts, Az.Monitor, Az.Resources

Implementatie

Dit artikel beschrijft hoe u een doordachte set Azure Monitor-alertregels ontwerpt, implementeert en beheert voor een Azure-tenant die kritieke overheidsprocessen ondersteunt. We starten met het vertalen van risico’s en business requirements naar concrete alerts, werken uit hoe u signalen uit platformlogboeken, metrische data en workload-specifieke bronnen combineert, en tonen hoe u ruis minimaliseert door slimme drempelwaarden, dynamische detectie en onderhoud van suppressieregels. Vervolgens laten we zien hoe u de implementatie en het beheer van alert rules automatiseert met PowerShell en Infrastructure as Code, zodat nieuwe abonnementen en workloads automatisch de juiste monitoring meekrijgen. Tot slot gaan we in op governance, rapportage en compliance: hoe borgt u eigenaarschap, hoe maakt u de effectiviteit van alerts inzichtelijk, en hoe gebruikt u de bijbehorende PowerShell-scriptreferentie alert-rules-deployment.ps1 om de inrichting periodiek te toetsen en te verbeteren.

Van Risico’s naar Alert Architectuur: Ontwerpprincipes voor Azure Monitor

Een effectieve alertinrichting begint niet bij techniek, maar bij een heldere analyse van risico’s en kritieke processen. Voor een Nederlandse overheidsorganisatie betekent dit dat u eerst in kaart brengt welke diensten absoluut beschikbaar moeten blijven – denk aan burgerzaken, omgevingsvergunningen, uitkeringssystemen of meldkamers – en welke Azure-resources en -platformdiensten daar direct aan bijdragen. Vanuit deze businesskant bepaalt u vervolgens welke gebeurtenissen zo belangrijk zijn dat zij altijd een alert moeten genereren: bijvoorbeeld mislukte back-ups, uitval van een cluster, afwijkende prestaties, mislukte authenticaties op beheerdersaccounts of uitschakeling van belangrijke beveiligingsfuncties. Dit voorkomt dat u willekeurig alerts aanzet op basis van technische mogelijkheden in plaats van echte informatiebehoefte. Daarna vertaalt u deze risico’s naar een hiërarchie van signalen. Op het hoogste niveau definieert u tenant-brede alerts, bijvoorbeeld rond identity, netwerkconnectiviteit en beveiligingspostuur, die gelden voor alle abonnementen en workloads. Op een lager niveau specificeert u workload-specifieke alerts, bijvoorbeeld voor een kritieke webapplicatie of een data-analyseplatform. Voor iedere alert legt u expliciet vast: het bewaakte object (resource, resource group of subscription), de triggerconditie (welke metriek of logquery), de drempelwaarde, de aggregatieperiode en de vereiste respons binnen de organisatie. Dit alles wordt gedocumenteerd in een monitoring- en alertontwerp, dat onderdeel uitmaakt van de bredere architectuurdocumentatie en door de CISO of het cloudcompetencecenter wordt goedgekeurd. Een veelgemaakte fout is om uitsluitend op statische drempelwaarden te vertrouwen. In een dynamische cloudomgeving variëren belasting en gebruikspatronen continu, waardoor vaste grenzen (bijvoorbeeld CPU > 80% gedurende 5 minuten) óf te vaak afgaan, óf belangrijke afwijkingen missen. Daarom is het verstandig om waar mogelijk gebruik te maken van dynamische drempelwaarden en geavanceerde detectiemogelijkheden in Azure Monitor, zoals smart detection of metrische alerts met dynamische basislijnen. Voor loggebaseerde alerts is het belangrijk om queries te ontwerpen die duidelijke condities beschrijven – bijvoorbeeld "meer dan X mislukte aanmeldingen vanaf één IP-adres binnen Y minuten" – en om onderscheid te maken tussen informatieve, waarschuwings- en kritieke alerts. Dit voorkomt dat het SOC of beheerteam verdrinkt in niet-actiegerichte meldingen. Tot slot moet bij het ontwerp expliciet rekening worden gehouden met incidentprocessen en escalatieroutes. Een alert die niemand ziet, heeft geen waarde. Bepaal daarom per type alert wie de primaire ontvanger is (bijvoorbeeld het SOC, een applicatiebeheerteam of een 24/7-waakdienst), welke back-upkanalen worden gebruikt (Teams, e-mail, sms, ticketingsysteem) en welke responstijden verwacht worden. Deze afspraken worden vastgelegd in runbooks en procedures, zodat duidelijk is wat er moet gebeuren wanneer een alert afgaat. Het PowerShell-script alert-rules-deployment.ps1 sluit hierbij aan door de aanwezigheid en kwaliteit van deze alertconfiguraties te toetsen, bijvoorbeeld door te controleren of kritieke alerts daadwerkelijk zijn gekoppeld aan een actiegericht action group en of ze ingeschakeld zijn in alle relevante abonnementen.

Implementatie en Automatisering van Alert Rules met PowerShell

Zodra het ontwerp gereed is, verschuift de aandacht naar een beheerbare implementatie. Voor een middelgrote tot grote overheidsorganisatie is het onhaalbaar om alert rules handmatig via de Azure Portal te onderhouden; wijzigingen in abonnementen, resourcegroepen of workloads zouden al snel leiden tot inconsistenties en vergeten configuraties. Daarom is het cruciaal om alert rules zoveel mogelijk als code te beheren, waarbij PowerShell, ARM/Bicep of Terraform de bron van waarheid vormen. Praktisch betekent dit dat u templates definieert voor veelvoorkomende alertpatronen, zoals beschikbaarheidsmonitoring van webapps, capaciteitsbewaking van databases, controle van back-upjobs en detectie van verdachte aanmeldpogingen. PowerShell speelt hierbij een dubbele rol. Enerzijds gebruikt u scripts om op gecontroleerde wijze nieuwe alerts uit te rollen naar één of meerdere abonnementen, bijvoorbeeld op basis van een lijst van kritieke resources of tags. Anderzijds gebruikt u scripts om de bestaande configuratie te inventariseren en af te zetten tegen de gewenste situatie. Het script alert-rules-deployment.ps1 in deze baseline is specifiek ontworpen voor dat laatste. Het script maakt verbinding met Azure via Connect-AzAccount (of een vooraf geconfigureerde managed identity-context), leest alle abonnementen uit waarop de uitvoerende identiteit rechten heeft en verzamelt voor elk abonnement de geconfigureerde metrische en log alerts. Daarbij wordt onder andere vastgelegd: of de alert is ingeschakeld, op welke resource deze betrekking heeft, welke drempelwaarden en perioden gelden, en aan welke action groups notificaties worden verstuurd. Op basis van deze data vergelijkt het script de gevonden alerts met een set minimale vereisten die u in het script of in een begeleidend configuratiebestand vastlegt. Denk bijvoorbeeld aan de eis dat iedere productie-resourcegroep met het label "Critical=True" ten minste één actieve availability-alert en één beveiligingsgerelateerde alert moet hebben, of de eis dat specifieke signalen – zoals het uitschakelen van diagnostic settings of het falen van back-upjobs – altijd leiden tot een kritieke alert richting het SOC. Voor resources waarvoor dergelijke alerts ontbreken, markeert het script de situatie als non-compliant en voegt het een duidelijke toelichting toe aan de resultaten. Deze resultaten kunnen vervolgens worden geëxporteerd naar JSON of CSV en via dashboards worden gevisualiseerd. Hoewel dit script zich in eerste instantie richt op monitoring en compliance, kan het ook een startpunt zijn voor geautomatiseerde remediatie. Door de inventarisatiefase te combineren met aanmaak- of update-acties op alerts, kunt u zorgen dat nieuwe of gewijzigde resources automatisch de juiste alert rules krijgen. In de baseline is er bewust voor gekozen om remediatie in alert-rules-deployment.ps1 beperkt en voorzichtig te houden: de functie Invoke-Remediation toont welke aanpassingen nodig zijn en kan – indien expliciet bevestigd – standaard-alertregels aanmaken op basis van vooraf gedefinieerde parameters. Voor productieomgevingen wordt aanbevolen om deze logica te combineren met Infrastructure as Code in CI/CD-pijplijnen, zodat wijzigingen aan alerts onderdeel worden van dezelfde change- en reviewprocessen als de onderliggende infrastructuur.

Gebruik PowerShell-script alert-rules-deployment.ps1 (functie Invoke-Monitoring) – Voert een tenant-brede inventarisatie en compliancecheck uit op Azure Monitor-alertregels, inclusief status, drempelwaarden en gekoppelde action groups..

Operationele Monitoring, Governance en Continue Verbetering

Gebruik PowerShell-script alert-rules-deployment.ps1 (functie Invoke-Remediation) – Ondersteunt verbetering van de alertinrichting door niet-conforme resources te identificeren en – indien gewenst – standaard-alertregels voor kritieke workloads aan te maken..

Een alertlandschap is geen statisch ontwerp dat na implementatie kan worden vergeten. Nieuwe workloads, wijzigingen in architectuur, wijzigende dreigingsbeelden en lessen uit incidenten vereisen dat alert rules doorlopend worden geëvalueerd en aangepast. Zonder actieve governance ontstaan na verloop van tijd blinde vlekken: nieuwe abonnementen krijgen geen alerts, verouderde action groups verwijzen naar niet-bestaande mailboxen of Teams-kanalen en suppressieregels worden nooit herzien waardoor belangrijke signalen onzichtbaar blijven. Daarom moet de inrichting van Azure Monitor-alerts ingebed worden in het bredere governance- en risicomanagementproces van de organisatie. Een praktisch vertrekpunt is het inrichten van een periodieke reviewcyclus, bijvoorbeeld per kwartaal, waarin de effectiviteit van alerts wordt beoordeeld. Tijdens deze sessies bekijkt u samen met het SOC, operations en proceseigenaren onder andere: hoeveel alerts zijn er gegenereerd, hoeveel daarvan waren werkelijk relevant, welke alerts zijn nooit geactiveerd en zouden wellicht kunnen worden afgeschaald, en welke incidenten zijn opgetreden zonder dat er een passende alert bestond. Het PowerShell-script kan hier direct input voor leveren door te rapporteren welke alerts frequent, zelden of nooit afgaan en welke actie-groepen in de praktijk niet meer worden gebruikt. Op basis van deze informatie kunt u gericht bijsturen: drempelwaarden verfijnen, onnodige alerts uitfaseren en ontbrekende detectielogica toevoegen. Governance betekent ook dat eigenaarschap over alerts expliciet wordt toegewezen. Voor elke kritieke workload moet duidelijk zijn wie verantwoordelijk is voor het beheer van de bijbehorende alerts, hoe wijzigingen worden aangevraagd en goedgekeurd, en hoe kennis wordt geborgd bij personeelswisselingen. In de context van Nederlandse overheidsorganisaties is het verstandig om dit eigenaarschap te koppelen aan bestaande rollen binnen de informatiebeveiligings- en continuïteitsorganisatie, zoals lijnmanagers, applicatie-eigenaren en de CISO. Leg vast dat grote wijzigingen in alertconfiguraties altijd via het changeproces lopen en dat bij ingrijpende wijzigingen – bijvoorbeeld het uitzetten van een kritieke beveiligingsalert – expliciet akkoord van security of compliance nodig is. Door alert-rules-deployment.ps1 periodiek als onafhankelijke controle te draaien, krijgt de CISO inzicht in de daadwerkelijke status van de alertinrichting en kan hij of zij gericht vragen stellen aan teams waar afwijkingen worden geconstateerd.

Compliance, Audit en Bewijsvoering rondom Alert Rules

Alert rules spelen een belangrijke rol in het aantonen van compliance met uiteenlopende kaders zoals de BIO, ISO 27001 en NIS2. Toezichthouders en auditors vragen steeds vaker niet alleen óf logging is ingericht, maar ook hoe de organisatie waarborgt dat relevante gebeurtenissen tijdig worden gesignaleerd en opgevolgd. Tijdens audits worden bijvoorbeeld vragen gesteld als: hoe weet u dat kritieke beveiligingsgebeurtenissen binnen een acceptabele tijd bij het SOC terechtkomen? Hoe borgt u dat alerts nog actueel zijn na grote wijzigingen in architectuur of leveranciers? En hoe voorkomt u dat overmatige ruis ertoe leidt dat belangrijke waarschuwingen worden genegeerd? Een goed gedocumenteerde alertarchitectuur, gecombineerd met aantoonbare reviewcycli en scriptgestuurde controles, vormt het antwoord op deze vragen. Voor de BIO sluiten alerts vooral aan bij de normen rond logging, monitoring en incidentrespons. Door in het informatiebeveiligingsbeleid expliciet op te nemen dat kritieke processen ondersteund worden door Azure Monitor-alerts met gedefinieerde responstijden, en door de concrete invulling te documenteren per workload, kan de organisatie richting ENSIA-auditors onderbouwen dat monitoring structureel is ingericht. Het PowerShell-script levert daarbij concreet auditbewijs in de vorm van exports die tonen welke alerts actief zijn, op welke resources zij betrekking hebben en hoe zij zijn gekoppeld aan responskanalen. Deze exports kunnen worden bewaard in een auditdossier, samen met besluiten uit de periodieke reviewmeetings en runbooks die beschrijven hoe het SOC of beheerteam reageert op specifieke alerts. Voor ISO 27001 en NIS2 is vooral van belang dat er een aantoonbare PDCA-cyclus (Plan-Do-Check-Act) bestaat rondom monitoring en alertering. Het plan-niveau wordt ingevuld via architectuur- en beleidsdocumenten, de do-fase via implementatie van alerts en koppeling met incidentprocessen, de check-fase via periodieke analyses en scriptgestuurde controles, en de act-fase via verbetermaatregelen op basis van bevindingen en incidenten. Door deze samenhang expliciet te maken in documentatie en tijdens audits te illustreren met concrete voorbeelden – bijvoorbeeld een incident waarbij een alert een dreiging vroegtijdig signaleerde, of een oefening waarin het opschalen van het crisisteam is getest – ontstaat een overtuigend beeld van volwassen monitoring. Het gebruik van alert-rules-deployment.ps1 als standaardinstrument in deze check-fase toont bovendien aan dat de organisatie niet afhankelijk is van handmatige controles, maar geautomatiseerde waarborgen inzet om de kwaliteit van alert rules op niveau te houden.

Gebruik PowerShell-script alert-rules-deployment.ps1 (functie Invoke-Revert) – Biedt waar nodig een gecontroleerd mechanisme om test- of tijdelijke alertconfiguraties terug te draaien naar een eerder vastgelegde, goedgekeurde staat..

Compliance & Frameworks

Automation

Gebruik het onderstaande PowerShell script om deze security control te monitoren en te implementeren. Het script bevat functies voor zowel monitoring (-Monitoring) als remediation (-Remediation).

PowerShell
<# .SYNOPSIS Inventariseert en beoordeelt Azure Monitor-alertregels voor kritieke workloads. .DESCRIPTION Dit script leest per abonnement de geconfigureerde Azure Monitor-alertregels uit en beoordeelt of deze voldoen aan minimale eisen voor beschikbaarheid, beveiliging en incidentrespons. De nadruk ligt op: - Aanwezigheid van ingeschakelde metrische en log alerts op kritieke resources - Koppeling van alerts aan geldige action groups (zoals e-mail, Teams of ITSM) - Basiscontrole op ruis (bijvoorbeeld alerts die nooit of juist extreem vaak afgaan) Met de parameter -Monitoring wordt een samenvattend compliance-overzicht getoond. Met -Remediation worden voorstellen gedaan voor standaard-alertregels en kan, indien gewenst, een basisset alerts worden aangemaakt voor met tags gemarkeerde kritieke resourcegroepen. .NOTES Filename: alert-rules-deployment.ps1 Author: Nederlandse Baseline voor Veilige Cloud Version: 1.0 Related JSON: content/azure/monitoring/alert-rules-deployment.json Category: monitoring Workload: azure .LINK https://github.com/m365-tenant-best-practise .EXAMPLE .\alert-rules-deployment.ps1 -Monitoring Controleert de huidige alert rules en rapporteert de compliance-status. .EXAMPLE .\alert-rules-deployment.ps1 -Remediation -WhatIf Toont welke standaard-alertregels zouden worden aangemaakt voor kritieke resourcegroepen. .EXAMPLE .\alert-rules-deployment.ps1 -Remediation Maakt standaard-alertregels aan voor met tags gemarkeerde kritieke resourcegroepen. #> #Requires -Version 5.1 #Requires -Modules Az.Accounts, Az.Monitor, Az.Resources [CmdletBinding()] param( [Parameter(HelpMessage = "Monitor current configuration status")] [switch]$Monitoring, [Parameter(HelpMessage = "Apply recommended configuration")] [switch]$Remediation, [Parameter(HelpMessage = "Revert to previous configuration")] [switch]$Revert, [Parameter(HelpMessage = "Show what would happen without making changes")] [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HELPER: CONNECTIEBEHEER # ============================================================================ function Get-AzContextOrWarning { <# .SYNOPSIS Zorgt voor een geldige Azure-context zonder interactieve prompts. .DESCRIPTION In omgevingen zonder vooraf ingestelde context geeft deze functie een duidelijke waarschuwing en retourneert $null. Dit voorkomt dat scripts blijven hangen op interactieve logins in geautomatiseerde pipelines. #> [CmdletBinding()] param() $ctx = Get-AzContext -ErrorAction SilentlyContinue if (-not $ctx) { Write-Warning "Geen actieve Azure-context gevonden. Meld u vooraf aan met 'Connect-AzAccount' (bij voorkeur non-interactief, bijvoorbeeld via managed identity of service principal)." return $null } return $ctx } # ============================================================================ # FUNCTIONS # ============================================================================ function Test-Compliance { <# .SYNOPSIS Tests if current configuration meets compliance requirements .DESCRIPTION Wrapper function that calls Invoke-Monitoring and returns compliance status .OUTPUTS Returns monitoring result object with isCompliant property #> [CmdletBinding()] param() return Invoke-Monitoring } function Invoke-Monitoring { <# .SYNOPSIS Monitors and reports current Azure Monitor alert rules configuration .DESCRIPTION Controleert per abonnement en resourcegroep: - Of er actieve alert rules zijn op kritieke resources (tag: Critical=True) - Of alerts gekoppeld zijn aan ten minste één action group - Een globale indicatie van ruis en dekking .OUTPUTS Hashtable met: - isCompliant: Boolean - timestamp: Datum/tijd - findings: Lijst met tekstuele bevindingen - summary: Overzicht met aantallen alerts en kritieke afwijkingen #> [CmdletBinding()] param() try { Write-Host "`nMonitoring Azure Monitor-alertregels..." -ForegroundColor Yellow $ctx = Get-AzContextOrWarning if (-not $ctx) { return @{ isCompliant = $false timestamp = Get-Date findings = @("Geen Azure-context beschikbaar; voer Connect-AzAccount uit voordat u deze controle draait.") summary = @{ SubscriptionsChecked = 0 CriticalGroupsWithoutAlerts = 0 AlertsWithoutActionGroup = 0 TotalAlerts = 0 } } } Write-Host "Context: $($ctx.Subscription.Name) ($($ctx.Subscription.Id))" -ForegroundColor Gray $result = @{ isCompliant = $true timestamp = Get-Date findings = @() summary = @{ SubscriptionsChecked = 0 CriticalGroupsWithoutAlerts = 0 AlertsWithoutActionGroup = 0 TotalAlerts = 0 } } $subscriptions = Get-AzSubscription -ErrorAction Stop foreach ($sub in $subscriptions) { Set-AzContext -SubscriptionId $sub.Id -ErrorAction Stop | Out-Null $result.summary.SubscriptionsChecked++ Write-Host "`nAbonnement: $($sub.Name) [$($sub.Id)]" -ForegroundColor Cyan $resourceGroups = Get-AzResourceGroup -ErrorAction Stop # Kritieke resourcegroepen via tag Critical=True $criticalGroups = $resourceGroups | Where-Object { $_.Tags.Keys -contains "Critical" -and $_.Tags["Critical"] -eq "True" } foreach ($rg in $criticalGroups) { Write-Host " Controleren resourcegroep (kritiek): $($rg.ResourceGroupName)" -ForegroundColor White # Metrische alerts (v2) $metricAlerts = Get-AzMetricAlertRuleV2 -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue # Gelogde alerts (Scheduled Query Rules) $logAlerts = Get-AzScheduledQueryRule -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue $allAlerts = @() if ($metricAlerts) { $allAlerts += $metricAlerts } if ($logAlerts) { $allAlerts += $logAlerts } $result.summary.TotalAlerts += $allAlerts.Count if (-not $allAlerts -or $allAlerts.Count -eq 0) { $result.isCompliant = $false $result.summary.CriticalGroupsWithoutAlerts++ $msg = "Kritieke resourcegroep '$($rg.ResourceGroupName)' in abonnement '$($sub.Name)' heeft geen enkele Azure Monitor-alertregel." $result.findings += $msg Write-Host " [FAIL] $msg" -ForegroundColor Red continue } foreach ($alert in $allAlerts) { $hasActionGroup = $false if ($alert.PSObject.Properties.Name -contains "Actions") { if ($alert.Actions -and $alert.Actions.ActionGroups -and $alert.Actions.ActionGroups.Count -gt 0) { $hasActionGroup = $true } } elseif ($alert.PSObject.Properties.Name -contains "ActionGroupId") { # Oudere objecttypen if ($alert.ActionGroupId) { $hasActionGroup = $true } } if (-not $hasActionGroup) { $result.isCompliant = $false $result.summary.AlertsWithoutActionGroup++ $msg = "Alert '$($alert.Name)' in resourcegroep '$($rg.ResourceGroupName)' heeft geen gekoppelde action group." $result.findings += $msg Write-Host " [WARN] $msg" -ForegroundColor Yellow } else { Write-Host " [OK] Alert '$($alert.Name)' is gekoppeld aan ten minste één action group." -ForegroundColor Green } } } } Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "SAMENVATTING ALERT RULES" -ForegroundColor Cyan Write-Host (" Abonnementen gecontroleerd : {0}" -f $result.summary.SubscriptionsChecked) -ForegroundColor White Write-Host (" Totaal aantal gevonden alerts : {0}" -f $result.summary.TotalAlerts) -ForegroundColor White $colorCriticalGroups = 'Green' if ($result.summary.CriticalGroupsWithoutAlerts -gt 0) { $colorCriticalGroups = 'Yellow' } Write-Host (" Kritieke RG's zonder alerts : {0}" -f $result.summary.CriticalGroupsWithoutAlerts) -ForegroundColor $colorCriticalGroups $colorAlertsWithoutAG = 'Green' if ($result.summary.AlertsWithoutActionGroup -gt 0) { $colorAlertsWithoutAG = 'Yellow' } Write-Host (" Alerts zonder action group : {0}" -f $result.summary.AlertsWithoutActionGroup) -ForegroundColor $colorAlertsWithoutAG if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT: Kritieke resourcegroepen beschikken over alerts met gekoppelde action groups." -ForegroundColor Green } else { Write-Host "`n[FAIL] NON-COMPLIANT: Zie bevindingen voor ontbrekende alerts of action groups." -ForegroundColor Red } return $result } catch { Write-Host "`n[FAIL] ERROR tijdens monitoring: $_" -ForegroundColor Red throw } } function Invoke-Remediation { <# .SYNOPSIS Biedt ondersteuning bij het aanmaken van standaard-alertregels. .DESCRIPTION Zoekt kritieke resourcegroepen (tag Critical=True) zonder alerts en kan, indien bevestigd, een eenvoudige CPU-gerichte metrische alert aanmaken als basisbeveiliging. Gebruik bij voorkeur -WhatIf om de impact te beoordelen. .PARAMETER WhatIf Shows what would be changed without making actual changes #> [CmdletBinding(SupportsShouldProcess)] param() try { Write-Host "`nRemediation van Azure Monitor-alertregels..." -ForegroundColor Yellow $ctx = Get-AzContextOrWarning if (-not $ctx) { Write-Warning "Remediation kan niet worden uitgevoerd zonder geldige Azure-context." return } $subscriptions = Get-AzSubscription -ErrorAction Stop foreach ($sub in $subscriptions) { Set-AzContext -SubscriptionId $sub.Id -ErrorAction Stop | Out-Null Write-Host "`nAbonnement: $($sub.Name) [$($sub.Id)]" -ForegroundColor Cyan $resourceGroups = Get-AzResourceGroup -ErrorAction Stop $criticalGroups = $resourceGroups | Where-Object { $_.Tags.Keys -contains "Critical" -and $_.Tags["Critical"] -eq "True" } foreach ($rg in $criticalGroups) { # Controleer of er al alerts zijn $metricAlerts = Get-AzMetricAlertRuleV2 -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue $logAlerts = Get-AzScheduledQueryRule -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue if (($metricAlerts + $logAlerts).Count -gt 0) { Write-Host " [INFO] Resourcegroep '$($rg.ResourceGroupName)' heeft al alerts; geen standaard-alerts aangemaakt." -ForegroundColor Gray continue } $alertName = "cpu-high-critical-default" $targetScope = @("/subscriptions/$($sub.Id)/resourceGroups/$($rg.ResourceGroupName)") Write-Host " [PLAN] Standaard CPU-alert aanmaken in '$($rg.ResourceGroupName)'..." -ForegroundColor Yellow if ($PSCmdlet.ShouldProcess($rg.ResourceGroupName, "Create default CPU metric alert '$alertName'")) { # Probeer een bestaande action group met naam of tag te vinden $actionGroup = Get-AzActionGroup -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue | Select-Object -First 1 if (-not $actionGroup) { Write-Warning "Geen bestaande action group gevonden in '$($rg.ResourceGroupName)'. De alert wordt zonder action group aangemaakt; koppel later handmatig een passend action group-profiel." } $criteria = New-AzMetricAlertRuleV2Criteria ` -MetricName "Percentage CPU" ` -MetricNamespace "Microsoft.Compute/virtualMachines" ` -TimeAggregation Average ` -Operator GreaterThan ` -Threshold 80 $params = @{ Name = $alertName ResourceGroupName = $rg.ResourceGroupName WindowSize = (New-TimeSpan -Minutes 5) Frequency = (New-TimeSpan -Minutes 1) Severity = 2 Condition = $criteria TargetResourceScope = $targetScope Description = "Standaard alert: gemiddelde CPU > 80% gedurende 5 minuten in kritieke resourcegroep." Enabled = $true } if ($actionGroup) { $params["ActionGroupId"] = $actionGroup.Id } New-AzMetricAlertRuleV2 @params -ErrorAction Stop | Out-Null Write-Host " [OK] Standaard CPU-alert '$alertName' aangemaakt in resourcegroep '$($rg.ResourceGroupName)'." -ForegroundColor Green } } } Write-Host "`n[OK] Remediation uitgevoerd (of gesimuleerd met WhatIf)." -ForegroundColor Green } catch { Write-Host "`n[FAIL] ERROR tijdens remediation: $_" -ForegroundColor Red throw } } function Invoke-Revert { <# .SYNOPSIS Reverts configuration to previous state .DESCRIPTION In deze baseline is geen volledige state-tracking voor alertconfiguraties geïmplementeerd. Deze functie verwijdert uitsluitend standaard-alerts met de naam 'cpu-high-critical-default' in kritieke resourcegroepen. #> [CmdletBinding(SupportsShouldProcess)] param() try { Write-Host "`nRevert van standaard-alertregels..." -ForegroundColor Yellow $ctx = Get-AzContextOrWarning if (-not $ctx) { Write-Warning "Revert kan niet worden uitgevoerd zonder geldige Azure-context." return } $subscriptions = Get-AzSubscription -ErrorAction Stop foreach ($sub in $subscriptions) { Set-AzContext -SubscriptionId $sub.Id -ErrorAction Stop | Out-Null Write-Host "`nAbonnement: $($sub.Name) [$($sub.Id)]" -ForegroundColor Cyan $resourceGroups = Get-AzResourceGroup -ErrorAction Stop $criticalGroups = $resourceGroups | Where-Object { $_.Tags.Keys -contains "Critical" -and $_.Tags["Critical"] -eq "True" } foreach ($rg in $criticalGroups) { $alerts = Get-AzMetricAlertRuleV2 -ResourceGroupName $rg.ResourceGroupName -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq "cpu-high-critical-default" } foreach ($alert in $alerts) { Write-Host " [PLAN] Verwijderen standaard-alert '$($alert.Name)' in '$($rg.ResourceGroupName)'..." -ForegroundColor Yellow if ($PSCmdlet.ShouldProcess($rg.ResourceGroupName, "Remove metric alert '$($alert.Name)'")) { Remove-AzMetricAlertRuleV2 -Name $alert.Name -ResourceGroupName $rg.ResourceGroupName -ErrorAction Stop Write-Host " [OK] Alert '$($alert.Name)' verwijderd." -ForegroundColor Green } } } } Write-Host "`n[OK] Revert van standaard-alertregels voltooid (of gesimuleerd met WhatIf)." -ForegroundColor Green } catch { Write-Host "`n[FAIL] ERROR tijdens revert: $_" -ForegroundColor Red throw } } # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Azure Monitor Alert Rules: Deployment & Governance" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Revert) { if ($WhatIf) { Write-Host "WhatIf: Zou standaard-alertregels verwijderen (cpu-high-critical-default)." -ForegroundColor Yellow } else { Invoke-Revert } } elseif ($Remediation) { if ($WhatIf) { Write-Host "WhatIf: Zou standaard-alertregels aanmaken voor kritieke resourcegroepen." -ForegroundColor Yellow } else { Invoke-Remediation } } elseif ($Monitoring) { $result = Invoke-Monitoring if ($result.isCompliant) { exit 0 } else { exit 1 } } else { Write-Host "Beschikbare parameters:" -ForegroundColor Yellow Write-Host " -Monitoring : Controleer huidige status van Azure Monitor-alertregels" -ForegroundColor Gray Write-Host " -Remediation : Stel standaard-alertregels voor en maak deze desgewenst aan" -ForegroundColor Gray Write-Host " -Revert : Verwijder standaard-alertregels (cpu-high-critical-default)" -ForegroundColor Gray Write-Host " -WhatIf : Toon welke wijzigingen zouden worden uitgevoerd" -ForegroundColor Gray Write-Host "`nVoorbeeld: .\alert-rules-deployment.ps1 -Monitoring" -ForegroundColor Cyan } } catch { Write-Error "Script execution failed: $_" exit 2 } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } # ============================================================================ # EXIT CODES # ============================================================================ # 0 = Success / Compliant # 1 = Warning / Non-compliant # 2 = Error / Execution failed

Risico zonder implementatie

Risico zonder implementatie
High: Zonder goed ontworpen en centraal beheerde Azure Monitor-alertregels worden kritieke beveiligings- en beschikbaarheidsincidenten te laat of helemaal niet gesignaleerd, ontstaat alert-moeheid bij beheerders en kan de organisatie richting toezichthouders niet aantonen dat monitoring en incidentrespons op orde zijn. Dit vergroot de kans op langdurige uitval, gegevensverlies, reputatieschade en non-compliance met BIO, ISO 27001 en NIS2.

Management Samenvatting

Vertaal risico’s en kritieke processen naar een set gerichte Azure Monitor-alertregels met duidelijke drempelwaarden, actiegerichte notificaties en vastgelegd eigenaarschap. Automatiseer de uitrol en inventarisatie van alerts met PowerShell en Infrastructure as Code, gebruik alert-rules-deployment.ps1 om de inrichting periodiek te toetsen en verbeter deze op basis van incidenten en audits. Zo borgt u dat relevante gebeurtenissen tijdig worden gedetecteerd, opgevolgd en aantoonbaar worden gemaakt richting bestuur en toezichthouders.