functions/Sync-ALZPolicyFromLibrary.ps1
function Sync-ALZPolicyFromLibrary { Param( [Parameter(Mandatory = $false)] [string] $DefinitionsRootFolder, [ValidateSet("ALZ", "AMBA")] [string]$Type = "ALZ", [Parameter(Mandatory = $true)] [string]$PacEnvironmentSelector, [string]$LibraryPath ) if ($LibraryPath -eq "") { if ($Tag) { git clone --depth 1 --branch $Tag https://github.com/anwather/Azure-Landing-Zones-Library.git .\temp $LibraryPath = ".\temp" } else { git clone --depth 1 https://github.com/anwather/Azure-Landing-Zones-Library.git .\temp $LibraryPath = ".\temp" } } if ($DefinitionsRootFolder -eq "") { if ($null -eq $env:PAC_DEFINITIONS_FOLDER) { if ($ModuleRoot) { $DefinitionsRootFolder = "./Definitions" } else { $DefinitionsRootFolder = "$PSScriptRoot/../../Definitions" } } else { $DefinitionsRootFolder = $env:PAC_DEFINITIONS_FOLDER } } try { $telemetryEnabled = (Get-Content $DefinitionsRootFolder/global-settings.jsonc | ConvertFrom-Json).telemetryOptOut $deploymentRootScope = (Get-Content $DefinitionsRootFolder/global-settings.jsonc | ConvertFrom-Json).pacEnvironments[0] if (!($telemetryEnabled)) { Write-Information "Telemetry is enabled" Submit-EPACTelemetry -Cuapid "pid-adaa7564-1962-46e6-92b4-735e91f76d43" -DeploymentRootScope $deploymentRootScope } else { Write-Information "Telemetry is disabled" } } catch {} New-Item -Path "$DefinitionsRootFolder\policyDefinitions" -ItemType Directory -Force -ErrorAction SilentlyContinue New-Item -Path "$DefinitionsRootFolder\policyDefinitions\$Type" -ItemType Directory -Force -ErrorAction SilentlyContinue New-Item -Path "$DefinitionsRootFolder\policySetDefinitions" -ItemType Directory -Force -ErrorAction SilentlyContinue New-Item -Path "$DefinitionsRootFolder\policySetDefinitions\$Type" -ItemType Directory -Force -ErrorAction SilentlyContinue New-Item -Path "$DefinitionsRootFolder\policyAssignments" -ItemType Directory -Force -ErrorAction SilentlyContinue New-Item -Path "$DefinitionsRootFolder\policyAssignments\$Type" -ItemType Directory -Force -ErrorAction SilentlyContinue # Create policy definition objects foreach ($file in Get-ChildItem -Path "$LibraryPath\platform\$($Type.ToLower())\policy_definitions" -Recurse -File -Include *.json) { $fileContent = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json $baseTemplate = @{ name = $fileContent.name properties = $fileContent.properties } $category = $baseTemplate.properties.Metadata.category if (!(Test-Path $DefinitionsRootFolder\policyDefinitions\$Type\$category)) { New-Item -Path $DefinitionsRootFolder\policyDefinitions\$Type\$category -ItemType Directory -Force -ErrorAction SilentlyContinue } $baseTemplate | Select-Object name, properties | ConvertTo-Json -Depth 50 | Out-File -FilePath $DefinitionsRootFolder\policyDefinitions\$Type\$category\$($fileContent.name).json -Force (Get-Content $DefinitionsRootFolder\policyDefinitions\$Type\$category\$($fileContent.name).json) -replace "\[\[", "[" | Set-Content $DefinitionsRootFolder\policyDefinitions\$Type\$category\$($fileContent.name).json } # Create policy set definition objects foreach ($file in Get-ChildItem -Path "$LibraryPath\platform\$($Type.ToLower())\policy_set_definitions" -Recurse -File -Include *.json) { $fileContent = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json $baseTemplate = @{ name = $fileContent.name properties = @{ description = $fileContent.properties.description displayName = $fileContent.properties.displayName metadata = $fileContent.properties.metadata parameters = $fileContent.properties.parameters policyType = $fileContent.properties.policyType policyDefinitionGroups = $fileContent.properties.policyDefinitionGroups } } $policyDefinitions = @() # Fix the policyDefinitionIds for custom policies foreach ($policyDefinition in $fileContent.properties.policyDefinitions) { $obj = @{ parameters = $policyDefinition.parameters groupNames = $policyDefinition.groupNames policyDefinitionReferenceId = $policyDefinition.policyDefinitionReferenceId } if ($policyDefinition.policyDefinitionId -match "managementGroups") { $obj.Add("policyDefinitionName", $policyDefinition.policyDefinitionId.split("/")[-1]) } else { $obj.Add("policyDefinitionId", $policyDefinition.policyDefinitionId) } $policyDefinitions += $obj } $baseTemplate.properties.policyDefinitions = $policyDefinitions $category = $baseTemplate.properties.Metadata.category if (!(Test-Path $DefinitionsRootFolder\policySetDefinitions\$Type\$category)) { New-Item -Path $DefinitionsRootFolder\policySetDefinitions\$Type\$category -ItemType Directory -Force -ErrorAction SilentlyContinue } $baseTemplate | Select-Object name, properties | ConvertTo-Json -Depth 50 | Out-File -FilePath $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json -Force (Get-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json) -replace "\[\[", "[" | Set-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json (Get-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json) -replace "variables\('scope'\)", "'/providers/Microsoft.Management/managementGroups/$managementGroupId'" | Set-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json (Get-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json) -replace "', '", "" | Set-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json (Get-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json) -replace "\[concat\(('(.+)')\)\]", "`$2" | Set-Content $DefinitionsRootFolder\policySetDefinitions\$Type\$category\$($fileContent.name).json } # Create assignment objects try { $structureFile = Get-Content .\$Type.policy_default_structure.json -ErrorAction Stop | ConvertFrom-Json switch ($structureFile.enforcementMode) { "Default" { $enforcementModeText = "must" } "DoNotEnforce" { $enforcementModeText = "should" } } } catch { Write-Host "No policy default structure file found. Please run Create-ALZPolicyDefaultStructure.ps1 first." exit } foreach ($file in Get-ChildItem -Path "$LibraryPath\platform\$($Type.ToLower())\archetype_definitions" -Recurse -File -Include *.json) { $archetypeContent = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json foreach ($requiredAssignment in $archetypeContent.policy_assignments) { switch ($Type) { "ALZ" { $fileContent = Get-ChildItem -Path $LibraryPath\platform\$Type\policy_assignments | Where-Object { $_.BaseName.Split(".")[0] -eq $requiredAssignment } | Get-Content -Raw | ConvertFrom-Json } "AMBA" { $fileContent = Get-ChildItem -Path $LibraryPath\platform\$Type\policy_assignments | Where-Object { $_.BaseName.Split(".")[0].Replace("_", "-") -eq $requiredAssignment } | Get-Content -Raw | ConvertFrom-Json } default { $fileContent = Get-ChildItem -Path $LibraryPath\platform\$Type\policy_assignments | Where-Object { $_.BaseName.Split(".")[0] -eq $requiredAssignment } | Get-Content -Raw | ConvertFrom-Json } } $baseTemplate = @{ nodeName = "$($archetypeContent.name)/$($fileContent.name)" assignment = @{ name = $fileContent.Name displayName = $fileContent.properties.displayName description = $fileContent.properties.description } definitionEntry = @{ displayName = $fileContent.properties.displayName } parameters = @{} enforcementMode = $structureFile.enforcementMode } # Definition Version if ($null -ne $fileContent.properties.definitionVersion) { $baseTemplate.Add("definitionVersion", $fileContent.properties.definitionVersion) } # Definition Entry if ($fileContent.properties.policyDefinitionId -match "placeholder.+policySetDefinition") { $baseTemplate.definitionEntry.Add("policySetName", ($fileContent.properties.policyDefinitionId).Split("/")[-1]) } elseif ($fileContent.properties.policyDefinitionId -match "placeholder.+policyDefinition") { $baseTemplate.definitionEntry.Add("policyName", ($fileContent.properties.policyDefinitionId).Split("/")[-1]) } else { if ($fileContent.properties.policyDefinitionId -match "policySetDefinitions") { $baseTemplate.definitionEntry.Add("policySetId", ($fileContent.properties.policyDefinitionId)) } else { $baseTemplate.definitionEntry.Add("policyId", ($fileContent.properties.policyDefinitionId)) } } #Scope $scopeTrim = $file.BaseName.split(".")[0] if ($scopeTrim -eq "root") { $scopeTrim = "alz" } if ($scopeTrim -eq "landing_zones") { $scopeTrim = "landingzones" } $scope = @{ $PacEnvironmentSelector = @( $structureFile.managementGroupNameMappings.$scopeTrim.value ) } $baseTemplate.Add("scope", $scope) # Base Parameters if ($fileContent.name -ne "Deploy-Private-DNS-Zones") { foreach ($parameter in $fileContent.properties.parameters.psObject.Properties.Name) { $baseTemplate.parameters.Add($parameter, $fileContent.properties.parameters.$parameter.value) } } # Non-compliance messages if ($null -ne $fileContent.properties.nonComplianceMessages) { $obj = @( @{ message = $fileContent.properties.nonComplianceMessages.message -replace "{enforcementMode}", $enforcementModeText } ) $baseTemplate.Add("nonComplianceMessages", $obj) } # Check for explicit parameters if ($fileContent.name -ne "Deploy-Private-DNS-Zones") { foreach ($key in $structureFile.defaultParameterValues.psObject.Properties.Name) { if ($structureFile.defaultParameterValues.$key.policy_assignment_name -eq $fileContent.name) { $keyName = $structureFile.defaultParameterValues.$key.parameters.parameter_name $baseTemplate.parameters.$keyName = $structureFile.defaultParameterValues.$key.parameters.value } } } else { $dnsZoneRegion = $structureFile.defaultParameterValues.private_dns_zone_region.parameters.value $dnzZoneSubscription = $structureFile.defaultParameterValues.private_dns_zone_subscription_id.parameters.value $dnzZoneResourceGroupName = $structureFile.defaultParameterValues.private_dns_zone_resource_group_name.parameters.value foreach ($parameter in $fileContent.properties.parameters.psObject.Properties.Name) { $value = "/subscriptions/$dnzZoneSubscription/resourceGroups/$dnzZoneResourceGroupName/providers/Microsoft.Network/privateDnsZones/$($fileContent.properties.parameters.$parameter.value.split("/")[-1])" #$value = $fileContent.properties.parameters.$parameter.value -replace "00000000-0000-0000-0000-000000000000", $dnzZoneSubscription -replace "placeholder", $dnzZoneResourceGroupName $baseTemplate.parameters.Add($parameter, $value) } } $category = $structureFile.managementGroupNameMappings.$scopeTrim.management_group_function if (!(Test-Path $DefinitionsRootFolder\policyAssignments\$Type\$category)) { New-Item -Path $DefinitionsRootFolder\policyAssignments\$Type\$category -ItemType Directory -Force -ErrorAction SilentlyContinue } $baseTemplate | Select-Object nodeName, assignment, definitionEntry, definitionVersion, enforcementMode, parameters, nonComplianceMessages, scope | ConvertTo-Json -Depth 50 | Out-File -FilePath $DefinitionsRootFolder\policyAssignments\$Type\$category\$($fileContent.name).json -Force (Get-Content $DefinitionsRootFolder\policyAssignments\$Type\$category\$($fileContent.name).json) -replace "\[\[", "[" | Set-Content $DefinitionsRootFolder\policyAssignments\$Type\$category\$($fileContent.name).json if ($fileContent.name -eq "Deploy-Private-DNS-Zones") { (Get-Content $DefinitionsRootFolder\policyAssignments\$Type\$category\$($fileContent.name).json) -replace "\.ne\.", ".$dnsZoneRegion." | Set-Content $DefinitionsRootFolder\policyAssignments\$Type\$category\$($fileContent.name).json } } } if ($LibraryPath -eq ".\temp") { Remove-Item .\temp -Recurse -Force -ErrorAction SilentlyContinue } } |