diff --git a/.github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1 b/.github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1 index 11f3cf280..a0e05c004 100644 --- a/.github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1 +++ b/.github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1 @@ -7,37 +7,36 @@ [CmdletBinding(SupportsShouldProcess)] param ( - [Parameter()][String]$AlzToolsPath = "$PWD/enterprise-scale/src/Alz.Tools", - [Parameter()][String]$TargetPath = "$PWD/terraform-azurerm-caf-enterprise-scale", - [Parameter()][String]$SourcePath = "$PWD/enterprise-scale", - [Parameter()][String]$LineEnding = "unix", - [Parameter()][String]$ParserToolUrl = "https://github.com/Azure/arm-template-parser/releases/download/0.2.2" + [Parameter()][String]$TargetPath = "$PWD/terraform-azurerm-caf-enterprise-scale", + [Parameter()][String]$SourcePath = "$PWD/enterprise-scale", + [Parameter()][String]$ParserToolUrl = "https://github.com/Azure/arm-template-parser/releases/download/0.2.2" +) + +$assignmentsToSkip = @( + "Enforce-Encryption-CMK" # Deprecated and breaks as we don't support policy versioning ) $ErrorActionPreference = "Stop" -# This script relies on a custom set of classes and functions -# defined within the EnterpriseScaleLibraryTools PowerShell -# module. -Import-Module $AlzToolsPath -ErrorAction 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" +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 - } +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 @@ -48,102 +47,104 @@ $eslzArmParametersSourcePath = "$SourcePath/eslzArm/eslzArm.terraform-sync.param $eslzArm = & $parser "-s $eslzArmSourcePath" "-f $eslzArmParametersSourcePath" "-a" | Out-String | ConvertFrom-Json +# create a dictionary of policy assignment names to a string for enforcement mode +$enforcementModeLookup = New-Object 'System.Collections.Generic.Dictionary[Tuple[string,string],string]' + $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" } -$managementGroupMapping = @{ - "defaults" = "root" - "management" = "management" - "connectivity" = "connectivity" - "corp" = "corp" - "landingzones" = "landing_zones" - "decommissioned" = "decommissioned" - "sandboxes" = "sandboxes" - "identity" = "identity" - "platform" = "platform" +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) + } + $newMg = $managementGroupMapping[$managementGroup.Replace("defaults-", "")] + Write-Verbose "Adding enforcement mode for $newMg - ${policyAssignmentFileName}: $enforcementMode" + $enforcementModeLookup[[Tuple]::Create($newMg, $policyAssignmentFileName)] = $enforcementMode + } + } } + $logAnalyticsWorkspaceIdPlaceholder = "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/`${root_scope_id}-mgmt/providers/Microsoft.OperationalInsights/workspaces/`${root_scope_id}-la" $parameters = @{ - default = @{ - nonComplianceMessagePlaceholder = "{donotchange}" - logAnalyticsWorkspaceName = "`${root_scope_id}-la" - automationAccountName = "`${root_scope_id}-automation" - workspaceRegion = "`${default_location}" - automationRegion = "`${default_location}" - retentionInDays = "30" - rgName = "`${root_scope_id}-mgmt" - logAnalyticsResourceId = "$logAnalyticsWorkspaceIdPlaceholder" - topLevelManagementGroupPrefix = "`${temp}" - dnsZoneResourceGroupId = "`${private_dns_zone_prefix}" - ddosPlanResourceId = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/`${root_scope_id}-mgmt/providers/Microsoft.Network/ddosProtectionPlans/`${root_scope_id}-ddos" - emailContactAsc = "security_contact@replace_me" - location = "uksouth" - listOfResourceTypesDisallowedForDeletion = "[[[Array]]]" - userWorkspaceResourceId = "$logAnalyticsWorkspaceIdPlaceholder" - userAssignedIdentityResourceId = "`${user_assigned_managed_identity_resource_id}" - dcrResourceId = "`${azure_monitor_data_collection_rule_resource_id}" - dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_resource_id}" + default = @{ + nonComplianceMessagePlaceholder = "{donotchange}" + logAnalyticsWorkspaceName = "`${root_scope_id}-la" + automationAccountName = "`${root_scope_id}-automation" + workspaceRegion = "`${default_location}" + automationRegion = "`${default_location}" + retentionInDays = "30" + rgName = "`${root_scope_id}-mgmt" + logAnalyticsResourceId = "$logAnalyticsWorkspaceIdPlaceholder" + topLevelManagementGroupPrefix = "`${temp}" + dnsZoneResourceGroupId = "`${private_dns_zone_prefix}" + ddosPlanResourceId = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/`${root_scope_id}-mgmt/providers/Microsoft.Network/ddosProtectionPlans/`${root_scope_id}-ddos" + emailContactAsc = "security_contact@replace_me" + location = "uksouth" + listOfResourceTypesDisallowedForDeletion = "[[[Array]]]" + userWorkspaceResourceId = "$logAnalyticsWorkspaceIdPlaceholder" + userAssignedIdentityResourceId = "`${user_assigned_managed_identity_resource_id}" + dcrResourceId = "`${azure_monitor_data_collection_rule_resource_id}" + dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_resource_id}" + } + overrides = @{ + sql_data_collection_rule_overrides = @{ + policy_assignments = @( + "DINE-MDFCDefenderSQLAMAPolicyAssignment.json" + ) + parameters = @{ + dcrResourceId = "`${azure_monitor_data_collection_rule_sql_resource_id}" + dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_sql_resource_id}" + } } - overrides = @{ - sql_data_collection_rule_overrides = @{ - policy_assignments = @( - "DINE-MDFCDefenderSQLAMAPolicyAssignment.json" - ) - parameters = @{ - dcrResourceId = "`${azure_monitor_data_collection_rule_sql_resource_id}" - dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_sql_resource_id}" - } - } - vm_insights_data_collection_rule_overrides = @{ - policy_assignments = @( - "DINE-VMHybridMonitoringPolicyAssignment.json", - "DINE-VMMonitoringPolicyAssignment.json", - "DINE-VMSSMonitoringPolicyAssignment.json" - ) - parameters = @{ - dcrResourceId = "`${azure_monitor_data_collection_rule_vm_insights_resource_id}" - dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_vm_insights_resource_id}" - } - } - change_tracking_data_collection_rule_overrides = @{ - policy_assignments = @( - "DINE-ChangeTrackingVMArcPolicyAssignment.json", - "DINE-ChangeTrackingVMPolicyAssignment.json", - "DINE-ChangeTrackingVMSSPolicyAssignment.json" - ) - parameters = @{ - dcrResourceId = "`${azure_monitor_data_collection_rule_change_tracking_resource_id}" - dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_change_tracking_resource_id}" - } - } + vm_insights_data_collection_rule_overrides = @{ + policy_assignments = @( + "DINE-VMHybridMonitoringPolicyAssignment.json", + "DINE-VMMonitoringPolicyAssignment.json", + "DINE-VMSSMonitoringPolicyAssignment.json" + ) + parameters = @{ + dcrResourceId = "`${azure_monitor_data_collection_rule_vm_insights_resource_id}" + dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_vm_insights_resource_id}" + } } + change_tracking_data_collection_rule_overrides = @{ + policy_assignments = @( + "DINE-ChangeTrackingVMArcPolicyAssignment.json", + "DINE-ChangeTrackingVMPolicyAssignment.json", + "DINE-ChangeTrackingVMSSPolicyAssignment.json" + ) + parameters = @{ + dcrResourceId = "`${azure_monitor_data_collection_rule_change_tracking_resource_id}" + dataCollectionRuleResourceId = "`${azure_monitor_data_collection_rule_change_tracking_resource_id}" + } + } + } } $finalPolicyAssignments = New-Object 'System.Collections.Generic.Dictionary[string,System.Collections.Generic.List[string]]' @@ -151,125 +152,120 @@ $finalPolicyAssignments = New-Object 'System.Collections.Generic.Dictionary[stri $policyAssignmentSourcePath = "$SourcePath/eslzArm/managementGroupTemplates/policyAssignments" $policyAssignmentTargetPath = "$TargetPath/modules/archetypes/lib/policy_assignments" -foreach($managementGroup in $policyAssignments.Keys) -{ - $managementGroupNameFinal = $managementGroupMapping[$managementGroup.Replace("defaults-", "")] - Write-Output "`nProcessing Archetype Policy Assignments for Management Group: $managementGroupNameFinal" - - foreach($policyAssignmentFile in $policyAssignments[$managementGroup]) - { - Write-Output "`nProcessing Archetype Policy Assignment: $managementGroupNameFinal - $policyAssignmentFile" - - $defaultParameters = $parameters.default - foreach($overrideKey in $parameters.overrides.Keys) - { - if($policyAssignmentFile -in $parameters.overrides[$overrideKey].policy_assignments) - { - foreach($parameter in $parameters.overrides[$overrideKey].parameters.Keys) - { - $defaultParameters.$parameter = $parameters.overrides[$overrideKey].parameters.$parameter - } - } +foreach ($managementGroup in $policyAssignments.Keys) { + $managementGroupNameFinal = $managementGroupMapping[$managementGroup.Replace("defaults-", "")] + Write-Output "`nProcessing Archetype Policy Assignments for Management Group: $managementGroupNameFinal" + + foreach ($policyAssignmentFile in $policyAssignments[$managementGroup]) { + Write-Output "`nProcessing Archetype Policy Assignment: $managementGroupNameFinal - $policyAssignmentFile" + + $defaultParameters = $parameters.default + foreach ($overrideKey in $parameters.overrides.Keys) { + if ($policyAssignmentFile -in $parameters.overrides[$overrideKey].policy_assignments) { + foreach ($parameter in $parameters.overrides[$overrideKey].parameters.Keys) { + $defaultParameters.$parameter = $parameters.overrides[$overrideKey].parameters.$parameter } + } + } + + $defaultParameterFormatted = $defaultParameters.GetEnumerator().ForEach({ "-p $($_.Name)=$($_.Value)" }) + + $parsedAssignmentArray = & $parser "-s $policyAssignmentSourcePath/$policyAssignmentFile" $defaultParameterFormatted "-a" | Out-String | ConvertFrom-Json - $defaultParameterFormatted = $defaultParameters.GetEnumerator().ForEach({ "-p $($_.Name)=$($_.Value)" }) - - $parsedAssignmentArray = & $parser "-s $policyAssignmentSourcePath/$policyAssignmentFile" $defaultParameterFormatted "-a" | Out-String | ConvertFrom-Json - - foreach($parsedAssignment in $parsedAssignmentArray) - { - if($parsedAssignment.type -ne "Microsoft.Authorization/policyAssignments") - { - continue - } - - $policyAssignmentName = $parsedAssignment.name - - Write-Output "Parsed Assignment Name: $($parsedAssignment.name)" - - if(!(Get-Member -InputObject $parsedAssignment.properties -Name "scope" -MemberType Properties)) - { - $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "scope" -Value "`${current_scope_resource_id}" - } - - if(!(Get-Member -InputObject $parsedAssignment.properties -Name "notScopes" -MemberType Properties)) - { - $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "notScopes" -Value @() - } - - if(!(Get-Member -InputObject $parsedAssignment.properties -Name "parameters" -MemberType Properties)) - { - $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "parameters" -Value @{} - } - - if(!(Get-Member -InputObject $parsedAssignment -Name "location" -MemberType Properties)) - { - $parsedAssignment | Add-Member -MemberType NoteProperty -Name "location" -Value "`${default_location}" - } - - if(!(Get-Member -InputObject $parsedAssignment -Name "identity" -MemberType Properties)) - { - $parsedAssignment | Add-Member -MemberType NoteProperty -Name "identity" -Value @{ type = "None" } - } - - if($parsedAssignment.properties.policyDefinitionId.StartsWith("/providers/Microsoft.Management/managementGroups/`${temp}")) - { - $parsedAssignment.properties.policyDefinitionId = $parsedAssignment.properties.policyDefinitionId.Replace("/providers/Microsoft.Management/managementGroups/`${temp}", "`${root_scope_resource_id}") - } - - foreach($property in Get-Member -InputObject $parsedAssignment.properties.parameters -MemberType NoteProperty) - { - $propertyName = $property.Name - Write-Verbose "Checking Parameter: $propertyName" - if($parsedAssignment.properties.parameters.($propertyName).value.GetType() -ne [System.String]) - { - Write-Verbose "Skipping non-string parameter: $propertyName" - continue - } - - if($parsedAssignment.properties.parameters.($propertyName).value.StartsWith("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/")) - { - $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/", "`${private_dns_zone_prefix}") - $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("privatelink.uks.backup.windowsazure.com", "privatelink.`${connectivity_location_short}.backup.windowsazure.com") - } - if($parsedAssignment.properties.parameters.($propertyName).value.StartsWith("`${temp}")) - { - $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("`${temp}", "`${root_scope_id}") - } - } - - $targetPolicyAssignmentFileName = "policy_assignment_es_$($policyAssignmentName.ToLower() -replace "-", "_").tmpl.json" - - Write-Information "Writing $targetPolicyAssignmentFileName" -InformationAction Continue - $json = $parsedAssignment | ConvertTo-Json -Depth 10 - $json | Edit-LineEndings -LineEnding $LineEnding | Out-File -FilePath "$policyAssignmentTargetPath/$targetPolicyAssignmentFileName" -Force - - Write-Verbose "Got final data for $managementGroupNameFinal and $policyAssignmentName" - - if(!($finalPolicyAssignments.ContainsKey($managementGroupNameFinal))) - { - $values = New-Object 'System.Collections.Generic.List[string]' - $values.Add($policyAssignmentName) - $finalPolicyAssignments.Add($managementGroupNameFinal, $values) - } - else - { - $finalPolicyAssignments[$managementGroupNameFinal].Add($policyAssignmentName) - } + foreach ($parsedAssignment in $parsedAssignmentArray) { + if ($parsedAssignment.type -ne "Microsoft.Authorization/policyAssignments") { + continue + } + + $policyAssignmentName = $parsedAssignment.name + + if ($assignmentsToSkip.Contains($policyAssignmentName)) { + continue + } + + Write-Output "Parsed Assignment Name: $($parsedAssignment.name)" + + if (!(Get-Member -InputObject $parsedAssignment.properties -Name "scope" -MemberType Properties)) { + $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "scope" -Value "`${current_scope_resource_id}" + } + + if (!(Get-Member -InputObject $parsedAssignment.properties -Name "notScopes" -MemberType Properties)) { + $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "notScopes" -Value @() + } + + if (!(Get-Member -InputObject $parsedAssignment.properties -Name "parameters" -MemberType Properties)) { + $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "parameters" -Value @{} + } + + if (!(Get-Member -InputObject $parsedAssignment -Name "location" -MemberType Properties)) { + $parsedAssignment | Add-Member -MemberType NoteProperty -Name "location" -Value "`${default_location}" + } + + if (!(Get-Member -InputObject $parsedAssignment -Name "identity" -MemberType Properties)) { + $parsedAssignment | Add-Member -MemberType NoteProperty -Name "identity" -Value @{ type = "None" } + } + + $enforcementMode = $enforcementModeLookup[[Tuple]::Create($managementGroupNameFinal, $policyAssignmentFile)] + if (($null -ne $enforcementMode) -and ($enforcementMode.Length -gt 0)) { + Write-Verbose "Setting enforcement mode for $policyAssignmentName to $enforcementMode" + if (!(Get-Member -InputObject $parsedAssignment.properties -Name "enforcementMode" -MemberType Properties)) { + $parsedAssignment.properties | Add-Member -MemberType NoteProperty -Name "enforcementMode" -Value $enforcementMode } + else { + $parsedAssignment.properties.enforcementMode = $enforcementMode + } + } + + if ($parsedAssignment.properties.policyDefinitionId.StartsWith("/providers/Microsoft.Management/managementGroups/`${temp}")) { + $parsedAssignment.properties.policyDefinitionId = $parsedAssignment.properties.policyDefinitionId.Replace("/providers/Microsoft.Management/managementGroups/`${temp}", "`${root_scope_resource_id}") + } + + foreach ($property in Get-Member -InputObject $parsedAssignment.properties.parameters -MemberType NoteProperty) { + $propertyName = $property.Name + Write-Verbose "Checking Parameter: $propertyName" + if ($parsedAssignment.properties.parameters.($propertyName).value.GetType() -ne [System.String]) { + Write-Verbose "Skipping non-string parameter: $propertyName" + continue + } + + if ($parsedAssignment.properties.parameters.($propertyName).value.StartsWith("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/")) { + $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("`${private_dns_zone_prefix}/providers/Microsoft.Network/privateDnsZones/", "`${private_dns_zone_prefix}") + $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("privatelink.uks.backup.windowsazure.com", "privatelink.`${connectivity_location_short}.backup.windowsazure.com") + } + if ($parsedAssignment.properties.parameters.($propertyName).value.StartsWith("`${temp}")) { + $parsedAssignment.properties.parameters.($propertyName).value = $parsedAssignment.properties.parameters.($propertyName).value.Replace("`${temp}", "`${root_scope_id}") + } + } + + $targetPolicyAssignmentFileName = "policy_assignment_es_$($policyAssignmentName.ToLower() -replace "-", "_").tmpl.json" + + Write-Information "Writing $targetPolicyAssignmentFileName" -InformationAction Continue + $json = $parsedAssignment | ConvertTo-Json -Depth 10 + $json | Out-File -FilePath "$policyAssignmentTargetPath/$targetPolicyAssignmentFileName" -Force + + Write-Verbose "Got final data for $managementGroupNameFinal and $policyAssignmentName" + + 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/modules/archetypes/lib/archetype_definitions" -foreach($managementGroup in $finalPolicyAssignments.Keys) -{ - $archetypeFilePath = "$policyAssignmentTargetPath/archetype_definition_es_$managementGroup.tmpl.json" - $archetypeJson = Get-Content $archetypeFilePath | ConvertFrom-Json +foreach ($managementGroup in $finalPolicyAssignments.Keys) { + $archetypeFilePath = "$policyAssignmentTargetPath/archetype_definition_es_$managementGroup.tmpl.json" + $archetypeJson = Get-Content $archetypeFilePath | ConvertFrom-Json - $archetypeJson.("es_$managementGroup").policy_assignments = @($finalPolicyAssignments[$managementGroup] | Sort-Object) + $archetypeJson.("es_$managementGroup").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 + Write-Information "Writing $archetypeFilePath" -InformationAction Continue + $json = $archetypeJson | ConvertTo-Json -Depth 10 + $json | Out-File -FilePath "$archetypeFilePath" -Force } diff --git a/.github/scripts/Invoke-LibraryUpdatePolicyDefinitions.ps1 b/.github/scripts/Invoke-LibraryUpdatePolicyDefinitions.ps1 index fc0567edf..855e965e4 100644 --- a/.github/scripts/Invoke-LibraryUpdatePolicyDefinitions.ps1 +++ b/.github/scripts/Invoke-LibraryUpdatePolicyDefinitions.ps1 @@ -21,12 +21,12 @@ [CmdletBinding(SupportsShouldProcess)] param ( - [Parameter()][String]$AlzToolsPath = "$PWD/enterprise-scale/src/Alz.Tools", - [Parameter()][String]$TargetPath = "$PWD/terraform-azurerm-caf-enterprise-scale", - [Parameter()][String]$SourcePath = "$PWD/enterprise-scale", - [Parameter()][String]$LineEnding = "unix", - [Parameter()][Switch]$Reset, - [Parameter()][Switch]$UpdateProviderApiVersions + [Parameter()][String]$AlzToolsPath = "$PWD/enterprise-scale/src/Alz.Tools", + [Parameter()][String]$TargetPath = "$PWD/terraform-azurerm-caf-enterprise-scale", + [Parameter()][String]$SourcePath = "$PWD/enterprise-scale", + [Parameter()][String]$LineEnding = "unix", + [Parameter()][Switch]$Reset, + [Parameter()][Switch]$UpdateProviderApiVersions ) $ErrorActionPreference = "Stop" @@ -41,35 +41,46 @@ Import-Module $AlzToolsPath -ErrorAction Stop # stored state in the module if the UseCacheFromModule flag # is set and the ProviderApiVersions.zip file is present. if (!$UpdateProviderApiVersions -and (Test-Path "$AlzToolsPath/ProviderApiVersions.zip")) { - Write-Information "Pre-loading ProviderApiVersions from saved cache." -InformationAction Continue - Invoke-UseCacheFromModule($AlzToolsPath) + Write-Information "Pre-loading ProviderApiVersions from saved cache." -InformationAction Continue + Invoke-UseCacheFromModule($AlzToolsPath) } # The defaultConfig object provides a set of default values # to reduce verbosity within the exportConfig object. $defaultConfig = @{ - inputFilter = "*.json" - resourceTypeFilter = @() - outputPath = $TargetPath + "/modules/archetypes/lib" - fileNamePrefix = "" - fileNameSuffix = ".json" - exportFormat = "Terraform" - recurse = $false + inputFilter = "*.json" + resourceTypeFilter = @() + outputPath = $TargetPath + "/modules/archetypes/lib" + fileNamePrefix = "" + fileNameSuffix = ".json" + exportFormat = "Terraform" + recurse = $false } +$excludePolicyDefinitions = @( + "*.AzureChinaCloud.json", + "*.AzureUSGovernment.json" +) + +$excludePolicySetDefinitions = @( + "*.AzureChineCloud.json", + "*.AzureUSGovernment.json", + "Enforce-Encryption-CMK.json" +) + # File locations from Enterprise-scale repository for # resources, organised by type $policyDefinitionFilePaths = ( - Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policyDefinitions/*" ` - -File ` - -Include "*.json" ` - -Exclude "*.AzureChinaCloud.json", "*.AzureUSGovernment.json" + Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policyDefinitions/*" ` + -File ` + -Include "*.json" ` + -Exclude $excludePolicyDefinitions ).FullName $policySetDefinitionFilePaths = ( - Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policySetDefinitions/*" ` - -File ` - -Include "*.json" ` - -Exclude "*.AzureChinaCloud.json", "*.AzureUSGovernment.json" + Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policySetDefinitions/*" ` + -File ` + -Include "*.json" ` + -Exclude $excludePolicySetDefinitions ).FullName # The exportConfig array controls the foreach loop used to run @@ -81,46 +92,46 @@ $policySetDefinitionFilePaths = ( $exportConfig = @() # Add Policy Definition source files to $exportConfig $exportConfig += $policyDefinitionFilePaths | -ForEach-Object { + ForEach-Object { [PsCustomObject]@{ - inputPath = $_ - resourceTypeFilter = "Microsoft.Authorization/policyDefinitions" - fileNamePrefix = "policy_definitions/policy_definition_es_" + inputPath = $_ + resourceTypeFilter = "Microsoft.Authorization/policyDefinitions" + fileNamePrefix = "policy_definitions/policy_definition_es_" } -} + } # Add Policy Set Definition source files to $exportConfig $exportConfig += $policySetDefinitionFilePaths | ForEach-Object { - [PsCustomObject]@{ - inputPath = $_ - resourceTypeFilter = "Microsoft.Authorization/policySetDefinitions" - fileNamePrefix = "policy_set_definitions/policy_set_definition_es_" - fileNameSuffix = ".tmpl.json" - } + [PsCustomObject]@{ + inputPath = $_ + resourceTypeFilter = "Microsoft.Authorization/policySetDefinitions" + fileNamePrefix = "policy_set_definitions/policy_set_definition_es_" + fileNameSuffix = ".tmpl.json" + } } # If the -Reset parameter is set, delete all existing # artefacts (by resource type) from the library if ($Reset) { - Write-Information "Deleting existing Policy Definitions from library." -InformationAction Continue - Remove-Item -Path "$TargetPath/modules/archetypes/lib/policy_definitions/" -Recurse -Force - Write-Information "Deleting existing Policy Set Definitions from library." -InformationAction Continue - Remove-Item -Path "$TargetPath/modules/archetypes/lib/policy_set_definitions/" -Recurse -Force + Write-Information "Deleting existing Policy Definitions from library." -InformationAction Continue + Remove-Item -Path "$TargetPath/modules/archetypes/lib/policy_definitions/" -Recurse -Force + Write-Information "Deleting existing Policy Set Definitions from library." -InformationAction Continue + Remove-Item -Path "$TargetPath/modules/archetypes/lib/policy_set_definitions/" -Recurse -Force } # Process the files added to $exportConfig, to add content # to the library foreach ($config in $exportConfig) { - Export-LibraryArtifact ` - -InputPath ($config.inputPath ?? $defaultConfig.inputPath) ` - -InputFilter ($config.inputFilter ?? $defaultConfig.inputFilter) ` - -ResourceTypeFilter ($config.resourceTypeFilter ?? $defaultConfig.resourceTypeFilter) ` - -OutputPath ($config.outputPath ?? $defaultConfig.outputPath) ` - -FileNamePrefix ($config.fileNamePrefix ?? $defaultConfig.fileNamePrefix) ` - -FileNameSuffix ($config.fileNameSuffix ?? $defaultConfig.fileNameSuffix) ` - -ExportFormat:($config.exportFormat ?? $defaultConfig.exportFormat) ` - -Recurse:($config.recurse ?? $defaultConfig.recurse) ` - -LineEnding $LineEnding ` - -WhatIf:$WhatIfPreference + Export-LibraryArtifact ` + -InputPath ($config.inputPath ?? $defaultConfig.inputPath) ` + -InputFilter ($config.inputFilter ?? $defaultConfig.inputFilter) ` + -ResourceTypeFilter ($config.resourceTypeFilter ?? $defaultConfig.resourceTypeFilter) ` + -OutputPath ($config.outputPath ?? $defaultConfig.outputPath) ` + -FileNamePrefix ($config.fileNamePrefix ?? $defaultConfig.fileNamePrefix) ` + -FileNameSuffix ($config.fileNameSuffix ?? $defaultConfig.fileNameSuffix) ` + -ExportFormat:($config.exportFormat ?? $defaultConfig.exportFormat) ` + -Recurse:($config.recurse ?? $defaultConfig.recurse) ` + -LineEnding $LineEnding ` + -WhatIf:$WhatIfPreference } # Get a list of current Policy Definition names diff --git a/.github/workflows/update-policy.yml b/.github/workflows/update-policy.yml index 1e6ae2cfe..9d4023626 100644 --- a/.github/workflows/update-policy.yml +++ b/.github/workflows/update-policy.yml @@ -84,7 +84,6 @@ jobs: Write-Information "==> Running policy assignments and archetypes script..." -InformationAction Continue ${{ github.repository }}/.github/scripts/Invoke-LibraryUpdatePolicyAssignmentArchetypes.ps1 ` - -AlzToolsPath "${{ github.workspace }}/${{ env.remote_repository }}/src/Alz.Tools/" ` -TargetPath "${{ github.workspace }}/${{ github.repository }}" ` -SourcePath "${{ github.workspace }}/${{ env.remote_repository }}" azPSVersion: "latest" @@ -113,6 +112,7 @@ jobs: echo "$PULL_REQUESTS" | jq -r '.[] | .number' | xargs -I {} gh pr close {} --delete-branch --comment "Out of date PR, closing and deleting branch" env: GH_TOKEN: ${{ steps.generate-token.outputs.token }} + working-directory: ${{ github.repository }} - name: Create pull request if: steps.git_status.outputs.changes > 0 diff --git a/tests/pipelines/templates/tests-backend.yml b/tests/pipelines/templates/tests-backend.yml index 6022e985f..5124cc92d 100644 --- a/tests/pipelines/templates/tests-backend.yml +++ b/tests/pipelines/templates/tests-backend.yml @@ -8,4 +8,4 @@ steps: scriptLocation: scriptPath scriptPath: "tests/scripts/azp-backend.sh" scriptType: bash - failOnStandardError: true + failOnStandardError: false diff --git a/tests/pipelines/templates/tests-common.yml b/tests/pipelines/templates/tests-common.yml index c5fe640b8..9678843ea 100644 --- a/tests/pipelines/templates/tests-common.yml +++ b/tests/pipelines/templates/tests-common.yml @@ -18,4 +18,4 @@ steps: scriptLocation: scriptPath scriptPath: "tests/scripts/tf-prepare.sh" scriptType: bash - failOnStandardError: true + failOnStandardError: false diff --git a/tests/pipelines/templates/tests-loop.yml b/tests/pipelines/templates/tests-loop.yml index 5129fc0ff..50c8f5986 100644 --- a/tests/pipelines/templates/tests-loop.yml +++ b/tests/pipelines/templates/tests-loop.yml @@ -12,7 +12,7 @@ steps: scriptType: bash scriptLocation: scriptPath scriptPath: "tests/scripts/tf-init.sh" - failOnStandardError: true + failOnStandardError: false addSpnToEnvironment: true azureSubscription: ado-mscet-cae-estf env: @@ -25,7 +25,7 @@ steps: scriptType: bash scriptLocation: scriptPath scriptPath: "tests/scripts/tf-plan.sh" - failOnStandardError: true + failOnStandardError: false addSpnToEnvironment: true azureSubscription: ado-mscet-cae-estf env: @@ -37,7 +37,7 @@ steps: inputs: scriptType: bash scriptLocation: scriptPath - failOnStandardError: true + failOnStandardError: false addSpnToEnvironment: true scriptPath: "tests/scripts/tf-apply.sh" azureSubscription: ado-mscet-cae-estf @@ -50,7 +50,7 @@ steps: inputs: scriptType: bash scriptLocation: scriptPath - failOnStandardError: true + failOnStandardError: false addSpnToEnvironment: true scriptPath: "tests/scripts/tf-destroy.sh" azureSubscription: ado-mscet-cae-estf diff --git a/tests/pipelines/templates/tests-strategy.yml b/tests/pipelines/templates/tests-strategy.yml index 019fa8e70..fee6b1cf0 100644 --- a/tests/pipelines/templates/tests-strategy.yml +++ b/tests/pipelines/templates/tests-strategy.yml @@ -7,7 +7,7 @@ steps: azureSubscription: ado-mscet-cae-estf scriptType: FilePath scriptPath: "tests/scripts/azp-strategy.ps1" - failOnStandardError: true - azurePowerShellVersion: 'LatestVersion' # Adding version specification for clarity + failOnStandardError: false + azurePowerShellVersion: "LatestVersion" # Adding version specification for clarity env: BILLING_SCOPE: $(BILLING_SCOPE)