Back to blog
AzureBest PracticesCloud SecurityCost OptimizationOperations & Compliance

No Allowed Locations Policy: Lock Down Azure Deployment Regions

Learn why a missing Azure allowed-locations policy risks compliance, cost, and security, plus step-by-step CLI, Bicep, and Terraform fixes to lock down regions.

TL;DR

This check flags Azure subscriptions that lack an allowed-locations policy, which means resources can be deployed to any region. Assign the built-in "Allowed locations" Azure Policy to lock deployments to approved regions and keep data residency, cost, and compliance under control.

When you hand a team access to an Azure subscription, you are also handing them the ability to spin up resources in any of the 60-plus regions Azure offers. Without a guardrail, nothing stops an engineer in your London team from deploying a database in Australia East, or a contractor from standing up VMs in a region you have never audited. The No Allowed Locations Policy check catches exactly this gap: a subscription with no allowed-locations policy assignment in place.


What this check detects

Lensix inspects the policy assignments on your Azure subscription and looks for an assignment of the built-in Allowed locations policy (or an equivalent custom policy that restricts deployment regions). If none is found, the check fails.

The relevant built-in policy definition is:

  • Allowed locations — definition ID e56962a6-4747-49cd-b67b-bf8b01975c4c. It restricts the regions where resources can be created.
  • Allowed locations for resource groups — definition ID e765b5de-1225-4ba3-bd56-1ac6695af988. It restricts where resource groups themselves can be created.

The check is specifically about whether any region restriction exists. A subscription with no such assignment leaves region selection entirely to whoever is deploying.

Note: Azure Policy assignments can live at the management group, subscription, or resource group scope. A policy assigned at a parent management group is inherited by all child subscriptions, so you do not need to assign it on every subscription individually.


Why it matters

"Resources can go anywhere" sounds harmless until you trace the consequences. Region sprawl touches compliance, cost, and security all at once.

Data residency and compliance

Regulations like GDPR, HIPAA, and various national data-sovereignty laws often require that customer data stays within specific geographic boundaries. If a developer accidentally provisions a storage account or SQL database in a region outside your approved boundary, you may be in breach without realizing it. Proving compliance to an auditor is far harder when your inventory is scattered across regions nobody signed off on.

Cost surprises

Azure prices vary by region. A VM size that is cheap in East US can cost noticeably more elsewhere, and egress charges between regions add up fast. Uncontrolled region selection makes cost forecasting unreliable and creates billing line items that are tedious to chase down.

Security blind spots

Every region you operate in is a region you have to monitor. If your logging, threat detection, and network controls are tuned for two regions but resources show up in a third, that third region becomes a quiet corner where misconfigurations and malicious activity go unnoticed. Attackers who compromise a set of credentials sometimes deploy resources in unusual regions precisely because defenders are not watching there, whether for cryptomining or staging exfiltration infrastructure.

Warning: Region sprawl is sticky. Once stateful resources like databases and storage accounts exist in an unapproved region, moving them is a migration project, not a config change. The cheapest time to enforce locations is before the first resource is deployed.


How to fix it

The fix is to assign the built-in Allowed locations policy to the subscription (or, better, to a management group above it) with your approved list of regions.

Option 1: Azure CLI

First, find the policy definition ID and confirm your subscription:

# Confirm the built-in definition exists
az policy definition show \
  --name "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
  --query "{name:displayName, id:id}" -o table

Then create the assignment, passing the regions you want to allow as the listOfAllowedLocations parameter:

az policy assignment create \
  --name "allowed-locations" \
  --display-name "Allowed locations - EU regions only" \
  --scope "/subscriptions/<SUBSCRIPTION_ID>" \
  --policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
  --params '{
    "listOfAllowedLocations": {
      "value": ["westeurope", "northeurope"]
    }
  }'

To scope it at a management group instead (recommended for fleets of subscriptions):

az policy assignment create \
  --name "allowed-locations" \
  --display-name "Allowed locations - EU regions only" \
  --scope "/providers/Microsoft.Management/managementGroups/<MG_NAME>" \
  --policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
  --params '{
    "listOfAllowedLocations": {
      "value": ["westeurope", "northeurope"]
    }
  }'

Note: The built-in policy intentionally exempts resources whose location is global (such as Azure DNS zones, Traffic Manager, and some identity resources). You do not need to add a special case for those, the policy handles them.

