functions/Deploy-PolicyPlan.ps1
|
function Deploy-PolicyPlan { <# Deploys Policy resources from a plan file. Defines which Policy as Code (PAC) environment we are using, if omitted, the script prompts for a value. The values are read from `$DefinitionsRootFolder/global-settings.jsonc. Definitions folder path. Defaults to environment variable `$env:PAC_DEFINITIONS_FOLDER or './Definitions'. Input folder path for plan files. Defaults to environment variable `$env:PAC_INPUT_FOLDER, `$env:PAC_OUTPUT_FOLDER or './Output'. Use switch to indicate interactive use If set, do not deploy the exemptions plan. Deploy-PolicyPlan.ps1 -PacEnvironmentSelector "dev" -DefinitionsRootFolder "C:\git\policy-as-code\Definitions" -InputFolder "C:\git\policy-as-code\Output" -Interactive Deploys Policy resources from a plan file. Deploy-PolicyPlan.ps1 -PacEnvironmentSelector "dev" -Interactive Deploys Policy resources from a plan file. https://azure.github.io/enterprise-azure-policy-as-code/#deployment-scripts #> [CmdletBinding()] param ( [parameter( HelpMessage = "Defines which Policy as Code (PAC) environment we are using, if omitted, the script prompts for a value. The values are read from `$DefinitionsRootFolder/global-settings.jsonc.", Position = 0 )] [string] $PacEnvironmentSelector, [Parameter(HelpMessage = "Definitions folder path. Defaults to environment variable `$env:PAC_DEFINITIONS_FOLDER or './Definitions'.")] [string]$DefinitionsRootFolder, [Parameter(HelpMessage = "Input folder path for plan files. Defaults to environment variable `$env:PAC_INPUT_FOLDER, `$env:PAC_OUTPUT_FOLDER or './Output'.")] [string] $InputFolder, [Parameter(HelpMessage = "Use switch to indicate interactive use")] [switch] $Interactive, [Parameter(HelpMessage = "If set, do not deploy the exemptions plan.")] [switch] $SkipExemptions, [Parameter(HelpMessage = "Set true to fail the pipeline and deployment if a 403 error occurs during creation and updates of exemptions.")] [bool] $FailOnExemptionError = $false ) $PSDefaultParameterValues = @{ "Write-Information:InformationVariable" = "+global:epacInfoStream" } Clear-Variable -Name epacInfoStream -Scope global -Force -ErrorAction SilentlyContinue $Global:epacInfoStream = @() # Dot Source Helper Scripts $InformationPreference = "Continue" $scriptStartTime = Get-Date # Display welcome header Write-ModernHeader -Title "Enterprise Policy as Code (EPAC)" -Subtitle "Deploying Policy Plan" -HeaderColor Magenta -SubtitleColor DarkMagenta $pacEnvironment = Select-PacEnvironment $PacEnvironmentSelector -DefinitionsRootFolder $DefinitionsRootFolder -InputFolder $InputFolder -Interactive $Interactive $null = Set-AzCloudTenantSubscription -Cloud $pacEnvironment.cloud -TenantId $pacEnvironment.tenantId -Interactive $pacEnvironment.interactive -DeploymentDefaultContext $pacEnvironment.defaultContext # Display environment information Write-ModernSection -Title "Environment Configuration" -Color Blue Write-ModernStatus -Message "PAC Environment: $($pacEnvironment.pacSelector)" -Status "info" -Indent 2 Write-ModernStatus -Message "Deployment Root: $($pacEnvironment.deploymentRootScope)" -Status "info" -Indent 2 Write-ModernStatus -Message "Input Folder: $InputFolder" -Status "info" -Indent 2 # Telemetry if ($pacEnvironment.telemetryEnabled) { Write-ModernStatus -Message "Telemetry is enabled" -Status "info" -Indent 2 Submit-EPACTelemetry -Cuapid "pid-fe9ff1e8-5521-4b9d-ab1d-84e15447565e" -DeploymentRootScope $pacEnvironment.deploymentRootScope } else { Write-ModernStatus -Message "Telemetry is disabled" -Status "info" -Indent 2 } $planFile = $pacEnvironment.policyPlanInputFile $plan = Get-DeploymentPlan -PlanFile $planFile if ($null -eq $plan) { Write-ModernSection -Title "Deployment Status" -Color Red Write-ModernStatus -Message "Plan file '$planFile' does not exist, skipping Policy resource deployment" -Status "error" -Indent 2 exit } else { Write-ModernSection -Title "Deployment Plan Loaded" -Color Green Write-ModernStatus -Message "Plan file: $planFile" -Status "success" -Indent 2 Write-ModernStatus -Message "Plan created on: $($plan.createdOn)" -Status "info" -Indent 2 #region delete exemptions, assignment, definitions if (-not $SkipExemptions) { $table = ConvertTo-HashTable $plan.exemptions.delete $table += ConvertTo-HashTable $plan.exemptions.replace if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Deleting Policy Exemptions ($($table.psbase.Count) items)" -Color Red Write-ModernStatus -Message "Removing $($table.psbase.Count) orphaned, deleted, expired and replaced exemptions" -Status "info" -Indent 2 foreach ($id in $table.Keys) { $entry = $table.$id Write-ModernStatus -Message "$($entry.displayName) ($($entry.name)) at scope: $($entry.scope)" -Status "info" -Indent 4 Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $pacEnvironment.apiVersions.policyExemptions } } } $table = ConvertTo-HashTable $plan.assignments.delete $table += ConvertTo-HashTable $plan.assignments.replace if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Deleting Policy Assignments ($($table.psbase.Count) items)" -Color Red foreach ($id in $table.Keys) { $entry = $table.$id Write-ModernStatus -Message "$($entry.displayName)" -Status "info" -Indent 2 Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $pacEnvironment.apiVersions.policyAssignments } } $table = ConvertTo-HashTable $plan.policySetDefinitions.delete $table += ConvertTo-HashTable $plan.policySetDefinitions.replace if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Deleting Policy Set Definitions ($($table.psbase.Count) items)" -Color Red foreach ($id in $table.Keys) { $entry = $table.$id Write-ModernStatus -Message "$($entry.displayName)" -Status "info" -Indent 2 Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $pacEnvironment.apiVersions.policySetDefinitions } } $table = ConvertTo-HashTable $plan.policyDefinitions.replace if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Deleting Replaced Policies ($($table.psbase.Count) items)" -Color Red foreach ($id in $table.Keys) { $entry = $table.$id Write-ModernStatus -Message "Removing:`n Display Name: $($entry.displayName)`n ID: $id" -Status "pending" -Indent 2 Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $pacEnvironment.apiVersions.policyDefinitions } } #endregion $table = ConvertTo-HashTable $plan.policyDefinitions.new $table += ConvertTo-HashTable $plan.policyDefinitions.replace $table += ConvertTo-HashTable $plan.policyDefinitions.update if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Creating and Updating Policies ($($table.psbase.Count) items)" -Color Blue foreach ($id in $table.Keys) { $entry = $table.$id Set-AzPolicyDefinitionRestMethod -Definition $entry -ApiVersion $pacEnvironment.apiVersions.policyDefinitions Write-ModernStatus -Message "Completed: $($entry.displayName)" -Status "success" -Indent 4 Write-Information "" } } $table = ConvertTo-HashTable $plan.policySetDefinitions.new $table += ConvertTo-HashTable $plan.policySetDefinitions.replace $table += ConvertTo-HashTable $plan.policySetDefinitions.update if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Creating and Updating Policy Sets ($($table.psbase.Count) items)" -Color Green foreach ($id in $table.Keys) { $entry = $table.$id Set-AzPolicySetDefinitionRestMethod -Definition $entry -ApiVersion $pacEnvironment.apiVersions.policySetDefinitions Write-ModernStatus -Message "Completed: $($entry.displayName)" -Status "success" -Indent 4 Write-Information "" } } # Policy Sets are updated, can now delete the obsolete Policies $table = ConvertTo-HashTable $plan.policyDefinitions.delete if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Deleting Obsolete Policies ($($table.psbase.Count) items)" -Color Red foreach ($id in $table.Keys) { $entry = $table.$id Write-ModernStatus -Message "Removing:`n Display Name: $($entry.displayName)`n ID: $id" -Status "pending" -Indent 2 Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $pacEnvironment.apiVersions.policyDefinitions } } $table = ConvertTo-HashTable $plan.assignments.new $table += ConvertTo-HashTable $plan.assignments.replace $table += ConvertTo-HashTable $plan.assignments.update if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Creating and Updating Assignments ($($table.psbase.Count) items)" -Color Yellow foreach ($id in $table.Keys) { $entry = $table.$id Set-AzPolicyAssignmentRestMethod -Assignment $entry -ApiVersion $pacEnvironment.apiVersions.policyAssignments Write-ModernStatus -Message "Completed: $($entry.displayName)" -Status "success" -Indent 4 Write-Information "" } } if (-not $SkipExemptions) { $table = ConvertTo-HashTable $plan.exemptions.new $table += ConvertTo-HashTable $plan.exemptions.replace $table += ConvertTo-HashTable $plan.exemptions.update if ($table.psbase.Count -gt 0) { Write-ModernSection -Title "Creating and Updating Exemptions ($($table.psbase.Count) items)" -Color Cyan foreach ($exemptionId in $table.Keys) { $entry = $table.$exemptionId Write-ModernStatus -Message "Processing: $($entry.displayName)" -Status "pending" -Indent 2 Set-AzPolicyExemptionRestMethod -ExemptionObj $entry -ApiVersion $pacEnvironment.apiVersions.policyExemptions -FailOnExemptionError $FailOnExemptionError Write-ModernStatus -Message "Completed Successfully!" -Status "success" -Indent 4 Write-Information "" } } } # Calculate execution time $scriptEndTime = Get-Date $executionTime = $scriptEndTime - $scriptStartTime # Display completion summary Write-ModernSection -Title "Deployment Complete" -Color Green Write-ModernStatus -Message "Plan file: $planFile" -Status "success" -Indent 2 Write-ModernStatus -Message "Execution time: $($executionTime.ToString('mm\:ss'))" -Status "info" -Indent 2 Write-ModernStatus -Message "All policy resources have been successfully deployed" -Status "success" -Indent 2 } } |