Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: policysync #1

Merged
merged 4 commits into from
Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
version: 2

updates:
- package-ecosystem: "github-actions"
directory: "/.github"
schedule:
interval: daily
120 changes: 120 additions & 0 deletions .github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/pwsh

#
# PowerShell Script
# - Update template library in terraform-azurerm-caf-enterprise-scale repository
#

[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter()][String]$AlzToolsPath = "$PWD/enterprise-scale/src/Alz.Tools",
[Parameter()][String]$TargetPath = "$PWD/alzlib",
[Parameter()][String]$SourcePath = "$PWD/enterprise-scale",
[Parameter()][String]$LineEnding = "unix",
[Parameter()][String]$ParserToolUrl = "https://github.com/jaredfholgate/template-parser/releases/download/0.1.18"
)

$ErrorActionPreference = "Stop"

# This script relies on a custom set of classes and functions
# defined within the EnterpriseScaleLibraryTools PowerShell
# module.
Import-Module $AlzToolsPath -ErrorAction Stop

$parserPath = "$TargetPath/.github/scripts"
$parserExe = "Template.Parser.Cli"
if ($IsWindows) {
$parserExe += ".exe"
}

$parser = "$parserPath/$parserExe"

if (!(Test-Path $parser)) {
Write-Information "Downloading Template Parser." -InformationAction Continue
Invoke-WebRequest "$ParserToolUrl/$parserExe" -OutFile $parser
if ($IsLinux) {
chmod +x $parser
}
}

# Update the policy assignments if enabled
Write-Information "Updating Policy Assignment Archetypes." -InformationAction Continue

$eslzArmSourcePath = "$SourcePath/eslzArm/eslzArm.json"
$eslzArmParametersSourcePath = "$SourcePath/eslzArm/eslzArm.terraform-sync.param.json"

$eslzArm = & $parser "-s $eslzArmSourcePath" "-f $eslzArmParametersSourcePath" "-a" | Out-String | ConvertFrom-Json

$policyAssignments = New-Object 'System.Collections.Generic.Dictionary[string,System.Collections.Generic.List[string]]'

foreach ($resource in $eslzArm) {
$scope = $resource.scope
$policyAssignment = $resource.properties.templateLink.uri

if ($null -ne $policyAssignment -and $policyAssignment.StartsWith("https://deploymenturi/managementGroupTemplates/policyAssignments/") -and $resource.condition) {
$managementGroup = $scope.Split("/")[-1]
$policyAssignmentFileName = $policyAssignment.Split("/")[-1]

if (!($policyAssignmentFileName.StartsWith("fairfax"))) {
if (!($policyAssignments.ContainsKey($managementGroup))) {
$values = New-Object 'System.Collections.Generic.List[string]'
$values.Add($policyAssignmentFileName)
$policyAssignments.Add($managementGroup, $values)
}
else {
$policyAssignments[$managementGroup].Add($policyAssignmentFileName)
}
}
}
}

$managementGroupMapping = @{
"defaults" = "root"
"management" = "management"
"connectivity" = "connectivity"
"corp" = "corp"
"landingzones" = "landing_zones"
"decommissioned" = "decommissioned"
"sandboxes" = "sandboxes"
"identity" = "identity"
"platform" = "platform"
}

$finalPolicyAssignments = New-Object 'System.Collections.Generic.Dictionary[string,System.Collections.Generic.List[string]]'

$policyAssignmentSourcePath = "$SourcePath/eslzArm/managementGroupTemplates/policyAssignments"



foreach ($managementGroup in $policyAssignments.Keys) {
foreach ($policyAssignmentFile in $policyAssignments[$managementGroup]) {
$parsedAssignment = & $parser "-s $policyAssignmentSourcePath/$policyAssignmentFile" | Out-String | ConvertFrom-Json
$policyAssignmentName = $parsedAssignment.name

$managementGroupNameFinal = $managementGroupMapping[$managementGroup.Replace("defaults-", "")]

Write-Information "Got final data for $managementGroupNameFinal and $policyAssignmentName" -InformationAction Continue

if (!($finalPolicyAssignments.ContainsKey($managementGroupNameFinal))) {
$values = New-Object 'System.Collections.Generic.List[string]'
$values.Add($policyAssignmentName)
$finalPolicyAssignments.Add($managementGroupNameFinal, $values)
}
else {
$finalPolicyAssignments[$managementGroupNameFinal].Add($policyAssignmentName)
}
}
}

