[LZ 7] Where the Tree Starts Saying No

The management-group tree has organized, scoped, and inherited, but it has not yet refused anything. Policy is the enforcement layer: audit before deny, mandatory tags and inheritance, exemptions as designed carve-outs, and the tree finally saying no.


The management-group tree has been waiting to do one thing since the first article, and it still has not done it. It has organized subscriptions, carried inheritance, and given identity somewhere to land, but it has not yet said no to anything. Policy is where that changes. This article is about the enforcement layer, the small set of rules assigned to the tree that decide what may be created and what may not, and about the one discipline that keeps enforcement from becoming an outage. You watch before you block, every time, and the difference between a governance rollout and an incident is whether you remembered that.


Assessment is not enforcement

The last article already gave the estate a sense of whether it is configured well. Defender for Cloud assesses every subscription against the Microsoft Cloud Security Benchmark, by default, and hands you a score and a list of what is wrong. That is assessment, and it is genuinely useful, but it stops nothing. A resource created without encryption, a storage account open to the internet, a resource group with no owner tag, all of them are assessed, scored, and created anyway. Policy is the layer that refuses. The benchmark tells you the door is unlocked; policy is what locks it. Keep the two straight, and in particular do not re-assign the benchmark as a policy initiative on the management group, because Defender already assigns it at the subscription for you, and a second copy at a higher scope buys nothing but confusion. The work in this article is the smaller, sharper set of rules that actually block and fix.

The practitioner’s middle ground

There are two ways to get policy wrong at this scale and they fail in opposite directions. One is to deploy the full enterprise Azure Landing Zone policy library, hundreds of definitions, onto an estate with a single subscription and three administrators, where you will spend more time granting exemptions than running workloads and the guardrails become noise nobody reads. The other is to decide that Defender’s assessment is enough and add nothing, which leaves the estate measured but unguarded, scored against a benchmark it is free to violate. The correct answer for an organization this size sits between them: the benchmark for assessment, which is already running, plus a deliberate and small layer of governance and operational policies that enforce the handful of things that actually cause incidents. Not everything. The things that matter, chosen on purpose.

It helps to name the effects, because the policy set becomes legible once you see it as verbs rather than a list. Audit reports a violation and never blocks. Deny refuses the request outright. Modify changes a property on the way in, adding a missing tag or flipping a setting to its secure value as the resource is created. Deploy-if-not-exists provisions something that should be there and is not, a diagnostic setting or a backup configuration. Those last two act on the world rather than merely judging it, which is why each carries a managed identity and needs a remediation pass to reach the resources that already exist. That is a design fact to plan for, not a detail to discover during a rollout.

Audit before deny, always

This is the discipline the whole article is built around, so I will state it plainly. A deny policy changes what your estate will accept, and in a brownfield estate it can block legitimate work the instant it turns on. So an enforcing policy never starts by enforcing. It starts by watching. Azure Policy gives you two distinct ways to watch, and knowing the difference matters: an audit-effect policy reports non-compliance and by its nature never blocks, while a deny policy assigned in do-not-enforce mode is fully evaluated and reported but has its block deliberately withheld. The second is how you trial an actual deny safely. You assign it not enforcing, you let it evaluate, you run a compliance scan to see exactly which resources it would have refused, and only once that result is clean or understood do you promote it to enforcing. That promotion is a decision with evidence behind it, not a hope.

In greenfield you can deny from day one, because there is nothing yet to break. In brownfield, denying before you have watched is the single most reliable way to turn a governance project into an outage with your name on it.

Expect a compliance flood the first time the tree evaluates an existing subscription, and prepare the customer for it before it happens. Dozens or hundreds of resources will report non-compliant at once, and that is not the foundation breaking. It is the foundation doing exactly its job, surfacing every place the estate drifted before anyone was watching. The flood is a worklist, not an alarm. You triage it, you remediate what matters, you exempt what is legitimate, and you promote policies to deny one at a time as each becomes clean. The brownfield rule from the governance article applies here in full: nothing moves to deny until you have proven, with the do-not-enforce trial, that it will not block work that should be allowed.

