azure-mg-modify-policy-guardrail
Ability to write Azure Policy assignments/definitions at a management group scope lets a principal weaken or remove a deny-effect guardrail inherited by the subtree.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?mg) ==
ManagementGroup
node_class(?guardrail) == Policy
node_type(?guardrail) == OrganizationPolicy # Azure Policy assignment at MG (deny-effect)
?principal effectively holds Microsoft.Authorization/policyAssignments/write (and/or policyDefinitions/write) at ?mg (Owner or Resource Policy Contributor)
emit
| source type | Identity |
|---|---|
| target type | * |
| source | ?principal |
| target | ?guardrail |
| permissions | Microsoft.Authorization/policyAssignments/write Microsoft.Authorization/policyDefinitions/write |
| conditions | iam_permission |
| state logic | ACTIVE for the modify capability when policyAssignments/write is held at ?mg; CONDITIONAL(iam_permission) when gated. This edge is the INPUT to hierarchy-chains.yaml guardrail-removal-upgrades-blocked, which re-emits every edge THIS guardrail was suppressing (BLOCKED) at its underlying state as CONDITIONAL(guardrail_removed). Emitting CanModifyPolicy here does NOT itself upgrade any edge. |
Narrative
{principal.name} can modify the Azure Policy guardrail {guardrail.name} at management group {mg.name} (Microsoft.Authorization/policyAssignments/write), lifting the deny it imposes on the subtree.
Raw rule rules/derived/azure/mgmtgroups.yaml
id: azure-mg-modify-policy-guardrail
emits: CanModifyPolicy
description: Ability to write Azure Policy assignments/definitions at a management group scope lets a
principal weaken or remove a deny-effect guardrail inherited by the subtree.
match:
- - principal: null
- HasPermission
- mg: null
- - mg: null
- HasPolicy
- guardrail: null
where:
- node_type(?mg) == ManagementGroup
- node_class(?guardrail) == Policy
- 'node_type(?guardrail) == OrganizationPolicy # Azure Policy assignment at MG (deny-effect)'
- ?principal effectively holds Microsoft.Authorization/policyAssignments/write (and/or policyDefinitions/write)
at ?mg (Owner or Resource Policy Contributor)
emit:
source_type: Identity
target_type: '*'
source: ?principal
target: ?guardrail
permissions:
- Microsoft.Authorization/policyAssignments/write
- Microsoft.Authorization/policyDefinitions/write
conditions:
- iam_permission
state_logic: ACTIVE for the modify capability when policyAssignments/write is held at ?mg; CONDITIONAL(iam_permission)
when gated. This edge is the INPUT to hierarchy-chains.yaml guardrail-removal-upgrades-blocked, which
re-emits every edge THIS guardrail was suppressing (BLOCKED) at its underlying state as CONDITIONAL(guardrail_removed).
Emitting CanModifyPolicy here does NOT itself upgrade any edge.
confidence: min(contributing_confidences)
derived_from:
- <HasPermission principal->mg (policyAssignments/write) edge_id>
- <HasPolicy mg->guardrail edge_id>
false_positive_note: "Applies to Azure POLICY assignments only (OrganizationPolicy node; Owner / Resource\
\ Policy Contributor can write them via policyAssignments/write). Azure DENY ASSIGNMENTS are modeled\
\ as the ConditionalPolicy subtype and are NOT written by policyAssignments/write \u2014 so this rule\
\ intentionally does NOT target ConditionalPolicy nodes (emitting CanModifyPolicy over a deny-assignment\
\ node under policyAssignments/write would be a permission/target mismatch). Deny assignments at MG\
\ scope are almost always system-managed (Blueprints / Managed Apps) and NOT directly user-writable;\
\ their realistic removal is deleting the owning blueprint/managed-app assignment or the move-out\
\ reparent (azure-mg-reparent), which the hierarchy-chains guardrail-removal upgrade should key off\
\ \u2014 mark CONDITIONAL when only that indirect route exists. Only fire when ?guardrail actually\
\ has a deny/deny-inheriting effect that suppresses edges; an audit-only policy blocks nothing."
narrative: '{principal.name} can modify the Azure Policy guardrail {guardrail.name} at management group
{mg.name} (Microsoft.Authorization/policyAssignments/write), lifting the deny it imposes on the subtree.'