$policyAssignmentTargetPath = "$TargetPath/lib/archetype_definitions"

foreach ($managementGroup in $finalPolicyAssignments.Keys) {
$archetypeFilePath = "$policyAssignmentTargetPath/archetype_definition_$managementGroup.json"
$archetypeJson = Get-Content $archetypeFilePath | ConvertFrom-Json

$archetypeJson.policy_assignments = @($finalPolicyAssignments[$managementGroup] | Sort-Object)

Write-Information "Writing $archetypeFilePath" -InformationAction Continue
$json = $archetypeJson | ConvertTo-Json -Depth 10
$json | Edit-LineEndings -LineEnding $LineEnding | Out-File -FilePath "$archetypeFilePath" -Force
}
153 changes: 153 additions & 0 deletions .github/scripts/Invoke-LibraryUpdatePolicyAssignments.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/usr/bin/pwsh

#
# PowerShell Script
# - Update template library in terraform-azurerm-caf-enterprise-scale repository
#

[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter()][String]$AlzToolsPath = "$PWD/enterprise-scale/src/Alz.Tools",
[Parameter()][String]$TargetPath = "$PWD/alzlib",
[Parameter()][String]$SourcePath = "$PWD/enterprise-scale",
[Parameter()][String]$LineEnding = "unix",
[Parameter()][String]$ParserToolUrl = "https://github.com/jaredfholgate/template-parser/releases/download/0.1.18"
)

$ErrorActionPreference = "Stop"

# This script relies on a custom set of classes and functions
# defined within the EnterpriseScaleLibraryTools PowerShell
# module.
Import-Module $AlzToolsPath -ErrorAction Stop

$parserPath = "$TargetPath/.temp/scripts"
$parserExe = "Template.Parser.Cli"
if ($IsWindows) {
$parserExe += ".exe"
}

$parser = "$parserPath/$parserExe"

if (!(Test-Path $parser)) {
Write-Information "Downloading Template Parser." -InformationAction Continue
New-Item -ItemType Directory -Path $parserPath -Force | Out-Null
Invoke-WebRequest "$ParserToolUrl/$parserExe" -OutFile $parser
if (! $IsWindows) {
$isExecutable = $(test -x "$parser"; 0 -eq $LASTEXITCODE)
if (!($isExecutable)) {
chmod +x $parser
}
}
}

# Update the policy assignments if enabled
Write-Information "Updating Policy Assignments." -InformationAction Continue
$policyAssignmentSourcePath = "$SourcePath/eslzArm/managementGroupTemplates/policyAssignments"
$policyAssignmentTargetPath = "$TargetPath/policy_assignments"
$sourcePolicyAssignmentFiles = Get-ChildItem -Path $policyAssignmentSourcePath -File
$targetPolicyAssignmentFiles = Get-ChildItem -Path $policyAssignmentTargetPath -File

# $temporaryNameMatches = @{
# "Deny-IP-forwarding" = "Deny-IP-Forwarding"
# "Deny-Priv-Esc-AKS" = "Deny-Priv-Containers-AKS"
# "Deny-Privileged-AKS" = "Deny-Priv-Escalation-AKS"
# }

$defaultParameterValues = @(
"-p nonComplianceMessagePlaceholder={donotchange}"
"-p logAnalyticsWorkspaceName=placeholder",
"-p automationAccountName=placeholder",
"-p workspaceRegion=placeholder",
"-p automationRegion=placeholder",
"-p retentionInDays=30",
"-p rgName=placeholder",
"-p logAnalyticsResourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/placeholder/providers/Microsoft.OperationalInsights/workspaces/placeholder",
"-p topLevelManagementGroupPrefix=alz",
"-p dnsZoneResourceGroupId=placeholder",
"-p ddosPlanResourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/placeholder/providers/Microsoft.Network/ddosProtectionPlans/placeholder",
"-p emailContactAsc=security_contact@replace_me"
)

