From c93000ed1c961a1e4562c07736996e761c53d43b Mon Sep 17 00:00:00 2001 From: Anthony Watherston Date: Mon, 3 Feb 2025 10:58:17 +1100 Subject: [PATCH] Fixes to export script (#866) Co-authored-by: Anthony Watherston --- Docs/operational-scripts.md | 10 +-- .../Confirm-ObjectValueEqualityDeep.ps1 | 22 +++++++ Scripts/Operations/Export-PolicyToEPAC.ps1 | 66 +++++++++++++++---- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/Docs/operational-scripts.md b/Docs/operational-scripts.md index 50fec594..4ac5cca3 100644 --- a/Docs/operational-scripts.md +++ b/Docs/operational-scripts.md @@ -36,9 +36,9 @@ The Hydration Kit is a set of scripts that can be used to deploy an EPAC environ The scripts `New-AzureDevOpsBug` and `New-GitHubIssue` create a Bug or Issue when there are one or multiple failed Remediation Tasks. -## Export from AzAdvertizer +## Export Policy To EPAC -The script `Export-PolicyToEPAC.ps1` creates for you the policyAssignments, policyDefinitions, and policySetDefinitions based on the provided URL in an Output folder under 'ALZ-Export'. +The script `Export-PolicyToEPAC.ps1` creates for you the policyAssignments, policyDefinitions, and policySetDefinitions based on the provided definition/set ID into an Output folder under 'Export'. Parameters: @@ -56,9 +56,11 @@ Parameters: * **UseBuiltIn**: Default to using builtin policies rather than local versions. -* **Scope**: Used to set scope value on each assignment file. +* **PacSelector**: Used to set PacEnvironment for each assignment file based on the pac selector privided. This pulls from global-settings.jsonc, therefore it must exist or an erro will be thrown. -* **PacSelector**: Used to set PacEnvironment for each assignment file. +* **OverwriteScope**: Used to overwrite scope value on each assignment file. + +* **OverwritePacSelector**: Used to overwrite PacEnvironment for each assignment file. * **OverwriteOutput**: Used to Overwrite the contents of the output folder with each run. Helpful when running consecutively. diff --git a/Scripts/Helpers/Confirm-ObjectValueEqualityDeep.ps1 b/Scripts/Helpers/Confirm-ObjectValueEqualityDeep.ps1 index b2f4c116..e196f37b 100644 --- a/Scripts/Helpers/Confirm-ObjectValueEqualityDeep.ps1 +++ b/Scripts/Helpers/Confirm-ObjectValueEqualityDeep.ps1 @@ -37,9 +37,31 @@ function Confirm-ObjectValueEqualityDeep { # $Object1 or $Object2 is an array or ArrayList if ($Object1 -isnot [System.Collections.Ilist]) { $Object1 = @($Object1) + # This resolves a unique situation where GraphApi returns a string instead of an array for a metadata value, very unique situation + # By testing the json and count, we can confirm that it is a json string and convert it to an array + # A try catch is included to revert to the value we normally use in the event of failure just in case there is a scenario that has not been accounted for + if ($(Test-Json -InputObject $Object1) -and $Object1.count -eq 1) { + try { + $Object1 = $Object1 | ConvertFrom-Json -Depth 100 + } + catch { + $Object1 = @($Object1) + } + } } elseif ($Object2 -isnot [System.Collections.Ilist]) { $Object2 = @($Object2) + # This resolves a unique situation where GraphApi returns a string instead of an array for a metadata value, very unique situation + # By testing the json and count, we can confirm that it is a json string and convert it to an array + # A try catch is included to revert to the value we normally use in the event of failure just in case there is a scenario that has not been accounted for + if ($(Test-Json -InputObject $Object2) -and $Object2.count -eq 1) { + try { + $Object2 = $Object2 | ConvertFrom-Json -Depth 100 + } + catch { + $Object2 = @($Object2) + } + } } if ($Object1.Count -ne $Object2.Count) { return $false diff --git a/Scripts/Operations/Export-PolicyToEPAC.ps1 b/Scripts/Operations/Export-PolicyToEPAC.ps1 index 7234f9d3..5e29f668 100644 --- a/Scripts/Operations/Export-PolicyToEPAC.ps1 +++ b/Scripts/Operations/Export-PolicyToEPAC.ps1 @@ -23,10 +23,13 @@ .PARAMETER UseBuiltIn Default to using builtin policies rather than local versions. -.PARAMETER Scope +.PARAMETER PacSelector Used to set scope value on each assignment file. -.PARAMETER PacSelector +.PARAMETER OverwriteScope + Used to set scope value on each assignment file. + +.PARAMETER OverwritePacSelector Used to set PacEnvironment for each assignment file. .PARAMETER OverwriteOutput @@ -37,7 +40,7 @@ Retrieves Policy from Azure Portal, auto creates parameters to be manipulated in the assignment and sets assignment and policy set to use built-in policies rather than self hosted. .EXAMPLE - "./Export-PolicyToEPAC.ps1" -ALZPolicySetDefinitionId "Enforce-Guardrails-OpenAI" -PacSelector "EPAC-Prod" -Scope "/providers/Microsoft.Management/managementGroups/4fb849a3-3ff3-4362-af8e-45174cd753dd" + "./Export-PolicyToEPAC.ps1" -ALZPolicySetDefinitionId "Enforce-Guardrails-OpenAI" -PacSelector "EPAC-Prod" -OverwriteScope "/providers/Microsoft.Management/managementGroups/4fb849a3-3ff3-4362-af8e-45174cd753dd" Retrieves Policy from ALZ Repo, sets the PacSelector in the assignment files to "EPAC-Prod" and the scope to the management group path provided. #> @@ -65,10 +68,13 @@ param ( [bool] $UseBuiltIn = $true, [Parameter(Mandatory = $false, HelpMessage = "Used to set scope value on each assignment file")] - [string] $Scope, + [string] $PacSelector, + + [Parameter(Mandatory = $false, HelpMessage = "Used to set scope value on each assignment file")] + [string] $OverwriteScope, [Parameter(Mandatory = $false, HelpMessage = "Used to set PacEnvironment for each assignment file")] - [string] $PacSelector, + [string] $OverwritePacSelector, [Parameter(Mandatory = $false, HelpMessage = "Used to Overwrite the contents of the output folder with each run. Helpful when running consecutively")] [bool] $OverwriteOutput = $true @@ -651,6 +657,7 @@ elseif ($ALZPolicySetDefinitionId) { } else { Write-Error "Export-PolicyToEPAC requires at least one of the following: PolicyDefinitionId, PolicySetDefinitionId, ALZPolicyDefinitionId or ALZPolicySetDefinitionId!" + exit 1 } @@ -719,20 +726,51 @@ if ($policyObject) { $assignmentObject.children.assignment.displayName = "$policyDisplayName" $assignmentObject.children.assignment.description = "$policyDescription" - # Overwrite PacSelector is given - if ($PacSelector -and $PacSelector -ne "EPAC-Dev") { - $assignmentObject.children.scope | Add-Member -MemberType NoteProperty -Name "$PacSelector" -Value "" - $assignmentObject.children.scope.$PacSelector = $assignmentObject.children.scope.'EPAC-Dev' + # Set PacSelector from Global-Settings if given + if ($PacSelector) { + $filePath = "Definitions/global-settings.jsonc" + if (Test-Path -Path $filePath) { + $globalSettingsContent = Get-Content -Path $filePath | ConvertFrom-Json + } + else { + Write-Error "'global-settings.jconc' file found in the 'Definitions' folder." + exit 1 + } + $pacEnvironments = $globalSettingsContent.PacEnvironments + if ($pacEnvironments.pacSelector -contains "$PacSelector") { + foreach ($environment in $pacEnvironments) { + if ($environment.pacSelector -eq "$PacSelector") { + $tempScope = $environment.deploymentRootScope + $assignmentObject.children.scope | Add-Member -MemberType NoteProperty -Name "$PacSelector" -Value @("$tempScope") + $assignmentObject.children[0].nodeName = "$PacSelector" + $assignmentObject.children.scope.PSObject.Properties.Remove("EPAC-Dev") + } + } + } + else { + Write-Error "The PacSelector provided not found in 'global-settings.jconc' file." + exit 1 + } + + # Overwrite Scope if given + if ($OverwriteScope) { + $assignmentObject.children[0].scope.$PacSelector[0] = "$OverwriteScope" + } + } + + # Overwrite PacSelector if given + if ($OverwritePacSelector -and $OverwritePacSelector -ne "EPAC-Dev") { + $assignmentObject.children.scope | Add-Member -MemberType NoteProperty -Name "$OverwritePacSelector" -Value "" + $assignmentObject.children.scope.$OverwritePacSelector = $assignmentObject.children.scope.'EPAC-Dev' $assignmentObject.children.scope.PSObject.Properties.Remove("EPAC-Dev") } # Overwrite Scope if given - if ($Scope -and $PacSelector) { - $assignmentObject.children.scope.$PacSelector = "$Scope" + if ($OverwriteScope -and $OverwritePacSelector -and !$PacSelector) { + $assignmentObject.children.scope.$OverwritePacSelector[0] = "$OverwriteScope" } - elseif ($Scope -and !$PacSelector) { - $assignmentObject.children.scope.'EPAC-Dev' = "$Scope" - + elseif ($OverwriteScope -and !$OverwritePacSelector -and !$PacSelector) { + $assignmentObject.children.scope.'EPAC-Dev'[0] = "$OverwriteScope" } #region AutoParameter