How to – Azure Policy via ARM Template

If you’ve worked with Azure for a while, you would know that one of the most efficient methods of deployment is ARM templates and one of the most powerful services is Azure Policy. What you might not know, is that you can combine the two for efficient, iterative and defined deployments.

A great point I saw recently on Twitter was that a lot of technical posts highlight features and how to use them but rarely go into why you should use them. Conscious of that, here are a couple of points on why I think you should make use of Policy via Template (PvT):

  • Quick deployment time – hilariously quick.
  • Repeatable defined structures – the exact policy definition, applied to the exact scope, with no possibility of user error.
  • Confident flexibility – Templates are idempotent; need to update the definition? Update the template, deploy the update, job done.

So if the “why” makes sense to you, let’s move onto the “how”. If it doesn’t, let me know! I’d love to hear your horror stories/use cases…

Templates can be deployed in several ways, for the sake of simplicity, I’m going to use two tools here. Visual Studio Code and Powershell. Currently you can only deploy subscription scope resources via Powershell or CLI.

There are some other differences to note. The schema for the template must be:

When deploying the template, it must be deployed to a location and given a name (the name of the template will be used if none is specified), that combination is then immutable for that location. So if you need to change location, you need to use a new name etc.

Now, let’s create our template. For this post, I am going to use an existing Template Definition and scope it to my Subscription. While you can pass the Template Parameters via Powershell Variable, for this post I am going to define them as a Template Variable. This is tricky piece of logic as they must be defined as a nested, object array. I also define the policyID via Variable. For existing definitions, you can get this via the Portal, or Powershell command

Get-AzPolicyDefinition | select PolicyDefinitionId -ExpandProperty properties | where displayName -Match "allowed locations"
    "$schema": "",
    "contentVersion": "",
    "parameters": {},
    "variables": {
      "policyName":"Allowed Locations",
    "resources": [
            "type": "Microsoft.Authorization/policyAssignments",
            "name": "[variables('policyName')]",
            "apiVersion": "2018-03-01",
            "properties": {
                "scope": "[subscription().id]",
                "policyDefinitionId": "[variables('policyDefinitionID')]",
                "parameters": "[variables('policyParameters')]"

Now are Policy deployment is defined and ready for use, we deploy using Powershell:

New-AzDeployment -Name "pvtDeployment" -Location northeurope -TemplateFile 'C:\Users\username\Documents\WDA\PvT.json'

You should receive a succeeded message within your shell and you can verify via the Portal. As it was a subscription level deployment, head to your Subscription blade and check the Deployments tab. You should see the Template listed as the same name as you ran for the deployment.

You can then confirm your settings via heading to Azure Policy and the Assignments blade. You will see your Policy Definition assigned at the scope you set, using the Parameters you set.

Just to go back to an early point on why you’d use this option. Look at the duration of the deployment in the above screengrab – 1 second. You simply cannot beat that!

This can obviously be used for much more complex deployments, for example, defining your own policy inline and deploying via template. The possibilities are endless with one current exception; Subscription is highest scope you can currently use, hopefully Management Groups are on the roadmap and therefore the scaling capability is excellent.

As always, if there are any questions or suggestions, please get in touch!