$parsedAssignments = @{}
foreach ($sourcePolicyAssignmentFile in $sourcePolicyAssignmentFiles) {
$parsedAssignment = & $parser "-s $sourcePolicyAssignmentFile" $defaultParameterValues | Out-String | ConvertFrom-Json
$parsedAssignments[$parsedAssignment.name] = @{
json = $parsedAssignment
file = $sourcePolicyAssignmentFile
}
# if (!(Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json.properties -Name "scope" -MemberType Properties)) {
# $parsedAssignments[$parsedAssignment.name].json.properties | Add-Member -MemberType NoteProperty -Name "scope" -Value "`${current_scope_resource_id}"
# }

if (!(Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json.properties -Name "notScopes" -MemberType Properties)) {
$parsedAssignments[$parsedAssignment.name].json.properties | Add-Member -MemberType NoteProperty -Name "notScopes" -Value @()
}

if (!(Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json.properties -Name "parameters" -MemberType Properties)) {
$parsedAssignments[$parsedAssignment.name].json.properties | Add-Member -MemberType NoteProperty -Name "parameters" -Value @{}
}

# if (!(Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json -Name "location" -MemberType Properties)) {
# $parsedAssignments[$parsedAssignment.name].json | Add-Member -MemberType NoteProperty -Name "location" -Value "`${default_location}"
# }

if (!(Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json -Name "identity" -MemberType Properties)) {
$parsedAssignments[$parsedAssignment.name].json | Add-Member -MemberType NoteProperty -Name "identity" -Value @{ type = "None" }
}

# if ($parsedAssignments[$parsedAssignment.name].json.properties.policyDefinitionId.StartsWith("/providers/Microsoft.Management/managementGroups/`${temp}")) {
# $parsedAssignments[$parsedAssignment.name].json.properties.policyDefinitionId = $parsedAssignments[$parsedAssignment.name].json.properties.policyDefinitionId.Replace("/providers/Microsoft.Management/managementGroups/`${temp}", "`${root_scope_resource_id}")
# }

# foreach ($property in Get-Member -InputObject $parsedAssignments[$parsedAssignment.name].json.properties.parameters -MemberType NoteProperty) {
# $propertyName = $property.Name
# if ($parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value.StartsWith("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/")) {
# $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value = $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value.Replace("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/", "`${private_dns_zone_prefix}")
# $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value = $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value.Replace("privatelink.batch.azure.com", "privatelink.`${connectivity_location}.batch.azure.com")
# }
# if ($parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value.StartsWith("`${temp}")) {
# $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value = $parsedAssignments[$parsedAssignment.name].json.properties.parameters.($propertyName).value.Replace("`${temp}", "`${root_scope_id}")
# }
# }
}

$originalAssignments = @{}
foreach ($targetPolicyAssignmentFile in $targetPolicyAssignmentFiles) {
$originalAssignment = Get-Content $targetPolicyAssignmentFile | ConvertFrom-Json
$originalAssignments[$originalAssignment.name] = @{
json = $originalAssignment
file = $targetPolicyAssignmentFile
}
}

foreach ($key in $parsedAssignments.Keys | Sort-Object) {
$targetPolicyAssignmentFileName = "policy_assignment_$($key.ToLower() -replace "-", "_").json"

# $mappedKey = $key
# if ($temporaryNameMatches.ContainsKey($key)) {
# $mappedKey = $temporaryNameMatches[$key]
# }

$sourceFileName = $parsedAssignments[$key].file.Name

if ($originalAssignments.ContainsKey($key)) {
$originalFileName = $originalAssignments[$key].file.Name

Write-Information "Found match for $mappedKey $key $originalFileName $sourceFileName $targetPolicyAssignmentFileName" -InformationAction Continue
# if ($originalFileName -ne $targetPolicyAssignmentFileName) {
# Write-Information "Renaming $originalFileName to $targetPolicyAssignmentFileName" -InformationAction Continue
# Set-Location $policyAssignmentTargetPath
# git mv $originalAssignments[$key].file.FullName $targetPolicyAssignmentFileName
# Set-Location $SourcePath
# Set-Location ..
# }
}
else {
Write-Information "No match found for $mappedKey $key $sourceFileName $targetPolicyAssignmentFileName" -InformationAction Continue
}

Write-Information "Writing $targetPolicyAssignmentFileName" -InformationAction Continue
$json = $parsedAssignments[$key].json | ConvertTo-Json -Depth 10
$json | Edit-LineEndings -LineEnding $LineEnding | Out-File -FilePath "$policyAssignmentTargetPath/$targetPolicyAssignmentFileName" -Force
}
Loading
Loading