New-CommentPolicySet.ps1
<#PSScriptInfo .VERSION 1.0.0 .GUID cc328e30-304f-426d-83c3-2ef20b68b97d .AUTHOR PaulHCode .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI https://github.com/PaulHCode/CommentPolicySet/blob/main/New-CommentPolicySet.ps1 .ICONURI .EXTERNALMODULEDEPENDENCIES Az.Resources Az.Accounts .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .SYNOPSIS This script will create a policy set definition for each control in a policy set which applies to each subscription. .DESCRIPTION You must be logged into the Azure account which has access to the subscriptions you wish to create the policy and sets in before running this script. This script will create a policy set definition for each group in the file or URL specified. It will then create a policy for each group in each subscription selected. It will then create a policy set definition for each subscription selected. It will then assign the policy set definition to each subscription selected. .EXAMPLE .\New-CommentPolicySet.ps1 -PolicyNamePrefix "800-53Comments" -RegulatoryComplianceSetDefinitionURL 'https://raw.githubusercontent.com/Azure/azure-policy/master/built-in-policies/policySetDefinitions/Regulatory%20Compliance/NIST_SP_800-53_R4.json' This gets the policy set definition from the URL specified and creates a policy definition for each group in the policy set, then creates a policy set definition containing every policy just created. .EXAMPLE .\New-CommentPolicySet.ps1 -PolicyNamePrefix "800-53Comments" -RegulatoryComplianceSetDefinitionFile .\groups.clixml This gets the policy set definition from the file specified and creates a policy definition for each group in the policy set, then creates a policy set definition containing every policy just created. .NOTES This script is provided as is and is not supported by Microsoft. For more fun code check out https://github.com/PaulHCode/azurehelper #> #Requires -Version 7.0 #Requires -Module Az.Resources #Requires -Module Az.Accounts param( [Parameter(Mandatory = $true, ParameterSetName = 'URL')] [Parameter(Mandatory = $true, ParameterSetName = 'File')] [string]$PolicyNamePrefix = '800-53Comments', [Parameter(Mandatory = $false, ParameterSetName = 'URL')] [Parameter(Mandatory = $false, ParameterSetName = 'File')] [string]$SubscriptionId, [Parameter(Mandatory = $true, ParameterSetName = 'URL')] [ValidateScript({ (Invoke-WebRequest -Uri $_ -UseBasicParsing -Method head).StatusCode -eq 200})] [string]$RegulatoryComplianceSetDefinitionURL = 'https://raw.githubusercontent.com/Azure/azure-policy/master/built-in-policies/policySetDefinitions/Regulatory%20Compliance/NIST_SP_800-53_R4.json', [Parameter(Mandatory = $true, ParameterSetName = 'File')] [ValidateScript({ Test-Path $_ -PathType Leaf })] [string]$RegulatoryComplianceSetDefinitionFile ) If($Null -eq (Get-AzContext)){ throw "You must be logged into Azure to run this script" Exit } #$RegulatoryComplianceSetDefinitionURL = 'https://github.com/Azure/azure-policy/blob/master/built-in-policies/policySetDefinitions/Regulatory%20Compliance/NIST_SP_800-53_R4.json' If($RegulatoryComplianceSetDefinitionURL){ $RegulatoryComplianceSetDefinition = Invoke-RestMethod -Uri $RegulatoryComplianceSetDefinitionURL -UseBasicParsing $groups = $RegulatoryComplianceSetDefinition.properties.policyDefinitionGroups write-verbose "Loaded $($groups.count) groups from $RegulatoryComplianceSetDefinitionURL" }Else{ $groups = Import-Clixml $RegulatoryComplianceSetDefinitionFile write-verbose "Loaded $($groups.count) groups from $RegulatoryComplianceSetDefinitionFile" } If($SubscriptionId){ $SubscriptionsToApplyTo = [array](Get-AzSubscription -SubscriptionId $SubscriptionId -WarningAction SilentlyContinue) }else{ Write-host "Select Subscriptions to apply to. There is a pop-under window which may be hidden behind this window" $SubscriptionsToApplyTo = [array](Get-AzSubscription -WarningAction SilentlyContinue | Out-GridView -Title "Select Subscriptions to apply to" -OutputMode Multiple) } #$SubscriptionsToApplyTo = $SubscriptionsToApplyTo.SubscriptionId #$SubscriptionsToApplyTo = [array](Get-AzSubscription | Out-GridView -Title "Select Subscriptions to apply to" -OutputMode Multiple) #$groups = Import-Clixml .\groups.clixml #$PolicyNamePrefix = '800-53Comments' #$SubscriptionId = '6a63eec2-cc9d-48ac-a0b7-ac7de8a7c23f' ForEach ($sub in $SubscriptionsToApplyTo) { Write-Host "Working on $($sub.Name)" #Create Policies $count = 0 $max = $groups.Count $createdPolicies = ForEach ($group in $groups) { write-verbose "Working on $($group.Name)" Write-Progress -Activity "Creating Policies" -Status "Creating Policy $count of $max" -PercentComplete (($count / $max) * 100) -CurrentOperation "$($group.Name)" $policy = @' { "if": { "field": "type", "equals": "Microsoft.Resources/subscriptions" }, "then": { "effect": "Manual", "details": { "defaultState": "Unknown" } } } '@ $metadata = @" { "version": "1.1.0", "category": "Custom Regulatory Compliance", "additionalMetadataId": "$($group.additionalMetadataId)" } "@ $PolicyDefinitionSplat = @{ Name = "$PolicyNamePrefix-$($group.Name)" DisplayName = "$PolicyNamePrefix-$($group.Name)" Description = "$PolicyNamePrefix-$($group.Name)" Policy = $policy Mode = 'All' SubscriptionId = $($sub.Id) Metadata = $metadata } New-AzPolicyDefinition @PolicyDefinitionSplat $count++ } #build PolicySetDefinition $PolicySetDefinition = "[`n" $count = 0 $max = $createdPolicies.Count ForEach ($policy in $createdPolicies) { $PolicySetDefinition += @" { "policyDefinitionId": "/subscriptions/$SubscriptionId/providers/Microsoft.Authorization/policyDefinitions/$($policy.Name)" } "@ If ($count -lt ($max - 1)) { $PolicySetDefinition += "," } $count++ } $PolicySetDefinition += "`n]" #export PolicySetDefinition $tempFileName = ".\PolicyDefinition-$($sub.Name).json" $PolicySetDefinition | Out-File $tempFileName -Force #Create PolicySetDefinition New-AzPolicySetDefinition -Name $PolicyNamePrefix -DisplayName $PolicyNamePrefix -Description $PolicyNamePrefix -PolicyDefinition $tempFileName -SubscriptionId $sub.Id Remove-Item $tempFileName -Force } #cleanup - works probably, but commented out for safety #Get-AzPolicySetDefinition | Where-Object { $_.Properties.DisplayName -like "$PolicyNamePrefix*" } | Remove-AzPolicySetDefinition -Force #Get-AzPolicyDefinition | Where-Object { $_.Properties.DisplayName -like "$PolicyNamePrefix*" } | Remove-AzPolicyDefinition -Force |