runbook/runbook.classes.ps1
<#
.CLASS Recommendation .SYNOPSIS Represents a recommendation associated with a runbook check. .DESCRIPTION The `Recommendation` class defines a recommendation, including metadata, impact assessment, query logic, and automation availability. This class is used within the runbook module to define checks and their associated guidance. .PROPERTY AprlGuid A unique identifier for the recommendation, if applicable. .PROPERTY CheckName The name of the check associated with this recommendation. .PROPERTY RecommendationTypeId The type identifier for this recommendation. .PROPERTY RecommendationMetadataState The current state of the recommendation (e.g., Active, Deprecated). .PROPERTY RecommendationControl The control category associated with the recommendation. .PROPERTY LongDescription A detailed explanation of the recommendation, its purpose, and implementation guidance. .PROPERTY Description A brief summary of the recommendation. .PROPERTY PotentialBenefits A concise statement highlighting the benefits of implementing the recommendation. .PROPERTY RecommendationResourceType The resource type that the recommendation applies to. .PROPERTY RecommendationImpact The expected impact of following or ignoring the recommendation. .PROPERTY Query The query logic used to evaluate compliance with the recommendation. .PROPERTY Links A hashtable containing additional reference links for further details. .PROPERTY Tags An array of tags categorizing or classifying the recommendation. .PROPERTY PgVerified Indicates whether the recommendation has been verified by the product group. .PROPERTY AutomationAvailable Indicates whether automation is available to apply the recommendation. .NOTES Author: Casey Watson Date: 2025-02-27 #> class Recommendation { [string] $AprlGuid [string] $CheckName [string] $RecommendationTypeId [string] $RecommendationMetadataState [string] $RecommendationControl [string] $LongDescription [string] $Description [string] $PotentialBenefits [string] $RecommendationResourceType [string] $RecommendationImpact [string] $Query [hashtable] $Links = @{} [string[]] $Tags = @() [bool] $PgVerified [bool] $AutomationAvailable } <# .CLASS RunbookRecommendation .SYNOPSIS Represents a recommendation within a runbook. .DESCRIPTION The `RunbookRecommendation` class encapsulates a specific recommendation as part of a runbook. It includes metadata such as the check set name, the individual check name, and an associated `Recommendation` object. .PROPERTY CheckSetName The name of the check set that this recommendation belongs to. .PROPERTY CheckName The name of the specific check within the check set. .PROPERTY Recommendation The `Recommendation` object associated with this runbook entry. .NOTES Author: Casey Watson Date: 2025-02-27 #> class RunbookRecommendation { [string] $CheckSetName [string] $CheckName [Recommendation] $Recommendation } <# .CLASS RunbookQuery .SYNOPSIS Represents a query associated with a runbook check. .DESCRIPTION The `RunbookQuery` class stores query details for a specific check within a runbook check set. It includes metadata such as the check set and check name, the query string, selector name, associated tags, and the linked recommendation. .PROPERTY CheckSetName The name of the check set containing this query. .PROPERTY CheckName The name of the specific check associated with the query. .PROPERTY SelectorName The selector used for filtering resources in the query. .PROPERTY Query The query string to evaluate the check. .PROPERTY Tags An array of tags associated with this query. .PROPERTY Recommendation The `Recommendation` object related to this query. .NOTES Author: Casey Watson Date: 2025-02-27 #> class RunbookQuery { [string] $CheckSetName [string] $CheckName [string] $SelectorName [string] $Query [string[]] $Tags [Recommendation] $Recommendation } <# .CLASS RunbookCheck .SYNOPSIS Represents a check within a runbook. .DESCRIPTION The `RunbookCheck` class defines an individual check, including its selector, parameters, and associated tags. It is part of a `RunbookCheckSet` and is used to evaluate specific conditions within a runbook. .PROPERTY SelectorName The name of the selector applied to this check. .PROPERTY Parameters A hashtable of parameters specific to this check. .PROPERTY Tags An array of tags categorizing this check. .NOTES Author: Casey Watson Date: 2025-02-27 #> class RunbookCheck { [string] $SelectorName [hashtable] $Parameters = @{} [string[]] $Tags = @() } <# .CLASS RunbookCheckSet .SYNOPSIS Represents a set of runbook checks. .DESCRIPTION The `RunbookCheckSet` class groups multiple `RunbookCheck` objects, allowing them to be organized and evaluated together as part of a runbook. .PROPERTY Checks A hashtable containing `RunbookCheck` objects. .NOTES Author: Casey Watson Date: 2025-02-27 #> class RunbookCheckSet { [hashtable] $Checks = @{} } <# .CLASS Runbook .SYNOPSIS Represents a runbook containing check sets, selectors, and parameters. .DESCRIPTION The `Runbook` class defines the structure of a runbook, including parameters, variables, selectors, and check sets. It provides a `Validate` method to ensure the runbook is correctly configured before execution. .PROPERTY Parameters A hashtable of parameters defined within the runbook. .PROPERTY Variables A hashtable of variables used in the runbook. .PROPERTY Selectors A hashtable of selectors that define resource filters. .PROPERTY CheckSets A hashtable of `RunbookCheckSet` objects. .METHOD Validate Ensures the runbook is properly configured by verifying that all required elements exist. .NOTES Author: Casey Watson Date: 2025-02-27 #> class Runbook { [hashtable] $Parameters = @{} [hashtable] $Variables = @{} [hashtable] $Selectors = @{} [hashtable] $CheckSets = @{} [void] Validate() { $errors = @() if ($this.Selectors.Count -eq 0) { $errors += "- [selectors]: At least one (1) selector is required." } if ($this.CheckSets.Count -eq 0) { $errors += "- [checks]: At least one (1) check set is required." } foreach ($checkSetKey in $this.CheckSets.Keys) { $checkSet = $this.CheckSets[$checkSetKey] foreach ($checkKey in $checkSet.Checks.Keys) { $check = $checkSet.Checks[$checkKey] $checkTitle = "[$checkSetKey]:[$checkKey]" if (-not $this.Selectors.ContainsKey($check.SelectorName)) { $errors += "- [checks]: $checkTitle references a selector that does not exist: [$($check.SelectorName)]." } } } if ($errors.Count -gt 0) { throw "Runbook is invalid:`n$($errors -join "`n")" } } } <# .CLASS SelectorReview .SYNOPSIS Stores the results of a selector review. .DESCRIPTION The `SelectorReview` class contains resolved selectors and their associated resources after evaluation. It helps users verify that selectors are correctly configured and returning the expected results. .PROPERTY Selectors A hashtable mapping selector names to selected resource sets. .NOTES Author: Casey Watson Date: 2025-02-27 #> class SelectorReview { [hashtable] $Selectors = @{} } <# .CLASS SelectedResourceSet .SYNOPSIS Represents a set of resources selected by a query. .DESCRIPTION The `SelectedResourceSet` class stores the results of a resource selection based on a selector and an Azure Resource Graph query. .PROPERTY Selector The selector that determined the resource set. .PROPERTY ResourceGraphQuery The query used to retrieve resources. .PROPERTY Resources An array of `SelectedResource` objects. .NOTES Author: Casey Watson Date: 2025-02-27 #> class SelectedResourceSet { [string] $Selector [string] $ResourceGraphQuery [SelectedResource[]] $Resources = @() } <# .CLASS SelectedResource .SYNOPSIS Represents a selected resource. .DESCRIPTION The `SelectedResource` class stores details about a resource, including its ID, type, name, location, resource group, and tags. .PROPERTY ResourceId The unique identifier of the resource. .PROPERTY ResourceType The type of the resource. .PROPERTY ResourceName The name of the resource. .PROPERTY ResourceLocation The geographical location of the resource. .PROPERTY ResourceGroupName The resource group that contains the resource. .PROPERTY ResourceTags A hashtable of key-value pairs representing resource tags. .NOTES Author: Casey Watson Date: 2025-02-27 #> class SelectedResource { [string] $ResourceId [string] $ResourceType [string] $ResourceName [string] $ResourceLocation [string] $ResourceGroupName [hashtable] $ResourceTags = @{} } <# .CLASS RunbookFactory .SYNOPSIS Parses and creates Runbook objects. .DESCRIPTION The `RunbookFactory` class provides methods to parse runbooks from a JSON file or raw JSON content, returning a `Runbook` instance. .METHOD ParseRunbookFile Reads and parses a runbook from a JSON file. .METHOD ParseRunbookContent Parses a runbook from raw JSON content. .NOTES - If the file does not exist, `ParseRunbookFile` returns `$null`. - Supports both simple and structured check definitions. - Automatically initializes missing properties as empty collections. Author: Casey Watson Date: 2025-02-27 #> class RunbookFactory { [Runbook] ParseRunbookFile([string] $path) { if (Test-FileExists -Path $path) { $fileContent = Get-Content -Path $path -Raw return $this.ParseRunbookContent($fileContent) } return $null } [Runbook] ParseRunbookContent([string] $content) { $runbookHash = ($content | ConvertFrom-Json -AsHashtable) $runbook = [Runbook]@{ Parameters = ($runbookHash.parameters ?? @{}) Variables = ($runbookHash.variables ?? @{}) Selectors = ($runbookHash.selectors ?? @{}) } foreach ($checkSetKey in $runbookHash.checks.Keys) { $checkSet = [RunbookCheckSet]::new() $checkSetHash = $runbookHash.checks[$checkSetKey] foreach ($checkKey in $checkSetHash.Keys) { $check = [RunbookCheck]::new() $checkValue = $checkSetHash[$checkKey] switch ($checkValue.GetType().Name.ToLower()) { "string" { $check.SelectorName = $checkValue } "orderedhashtable" { $check.SelectorName = $checkValue.selector $check.Parameters = ($checkValue.parameters ?? @{}) $check.Tags = ($checkValue.tags ?? @()) } } $checkSet.Checks[$checkKey] = $check } $runbook.CheckSets[$checkSetKey] = $checkSet } return $runbook } } |