Watch before you block: the path from audit to deny 1. Assign, not enforcing Audit, or Deny in do-not-enforce mode 2. Observe and scan See the compliance flood, learn what would be blocked 3. Promote to Deny Enforce, with evidence that it will not break work The effects, as verbs Auditreports a violation,never blocks Denyrefuses the requestoutright Modifychanges a propertyon the way in (identity) Deploy-if-not-existsprovisions what ismissing (identity) When a policy blocks something legitimate, exempt it, never disable it Waiver Temporary. Carries a removal trigger or expiry. For the exception you intend to resolve. Mitigated Permanent, with a documented compensating control. The gateway subnet that cannot carry an NSG.

Tags are the enforcement that pays for itself

The six mandatory tags from the naming and tagging decisions become real here, and they are the clearest example of why enforcement needs more than one effect. A deny policy on resource groups refuses any group created without the required tag keys, which stops the problem at the door where a human is making a deliberate choice. But a resource does not inherit its resource group’s tags on its own; that is simply not how Azure works, and it surprises people every time. So a second policy, using the modify effect, inherits each tag from the resource group down onto the resources inside it, running under a managed identity and reaching existing resources through a remediation pass. Deny the missing key where the group is created, modify the inheritance down to everything within it. Auditing this and stopping there is the common half-measure, and it is nearly worthless, because the entire value of mandatory tags is that every resource actually carries Owner and Contact and CostCenter without anyone typing them, which is exactly what the operating article will lean on when it turns tags into a cost model.

Where a policy blocks, an exemption is the designed answer

Exemptions are not admissions that a policy is wrong. They are how a correct policy accommodates a legitimate exception without being switched off for everyone. The distinction between the two kinds is the whole discipline. A waiver is temporary and carries a removal trigger, for the exception you fully intend to resolve, the vendor virtual machine on an off-list size while you document it, the management port left open for a forty-eight hour migration. A mitigated exemption is permanent and documents the compensating control that makes the exception safe, for the exception that is simply correct forever. The canonical case is the gateway subnet, which the Azure platform forbids from carrying a network security group at all, so the policy that requires an NSG on every subnet exempts that one subnet as a mitigated exemption, with the platform requirement written down as the reason. Exempt at the narrowest scope that solves the problem, a single resource or resource group rather than the subscription, because the policy still has to govern everything else. And treat every exemption as technical debt with a name, an owner, and a review date, not as a quiet way to make a finding disappear.

Where the assignments live, and protecting the tree itself

Assign each policy at the scope whose reach you actually intend. The governance and operational policies, the tags and the locations and the storage and key-vault protections, belong at the top of your custom hierarchy, assigned once so that inheritance carries them to every subscription beneath rather than repeating the assignment per subscription. The workload-specific rules, the ones that only make sense where business workloads run, belong lower, on the landing-zones branch. This is the same inheritance you designed the tree around, now doing the job it was shaped for, and it is why the tree mattered in the first place. A policy assigned at the right height governs everything below it and nothing above, which is precisely the control the whole structure was built to give you.

There is one newer capability worth adopting deliberately, because it closes a gap the rest of this design leaves open. Every effect discussed so far governs creation. But the most damaging thing that happens to a foundation is usually not a bad resource being made, it is a critical resource being destroyed, the hub network or the central log workspace or a key data store deleted by an errant script or a compromised account. The deny-action effect blocks deletion, not just creation, so you can make the resources the whole estate depends on genuinely undeletable through ordinary means, while the platform keeps the safeguards that stop such a policy from ever locking you out of your own subscription. A tree that can refuse a bad creation should also be able to refuse a catastrophic deletion, and now it can.

Building this is a careful, ordered sequence rather than a big-bang deployment: the tag and location policies assigned in audit, promoted to deny only after a clean scan, the tag inheritance wired with its remediation, the gateway subnet exempted with its reason recorded, and a resource proven to be blocked when it violates the rules and accepted when it complies. The build sheet does exactly that. After it, the series turns to the last thing a foundation has to do, which is not to be built but to be operated and grown, and that is where the tags you just made mandatory finally start paying you back.


Azure Landing Zones
‹ Previous: [LZ 6.1] Standing Up Posture and the Central Record
Next: [LZ 7.1] Standing Up the Policy Guardrails