Public/Invoke-AACWafAssessment.ps1
|
function Invoke-AACWafAssessment { <# .EXTERNALHELP Azure.Admin.Console-help.xml .SYNOPSIS Assesses the estate against the Azure Well-Architected Framework's five pillars - Reliability, Security, Cost Optimization, Operational Excellence and Performance Efficiency - scored by pillar, design principle and check, with workbook-style heat maps by subscription, resource group or resource type, findings and what to do, a Spectre.Console view, objects, and CSV, PDF and interactive HTML reports. .DESCRIPTION Read-only, with one batch of Azure Resource Graph queries - Reader is enough, no Az modules. Every check is evaluated against that one read: the resources the checks test (VMs, scale sets, disks, snapshots, storage, SQL, App Service, Key Vault, AKS, load balancers, Application Gateways, public IPs, NSGs, NICs, Cosmos DB, Redis, container registries, Recovery Services vaults, virtual networks, resource groups), VM extensions, autoscale settings, deployment slots, what Azure Backup protects, how many alert rules and action groups each subscription has, Azure Advisor's recommendations in the pillars' categories, and Defender for Cloud's plans, secure scores and high-severity assessments. Each pillar is scored against its design principles (Microsoft Learn): Reliability business requirements, resilience, recovery, operations, simplicity - zones, backups, redundancy, instance counts, retired Basic SKUs, health probes, SLA tiers Security security readiness, confidentiality, integrity, availability, sustained posture - Defender plans and secure score, TLS, HTTPS, public access, network restrictions, keys and local accounts, management ports open to the internet, WAF, DDoS Cost cost-management discipline, cost-efficiency, usage and rate optimization, monitoring - cost-allocation tags (-CostTag), unattached disks, unused public IPs, VMs stopped but billed, empty plans, old snapshots, Azure Hybrid Benefit, old VM generations Operational DevOps culture, standards, observability, deployment, Excellence automation - owner and environment tags (-OwnerTag), the Azure Monitor agent, boot diagnostics, Application Insights, alert rules and action groups, deployment slots, platform patching, AKS auto-upgrade Performance targets, capacity, sustained performance, optimization Efficiency - autoscale on plans, scale sets, AKS and Application Gateway, accelerated networking, SSD OS disks, SQL and Redis tiers Advisor and Defender are checks too, one per pillar (AD-HA, AD-SEC, AD-COST, AD-OPS, AD-PERF, DF-HIGH): a resource with an open recommendation fails. An item that is the same finding as a catalogue check on the same resource is counted once, by the catalogue check, whose result says 'Also flagged by Advisor' (or Defender); -KeepDuplicates counts both. What no API can test - business requirements, threat models, budgets, performance targets, team practices - comes from the questionnaire: Export-AACWafQuestionnaire writes one question per principle, the team answers Yes, Partly or No, and -AttestationPath scores the answers (checks AT-..., heat-map column 'Attested'). -HistoryPath keeps a line per run and shows the change since the last one. Scores are out of 100: a check's is the share of resources that pass; a principle's and a pillar's weigh their checks by severity (High 3, Medium 2, Low 1). A principle no check covers is shown as not assessed: it needs a review or attestation. Each pillar gets a maturity: Initial (under 50), Developing, Established (75+), Optimised (90+). The heat maps - pillars, and design principles, by -HeatMapBy - show each cell's score in colour: at the prompt (the first eight columns), in the PDF (ten columns a table) and in the HTML report, where clicking a cell lists its findings. What you get depends on where the command runs: at the prompt tiles, the heat maps, the principles, and the top findings - a page at a time piped onward one AAC.WafCheckResult per check and resource -PassThru the view and the results -NoDisplay the results only -CsvPath writes every result; -HtmlPath an interactive report (summary with heat maps, principles, checks, findings); -PdfPath a PDF. .PARAMETER SubscriptionId Only these subscriptions. .PARAMETER ManagementGroupId Only the subscriptions under these management groups. .PARAMETER ResourceGroupName Only these resource groups (a workload). .PARAMETER Pillar The pillars to assess (all five by default): Reliability, Security, 'Cost Optimization', 'Operational Excellence', 'Performance Efficiency'. .PARAMETER HeatMapBy The heat maps' columns: Subscription (the default), ResourceGroup or ResourceType. .PARAMETER ExcludeCheck Check IDs to leave out; wildcards work: 'SE-24', 'AD-*', 'DF-*'. .PARAMETER NoAdvisor Leave out Azure Advisor's recommendations. .PARAMETER NoDefender Leave out Defender for Cloud: plans, secure score and assessments. .PARAMETER AttestationPath An answered questionnaire (Export-AACWafQuestionnaire) to score with the automated checks. .PARAMETER HistoryPath A CSV file that keeps a line per run - overall and pillar scores - for the trend. .PARAMETER KeepDuplicates Count an Advisor or Defender item even when a catalogue check already tested the same thing on the same resource. .PARAMETER CostTag The tag names that allocate cost (any one counts). .PARAMETER OwnerTag The tag names that name an owner (any one counts). .PARAMETER CsvPath Write every result to this CSV file. .PARAMETER HtmlPath Write an interactive HTML report. .PARAMETER PdfPath Write a PDF report. .PARAMETER Title The reports' title. .PARAMETER PassThru Show the view and also return the results. .PARAMETER NoDisplay Return the results without showing the view. .PARAMETER NoPaging Show the whole view at once. .EXAMPLE Connect-AAC Invoke-AACWafAssessment All five pillars across every subscription, with heat maps by subscription. .EXAMPLE Export-AACWafQuestionnaire -Path .\waf-answers.csv Invoke-AACWafAssessment -ResourceGroupName 'rg-app-prod' -AttestationPath .\waf-answers.csv -HistoryPath .\waf-history.csv -HtmlPath .\out\WAF.html A workload's review with the team's answers, and its trend from run to run. .EXAMPLE Invoke-AACWafAssessment -ResourceGroupName 'rg-app-prod' -HeatMapBy ResourceType -HtmlPath .\out\WAF.html -PdfPath .\out\WAF.pdf One workload's go-live review, as HTML and PDF reports. .EXAMPLE Invoke-AACWafAssessment -ManagementGroupId 'mg-landingzones' -Pillar Reliability -HeatMapBy ResourceGroup The landing zones' reliability, resource group by resource group. .EXAMPLE Invoke-AACWafAssessment -NoDisplay | Where-Object { $_.Status -eq 'Fail' -and $_.Severity -eq 'High' } | Group-Object Check The high-severity gaps, by check. .OUTPUTS AAC.WafCheckResult (piped onward, or with -PassThru or -NoDisplay) #> [CmdletBinding()] [OutputType('AAC.WafCheckResult')] param( [ValidatePattern('^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$')] [string[]] $SubscriptionId, [ValidateNotNullOrEmpty()] [string[]] $ManagementGroupId, [ValidateNotNullOrEmpty()] [string[]] $ResourceGroupName, [ValidateSet('Reliability', 'Security', 'Cost Optimization', 'Operational Excellence', 'Performance Efficiency')] [string[]] $Pillar = @('Reliability', 'Security', 'Cost Optimization', 'Operational Excellence', 'Performance Efficiency'), [ValidateSet('Subscription', 'ResourceGroup', 'ResourceType')] [string] $HeatMapBy = 'Subscription', [SupportsWildcards()] [string[]] $ExcludeCheck, [switch] $NoAdvisor, [switch] $NoDefender, [string] $AttestationPath, [string] $HistoryPath, [switch] $KeepDuplicates, [ValidateNotNullOrEmpty()] [string[]] $CostTag = @('CostCenter', 'CostCentre', 'Cost Center', 'Project', 'Application', 'BillingCode'), [ValidateNotNullOrEmpty()] [string[]] $OwnerTag = @('Owner', 'Contact', 'TechnicalOwner', 'BusinessOwner'), [string] $CsvPath, [string] $HtmlPath, [string] $PdfPath, [string] $Title = 'Well-Architected assessment', [switch] $PassThru, [switch] $NoDisplay, [switch] $NoPaging ) trap { if ($_.Exception -is [System.Management.Automation.PipelineStoppedException]) { return }; $PSCmdlet.ThrowTerminatingError((Show-AACError -ErrorRecord $_ -Cmdlet $PSCmdlet)) } $pipedOnward = $MyInvocation.PipelinePosition -lt $MyInvocation.PipelineLength $interactive = -not $NoDisplay -and -not $pipedOnward $resolve = { param([string] $Path) if ($Path) { $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) } } $request = @{ SubscriptionId = @($SubscriptionId | Where-Object { $_ }); ManagementGroupId = @($ManagementGroupId | Where-Object { $_ }); ResourceGroupName = @($ResourceGroupName | Where-Object { $_ }) Pillar = @($Pillar | Select-Object -Unique); HeatMapBy = $HeatMapBy; ExcludeCheck = @($ExcludeCheck | Where-Object { $_ }); NoAdvisor = [bool]$NoAdvisor; NoDefender = [bool]$NoDefender AttestationPath = & $resolve $AttestationPath; HistoryPath = & $resolve $HistoryPath; CostTag = @($CostTag); OwnerTag = @($OwnerTag); KeepDuplicates = [bool]$KeepDuplicates } $null = Get-AACAccessToken if ($interactive) { Write-AACRule -Title 'Azure Admin Console :: Well-Architected assessment' -Color 'mediumpurple2' } $state = Get-AACWafAssessment -Request $request $history = if ($request.HistoryPath) { Write-AACWafHistory -Path $request.HistoryPath -State $state } $report = ConvertTo-AACWafReport -State $state -Request $request -History $history $result = $state.Result Invoke-AACReportOutput -Report $report -Title $Title -CsvObject @($result.Results) -Noun 'result' -CsvPath (& $resolve $CsvPath) -HtmlPath (& $resolve $HtmlPath) -PdfPath (& $resolve $PdfPath) ` -ShowView:$interactive -NoPaging:$NoPaging -Object @($result.Results) -ReturnObject:($PassThru -or $NoDisplay -or $pipedOnward) } |