6 May 2026

Your Azure Policy belongs in code, not the portal

By a senior cloud engineer with deep financial services experience: Claranet recommends Azure Policy as code for auditability in regulated cloud.

In a regulated industry, your controls are only as strong as the evidence that they actually work. Azure Policy gives you the controls. Infrastructure as Code gives you the evidence.

If you're running Azure in insurance, financial services, or any sector with a serious compliance burden, that distinction is the whole game.

A quick word on Azure Policy

Azure Policy is your safety net. It lets you define exactly how resources should be configured, and enforces it. Want to restrict deployments to UK regions for data sovereignty? Mandate tags on every resource? Block public IPs on databases? Policy handles it.

You have three modes to work with:

  • Audit. Watch and alert. Resources still deploy, but non-compliance is recorded.
  • Deny. Block the action outright. The resource never gets created in the first place.
  • Modify or DeployIfNotExists. Let the action through, then remediate. Apply the missing tag, configure the diagnostic setting, automatically.

Microsoft documents these as Azure Policy effects, with specific guidance for modify and DeployIfNotExists.

Most teams start in audit, clean up the worst offenders, then flip to deny. The problem isn't the policies themselves, it is how you manage them at scale.

Three ways to do this, and only one that scales

Option A: Custom policies, hand-written

You sit down and write your own policy definitions from scratch. In our experience, teams usually do this because the sheer volume of built-in policies feels intimidating, not because they have genuinely unique requirements. You end up reinventing controls that Microsoft already maintains for you.

Option B: Built-in initiatives, applied through the portal

Azure ships with built-in initiatives, curated bundles mapped to specific frameworks. Microsoft defines an Azure Policy initiative as a way to group related policy definitions so they can be assigned and managed as a single item. CIS, PCI DSS, UK NHS, UK OFFICIAL, NIST SP 800-53. The NIST Rev. 5 initiative alone bundles hundreds of definitions, each with configurable parameters. Right controls, but no audit trail.

Option C: Built-in initiatives, applied through Infrastructure as Code

You reference Azure's built-in initiatives in Terraform or Bicep and split your code logically: definitions, initiatives and assignments each in their own place. Every change goes through Git. Every change needs a pull request. Every pull request needs another pair of eyes. Now your governance has governance.

This is the same principle we apply when designing and operating governed cloud services and Microsoft Azure managed cloud environments: the control is only useful if it is repeatable, reviewable and evidenced.

The catch with the portal

Anyone with the right RBAC role can click in, add an exception, and quietly punch a hole through your compliance posture. No version history. No pull request. No four-eyes review. No rollback.

It's a bit like having 100 firewall rules and then someone adds "allow all from all" at the top. The other 99 don't matter anymore.

Option C makes that move impossible. Every change to a policy assignment is a pull request, visible, attributed and reviewed:

Pull Request Github

Figure 1. A change to a policy template in source control. Reviewers from the platform team are auto-assigned by CODEOWNERS. The merge button is blocked until at least one approves. There is no equivalent in the portal.

What "in code" actually looks like

The shape is simple. Definitions, initiatives, assignments and exemptions each live in their own folder. Terraform references the built-in initiative by GUID, then attaches it to a management group with parameters. That is the whole pattern.

policy/
├── definitions/
│   └── tags/
│
├── initiatives/
│   ├── baseline-governance/
│   ├── pci-dss/
│   └── insurance-regulatory/
│
├── assignments/
│   ├── management-groups/
│   └── subscriptions/
│
└── exemptions/
   └── legacy-workload-a/

Microsoft provides its own guidance for creating an Azure Policy assignment with Terraform, and documents the structure of policy assignments and policy exemptions. That matters because the same governance model should apply to exceptions as much as to the controls themselves.

Here is a real assignment. It references a Microsoft-maintained initiative by GUID and attaches it to a management group:

# Reference the built-in initiative by name (the GUID)
data "azurerm_policy_set_definition" "uk_official" {
 name = "3937f550-eedd-4639-9c5e-294358be442e"
}

# Target management group (adjust to your CAF naming)
data "azurerm_management_group" "landing_zones" {
 name = "mg-corp-landingzones"
}

resource "azurerm_management_group_policy_assignment" "uk_official" {
 name                 = "uk-official-uk-nhs-audit"
 display_name         = "UK OFFICIAL and UK NHS"
 description          = "Audits a subset of UK OFFICIAL and UK NHS controls per NCSC Cloud Security Principles."
 policy_definition_id = data.azurerm_policy_set_definition.uk_official.id
 management_group_id  = data.azurerm_management_group.landing_zones.id
 location             = "uksouth" # required because the initiative includes DeployIfNotExists/Modify policies, which need a managed identity

 identity {
   type = "SystemAssigned"
 }

 parameters = jsonencode({
   IncludeArcMachines = {
     value = "false"
   }
 })

 non_compliance_message {
   content = "Resource is not compliant with UK OFFICIAL / UK NHS audit controls. See aka.ms/ukofficial-init."
 }
}

Notice what is not there: no hand-written policy logic. The GUID points at a Microsoft-maintained initiative that is tested, versioned and updated for you. You are tailoring proven controls, not authoring them.

And because it is all Terraform in Git, every change to your governance has a name, a date, and a diff. The audit trail is just the repository history:

Commits Github

Figure 2. Built-in policy releases, dependency bumps, control updates. Each one a commit on master, signed and attributed. The auditor's question, "who changed this, when, and why?", has a one-click answer.

Commit DIFF

Figure 3. Two lines, fully accounted for. A single commit, signed off, linked to its pull request. The portal cannot show you this, because the portal is not the source of truth. The repository is.

Why this matters in a regulated environment

For an insurer, broker, or financial services firm, three things matter most:

  1. Evidence of control, end to end. FCA SYSC requires firms to maintain, and to demonstrate, appropriate systems and controls. Azure Policy is the control. IaC is the audit trail that proves the control was not tampered with. When the auditor asks "who changed this, when, and why?", you can answer in seconds rather than days.
  2. Risk reduction at the governance layer. A single careless policy exception can invalidate your entire compliance framework. With IaC, that exception either goes through review and is documented, or it gets reverted on the next pipeline run when your "known good" configuration reasserts itself. Human error has a much smaller blast radius.
  3. Speed and scale, without losing control. Insurers running CIS, Cyber Essentials and UK OFFICIAL simultaneously can be juggling close to a thousand policies. Managing that in the portal is a full-time job nobody wants. Codified, it is a folder structure. Onboarding a new subscription is one assignment change, reviewed and merged in minutes.

This is especially relevant for organisations moving regulated workloads into Azure. Claranet's managed cloud for financial services proposition is built around secure landing zones, compliance controls and operational governance across hyperscale and private cloud environments.

The pipeline is the control plane

Every release reapplies the known-good configuration. If someone bypasses review and clicks an exception into the portal, the next run quietly puts it back. Drift has a shelf life of one pipeline.

Pipeline

Figure 4. A governed pipeline run reapplying the policy estate. Three stages, each logged, each artefacted. Compliance posture is now a build artefact you can hand to an auditor.


The bottom line

Yes, this takes more set-up time than clicking through the portal. But that is time invested once.

The cost of a misconfigured cloud estate, financial, reputational and regulatory, is paid every day until it is fixed.

If you would like to see how your Azure governance would stand up under audit, talk to our Azure cloud team. We are working with insurers and financial services firms right now to design exactly this: built-in initiatives, codified in Terraform, deployed through governed pipelines, with the approval flows that hold up to regulatory scrutiny.