Option 2: Azure Portal

  1. Go to Policy in the Azure Portal.
  2. Select Assignments, then Assign policy.
  3. Set the Scope to your subscription or management group.
  4. Under Policy definition, search for and select Allowed locations.
  5. On the Parameters tab, pick the regions you want to permit.
  6. Review and select Create.

Option 3: Infrastructure as code (Bicep)

targetScope = 'subscription'

resource allowedLocations 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
  name: 'allowed-locations'
  properties: {
    displayName: 'Allowed locations - EU regions only'
    policyDefinitionId: '/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c'
    parameters: {
      listOfAllowedLocations: {
        value: [
          'westeurope'
          'northeurope'
        ]
      }
    }
  }
}

Option 3 (alternative): Terraform

resource "azurerm_subscription_policy_assignment" "allowed_locations" {
  name                 = "allowed-locations"
  display_name         = "Allowed locations - EU regions only"
  subscription_id      = "/subscriptions/${var.subscription_id}"
  policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c"

  parameters = jsonencode({
    listOfAllowedLocations = {
      value = ["westeurope", "northeurope"]
    }
  })
}

Warning: The default effect of the Allowed locations policy is Deny. New deployments to disallowed regions will fail outright after you assign it. Check your existing resources first (see below) so you understand what is already running outside your intended list before you flip the switch.

Find existing resources outside your approved regions

Run this before assigning the policy so you are not blindsided by existing workloads:

az resource list \
  --query "[?location!='westeurope' && location!='northeurope' && location!='global'].{name:name, type:type, location:location}" \
  -o table

Tip: Existing resources in disallowed regions are not deleted by the policy, they are only flagged as non-compliant and blocked from new creation. Use that compliance report as a migration backlog rather than panicking about an outage.


How to prevent it from happening again

Assigning the policy once fixes today. Keeping it assigned across every new subscription is where policy-as-code earns its place.

Enforce at the management group root

Assign the allowed-locations policy at your top-level (or a tier-1) management group. Every subscription created under it inherits the restriction automatically, including subscriptions that do not exist yet. This is the single highest-leverage move.

Use Azure Policy initiatives

Bundle allowed locations with related guardrails into an initiative (policy set) so they deploy as a unit. The Azure Security Benchmark and CIS Microsoft Azure Foundations built-in initiatives both include location controls, so you can adopt a recognized baseline rather than maintaining your own list of assignments.

Gate it in CI/CD

If you manage policy through IaC, run a check in your pipeline that fails when the allowed-locations assignment is missing or its region list drifts. A simple gate using the CLI:

# Fail the pipeline if no allowed-locations assignment exists on the subscription
assignment=$(az policy assignment list \
  --scope "/subscriptions/${SUBSCRIPTION_ID}" \
  --query "[?policyDefinitionId && contains(policyDefinitionId, 'e56962a6-4747-49cd-b67b-bf8b01975c4c')] | length(@)")

if [ "$assignment" -eq 0 ]; then
  echo "ERROR: No allowed-locations policy assignment found."
  exit 1
fi

Tip: Pair this with Lensix continuous monitoring so drift is caught even when changes happen outside your pipeline, like a manual portal edit or a deleted assignment. Policy-as-code prevents bad deploys; continuous scanning catches everything else.


Best practices

  • Keep the allowed list short and deliberate. Start with the one or two regions you actually operate in. You can always add more, but a broad list defeats the purpose.
  • Assign at management group scope, not per subscription. Inheritance keeps coverage consistent and removes the per-subscription toil that leads to gaps in the first place.
  • Also restrict resource group locations. Use the companion policy e765b5de-1225-4ba3-bd56-1ac6695af988 so resource groups themselves cannot be created in stray regions.
  • Account for paired regions. If you use geo-redundant storage or region-paired disaster recovery, make sure the paired region is in your allowed list, otherwise replication targets may break.
  • Review periodically. Business expansion into new markets is a legitimate reason to add regions. Treat the allowed list as a living document tied to a change-controlled approval, not a set-and-forget config.
  • Document the why. Put your data-residency rationale in the assignment description so the next engineer understands the boundary instead of widening it to unblock a deploy.

An allowed-locations policy is one of the cheapest, lowest-friction guardrails in Azure. It takes minutes to assign, it almost never breaks legitimate workflows when scoped sensibly, and it closes off an entire class of compliance and security problems before they start. If this check is failing on your subscription, it is worth fixing today.