[AP 13] The Decision: What Policy Owns, and What It Should Not

Policy against RBAC, locks, deny assignments, Defender for Cloud and machine configuration. Which control answers which question, and the restraint that keeps an assignment count manageable.


The failure mode of a governance team that has learned Azure Policy properly is that everything starts to look like a policy problem. Some of the most expensive assignments I have unwound were technically correct and answering a question that belonged to something else.

Five controls, five questions

Azure gives you several mechanisms that all feel like guardrails, and choosing between them is easier once you notice they answer different questions.

ControlThe question it answersReach for it when
Azure RBACMay this principal perform this operation here?The answer depends on who is asking, and the boundary is a person or a team rather than a configuration.
Azure PolicyIs this resulting state acceptable, whoever produced it?The rule should hold regardless of who deploys, including you, including the pipeline, including next year’s team.
Resource locksShould this specific object resist deletion or change?You want a deliberate, visible, per-object obstacle that an owner can remove knowingly. Locks are a speed bump with a name on it.
Deny assignmentsShould this principal be blocked from an action even though their role permits it?Mostly you do not reach for this directly. It arrives with managed platforms and it is the mechanism underneath several of them.
Defender for CloudDoes this estate meet a published security standard?The question is framed by a framework somebody else wrote, and the audience is a security or audit function.

The pairing that causes most confusion is Policy and locks, because both stop a deletion. A lock is attached to an object, visible on that object, and removable by whoever owns it, which makes it a good fit for the resource somebody has decided is precious. A denyAction policy is attached to a rule, applies to every matching resource in scope including ones created tomorrow, and is removable only by whoever holds policy write. Locks express care about a thing. Policy expresses a standard about a class of things.


What Policy is genuinely bad at

Three categories, and recognising them early saves months.

Anything inside the operating system. Azure Policy governs the Azure Resource Manager view of a machine and stops at the boundary of the guest. What is running inside is machine configuration, which is a different mechanism with different limits and, on Arc-connected servers, a real per-server bill. The Arc series on this site owns that subject, and the reason this series does not re-derive it is that the two surfaces are related by branding more than by behaviour.

Protecting your own governance. A denyAction policy cannot protect policy assignments, deny assignments, deployment stacks, subscriptions or locks, all of which are deliberately exempt so that a tenant cannot be made unrecoverable. So Azure Policy cannot stop somebody deleting Azure Policy. That is RBAC’s job, which is the point of removing policy write from everyone except a deployment pipeline, and it is why the policy as code article treats that permission change as the load-bearing step rather than the automation.

Anything needing a judgement. If a rule needs to know whether an exception is reasonable, whether a workload is production, or whether a team has done their design review, you are describing a process with a policy-shaped hole in it. The manual effect exists precisely because Microsoft accepted this, and an attestation is an honest way of recording that a human decided. Building an elaborate rule to infer intent from tags is how you get a control that fails whenever somebody types a tag value in a different case.


The restraint that keeps an estate legible

Microsoft’s own guidance carries a recommendation that reads like an aside and is the most useful sentence in it: limit the number of assignments at the root management group, to avoid managing exclusions at every inherited scope below. Every assignment placed at the top is a commitment to handle every exception underneath it, forever, and exceptions are where policy estates go to die.

Every rule at the root is a promise to manage every exception beneath it. Assign the rules you would defend in an outage, and put the rest one level down.

The rest of the discipline follows from the same instinct. Define high and assign lower, so a rule can move without being copied. Prefer built-ins, because somebody else maintains them and the version machinery lets you meet their changes deliberately. Assign initiatives rather than definitions so the count of objects grows more slowly than the count of controls. And accept that an estate with forty well-understood assignments governs better than one with four hundred that nobody can explain, because the second one gets exceptions rather than fixes.


The proportion that tells you how a programme is going

There is a single number I look for when reviewing a policy estate, and it is not the compliance percentage. It is the ratio of built-in definitions to custom ones.

A healthy estate is mostly Microsoft’s definitions, parameterised to the organisation’s values, grouped into initiatives the organisation authored and named. The custom definitions are few, each one traceable to a driver somebody can state, each carrying provenance if it was forked and an owner if it was written. That estate is cheap to run because most of its maintenance belongs to somebody else, and it stays current without anybody doing anything.

An estate with a large custom population is almost never one that found the catalogue insufficient. It is one that never read the catalogue, and every one of those definitions is a standing liability with no maintainer, no version, and no notification when the resource provider underneath it changes. The fix is unglamorous and it is the same every time: work out which of them a built-in now covers, run both in audit until they agree, and retire yours.


Where I would start, on a real estate

If you inherited an Azure estate tomorrow and had a week for this, the order that has repeatedly worked is not the order of this series. Export everything first, because you cannot govern what you cannot enumerate, and the export usually finds duplicate definitions and forgotten assignments before it finds anything else. Then read the exemptions and the excluded scopes, since that is where the estate keeps its real posture rather than its intended one. Then look at every assignment carrying a managed identity, and check what that identity was granted and where, because that is the largest standing privilege in the estate and the least reviewed. Then count the custom definitions and ask, for each, what the driver was.

Only after that would I write a rule. And the first thing I would write is not a control at all, it is the report: exemptions with their categories, owners and expiry dates, delivered on a schedule to the people who granted them.


The thing worth carrying

Azure Policy is the only place in an Azure estate where an organisation’s intent is written down in a form the platform will enforce without being asked, against everyone equally, including the people who wrote it. That is unusual and it is worth more than the compliance percentage it produces. It also means the rules you assign outlive your involvement, get inherited by people who never met you, and are read by teams trying to work out why they cannot deploy.

Write them for those people. Name the control in the display name, put the owner and the route in the non-compliance message, date every exemption, and keep the whole thing somewhere a pull request can explain why. The estate will change hands. The assignments will still be running.


Azure Policy
‹ Previous: [AP 12.1] Build Sheet: Policy in a Repository, Deployed by Pipeline