Use Azure Policy to ensure your Azure administrators deploy resources that meet your corporate governance requirements.
Latest posts by Timothy Warner (see all)

In my cloud consulting practice, many of my clients asked how they could ensure that their colleagues deployed resources in Microsoft Azure according to their established governance policies. With the introduction of Azure Policy (formerly called Azure Resource Manager [ARM] Policy), they now can take that kind of control.

Understand Azure Policy

The first thing you should know is that Azure Policy is not the same thing as role-based access control (RBAC) in Azure. RBAC controls which actions Azure users can take at different scopes. For instance, Azure administrators associated with the VM Contributor role at the resource group level can create and manage VMs within that resource group but take no action on VMs in other resource groups.

By contrast, Azure Policy focuses on auditing and potentially blocking deployment or configuration options on Azure resources. For example, you may need to limit the Azure regions in which someone can deploy Azure resources.

Examine a built-in policy

Log into the Azure portal with Owner permissions on your subscription and browse to the Policy resource blade. In the Settings list, click Authoring > Definitions. Here we see the list of built-in Azure Policy definitions. These will give you a good idea of what options are available out of the box. Use the filter control to view only the policy definitions that interest you. Here's a screen capture of the Azure portal:

Browsing built in Azure Policy definitions

Browsing built in Azure Policy definitions

Let's drill into a policy definition. Click the Allowed locations built-in policy. As you might expect, Azure Policy definitions are written in JavaScript Object Notation (JSON). Their schema is quite intuitive and easy to understand if you have basic PowerShell scripting knowledge. Take a look at the following screenshot, and I will walk you through precisely how the Allowed locations policy works, line by line:

Underlying policy structure

  • 2: The if element functions like the if statement in PowerShell; it's a conditional expression.
  • 3: The allOf element specifies inclusion of all the enclosed rules in the definition. It's the functional equivalent of the AND operator. The other supported logical operators are not and anyOf.
  • 5-6: This template includes an array parameter called listOfAllowedLocations that you specify at policy runtime.
  • 9-10 and 13-14: These are additional requirements we will ignore in today's tutorial. I want to focus only on allowed Azure regions for resource deployment.
  • 18-19: Here's the policy effect. Besides Deny, there is also Audit, Append, AuditIfNotExists, and DeployIfNotExists.

If you're thinking to yourself, "Wow, these Azure Policy templates work practically the same way as ARM deployment templates do," I give you hearty congratulations and a clap on the back because you are correct! If you already work with ARM templates, working with Azure Policy templates will be easy for you.

Assign the policy

In the Policy blade Settings list, navigate to Authoring > Assignments. Notice that you can assign policies and initiatives. An initiative is simply a container that holds one or more policies. Initiatives are useful when you have more complex governance needs that require the orchestration of multiple policies.

For our simple example, click Assign policy to open its resource blade. You can scope an Azure Policy at the following levels:

  • Subscription
  • Resource Group
  • Management Group

If you aren't familiar with management groups, please read the 4sysops tutorial I put together on the subject. Essentially a management group is a container object that holds one or more Azure subscriptions.

Let me show you a screenshot of my configuration, and I'll describe each relevant field:

Assigning a policy to an Azure subscription

Assigning a policy to an Azure subscription

  • Scope: Subscription, resource group, or management group
  • Exclusions: Exempt particular resources from the policy assignment
  • Policy definition: Here's where we choose the Allowed locations built-in policy
  • Allowed locations: This is the previously described parameter; the drop-down list box control makes it easy to select Azure regions

You can now see a populated compliance dashboard on the Overview setting in the Policy resource blade. Let's test!

Test policy enforcement

Let's try to deploy a storage account to an Azure region not included in our policy parameter array. In my lab, I tried to create a storage account in the South Central US Azure region.

As you can see in the following composite screenshot, the deployment failed at the validation stage.

Azure Policy enforcement results

Azure Policy enforcement results

What's cool here is that the deployment failed even though I am logged into the Azure portal as a subscription Owner. The bottom line is that Azure will enforce your policy at the given scope no matter what, excluding any resource exceptions you include in your policy assignment.

Define a custom policy

Let's wind down by editing that Allowed locations policy such that it audits compliance violations but allows the deployments to complete.

First, go back to the Authoring > Assignments blade and delete the current Allowed locations assignment by opening the entry's ellipsis (…) menu and clicking Delete assignment.

Second, load the Allowed locations built-in policy again, but this time click Duplicate definition from the resource blade's toolbar. Here are some of the form properties you need to complete:

  • Definition location: Store (not associate) the new definition to a subscription or management group
  • Category: Create a custom category to store your policy definitions
  • Policy rule: This field is fully editable

Take a look at how I refactored the Allowed locations policy in my subscription:

  "mode": "all",
  "policyRule": {
    "if": {
      "allOf": [
          "field": "location",
          "notIn": "[parameters('listOfAllowedLocations')]"
    "then": {
      "effect": "Audit"
  "parameters": {
    "listOfAllowedLocations": {
      "type": "Array",
      "metadata": {
        "displayName": "Allowed locations",
        "description": "The list of locations that can be specified when deploying resources.",
        "strongType": "location"

Notice that we see the underlying parameter definition now that we have the full source code of the Allowed locations built-in policy.

Next, go ahead and associate your new custom policy and redeploy the storage account we used earlier. The deployment should succeed, and you can read the audit log details in the Policy resource blade.

If your compliance statistics fail to update, you may need to re-register the Microsoft.PolicyInsights resource provider.

Re registering the Microsoft.PolicyInsights resource provider

Re registering the Microsoft.PolicyInsights resource provider


There you have it! You can find several more good policy ideas by visiting the Azure team's GitHub repository. I will leave you with some useful documentation links to help you take your newfound Azure Policy skills to the next level. Take care!

Subscribe to 4sysops newsletter!


Leave a reply

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2023


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account