In my previous blog post, I explored the topic of defining Azure Policies and their assignments in ARM templates, so instead of maintaining lots of separate files for policy definitions you can put all policy defining artifacts in an ARM template and deploy it in a pipeline along with other parts of your Azure infrastructure. However, in some cases, it might be more convenient to group the policies targeting a specific area of your Azure governance model and assign them to a subscription in bulk. So, here, Azure Policy initiatives come to help.
You can think about Azure Policy initiatives just as about collections of policy definitions, which allow you to assign all the policies in a collection in a single strike.
Note: At the time of writing this, the same limitations apply for working with policy initiatives as for single policy definitions – it is not possible to use ARM templates to deploy resources on a Management Group level. Use Azure PowerShell or Azure CLI options for that.
How to define Azure Policy initiatives in ARM templates
As with policy definitions, there is even less information or descriptive examples of defining policy initiatives in ARM templates. You can get more or less relevant information on that only from sample responses to Azure REST API requests. According to these examples, you can use the same approach when describing initiative definitions in the ARM template as for single policies, but with a few differences.
Firstly, the structure of the ARM template remains the same: you use the same schema reference for subscription-level deployments and the same high-level blocks – parameters, variables, resources, etc.
Secondly, as initiatives are sets of policies, you should use ‘Microsoft.Authorization/policySetDefinitions’ resource type to define your initiative.
Thirdly, when describing initiatives itself, you don’t define policies in them but rather reference existing ones. Of course, you can put both policy and initiative definitions in a single ARM template, but to deploy it correctly, you should specify dependencies, so policies referenced in the initiatives are deployed first.
So, a sample initiative definition might look like in the following example:
How to create assignments for Azure Policy initiatives from ARM templates
As well as for individual Azure Policies, you can define assignments for initiatives in ARM templates too. There is no separate resource type for initiative assignments, so you should use the already familiar ‘Microsoft.Authorization/policyAssignments’ type. The only difference is that to assign an initiative to a target scope, you should reference ‘Microsoft.Authorization/policySetDefinitions’ in the ‘policyDefinitionId’ property.
Also, if you are planning to assign policy initiatives not only to the subscription level but for individual resource groups too, you should use the regular deployment schema in your ARM template and deploy it using resource group deployment cmdlets.
Here is a sample fragment of ARM template for policy initiative assignment:
Azure policy parameters as object type when assigning an initiative
As you might already know from my previous post, if an Azure Policy takes input parameters, you should provide them as an object type during the assignment. Because the deployment order looks like the following:
Parameter file for an ARM template -> an ARM template with an Initiative assignment -> an Initiative definition -> (policy parameters as an object) -> a Policy definition
Policy parameters must be defined as objects in initiative definitions and also be passed as objects during initiative assignments. To achieve that, you should pack the parameter objects into another (parent) object in the parameter file, so the parameter file has the following structure:
It took me some trials and errors to figure out that nuance as error messages just tell you about some JSON parsing or referencing issues without any hints about processing parameter values.
I hope you will find this information helpful on your journey through Azure services, so give it a like and share it with your colleagues!
P.S. You can find all code samples from this post in the following repository on GitHub.