azure-sub-modify-deny-assignment
A principal who can delete the owning Blueprint/Managed-App or remove a deny-effect policy assignment can lift the guardrail suppressing inherited control edges.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_class(?guardrail) == Policy and node_type(?guardrail) in [
ConditionalPolicy, GenericPolicy]
?guardrail is a Microsoft.Authorization/denyAssignments node OR a deny/denyAction Microsoft.Authorization/policyAssignments node at a Subscription/ResourceGroup scope
?principal holds ONE OF: Microsoft.Authorization/policyAssignments/write or .../delete at the scope (removes a deny Azure Policy); Microsoft.Blueprint/blueprintAssignments/write|delete or Microsoft.Solutions/applications/write|delete (deletes the owning assignment that CREATED a system-managed deny assignment)
emit
| source type | Identity |
|---|---|
| target type | * |
| source | ?principal |
| target | ?guardrail |
| permissions | Microsoft.Authorization/policyAssignments/write Microsoft.Authorization/policyAssignments/delete Microsoft.Blueprint/blueprintAssignments/delete Microsoft.Solutions/applications/delete |
| conditions | guardrail_owner_write |
| state logic | ACTIVE for a DENY AZURE POLICY when the principal holds policyAssignments/write or delete at the scope (Owner or Resource Policy Contributor). CONDITIONAL (guardrail_owner_write) for a system-managed DENY ASSIGNMENT: those are not directly user-writable, so removal requires deleting the owning Blueprint assignment / Managed Application — mark CONDITIONAL because it is an indirect, multi-step route. BLOCKED if the principal lacks any removal capability. |
Narrative
{principal.name} can remove the guardrail {guardrail.name} (delete its owning Blueprint/Managed-App assignment, or remove the deny Azure Policy), lifting the block on the control edges it was suppressing.
Raw rule rules/derived/azure/subscriptions.yaml
id: azure-sub-modify-deny-assignment
emits: CanModifyPolicy
description: A principal who can delete the owning Blueprint/Managed-App or remove a deny-effect policy
assignment can lift the guardrail suppressing inherited control edges.
match:
- - principal: null
- HasPermission
- guardrail: null
where:
- node_class(?guardrail) == Policy and node_type(?guardrail) in [ConditionalPolicy, GenericPolicy]
- ?guardrail is a Microsoft.Authorization/denyAssignments node OR a deny/denyAction Microsoft.Authorization/policyAssignments
node at a Subscription/ResourceGroup scope
- '?principal holds ONE OF: Microsoft.Authorization/policyAssignments/write or .../delete at the scope
(removes a deny Azure Policy); Microsoft.Blueprint/blueprintAssignments/write|delete or Microsoft.Solutions/applications/write|delete
(deletes the owning assignment that CREATED a system-managed deny assignment)'
emit:
source_type: Identity
target_type: '*'
source: ?principal
target: ?guardrail
permissions:
- Microsoft.Authorization/policyAssignments/write
- Microsoft.Authorization/policyAssignments/delete
- Microsoft.Blueprint/blueprintAssignments/delete
- Microsoft.Solutions/applications/delete
conditions:
- guardrail_owner_write
state_logic: "ACTIVE for a DENY AZURE POLICY when the principal holds policyAssignments/write or delete\
\ at the scope (Owner or Resource Policy Contributor). CONDITIONAL (guardrail_owner_write) for a system-managed\
\ DENY ASSIGNMENT: those are not directly user-writable, so removal requires deleting the owning Blueprint\
\ assignment / Managed Application \u2014 mark CONDITIONAL because it is an indirect, multi-step route.\
\ BLOCKED if the principal lacks any removal capability."
confidence: '0.75'
derived_from:
- <HasPermission edge_id (policyAssignments/delete OR blueprintAssignments/delete OR applications/delete
@scope)>
note: This CanModifyPolicy over the guardrail node is CONSUMED by hierarchy-chains guardrail-removal-upgrades-blocked,
which re-emits every edge the guardrail was suppressing (blocked_by == ?guardrail) at its underlying
state, CONDITIONAL(guardrail_removed). We DO NOT perform that upgrade here; we only supply the modify
capability and document the gated edges (see the service .md GUARDRAIL section).
false_positive_note: "Azure deny assignments are overwhelmingly SYSTEM-MANAGED (created by Blueprints\
\ and Managed Applications) and NOT writable via a general denyAssignments/write \u2014 do NOT assume\
\ a direct-edit path. Prefer the delete-owning-assignment or move-out route (azure-sub-move-out-of-guardrail)\
\ and keep CONDITIONAL. Deny-EFFECT AZURE POLICY, by contrast, IS user-removable with policyAssignments/write|delete\
\ \u2014 that path can be ACTIVE. Fire only when the guardrail actually gates a BLOCKED edge (verified\
\ downstream by blocked_by)."
narrative: '{principal.name} can remove the guardrail {guardrail.name} (delete its owning Blueprint/Managed-App
assignment, or remove the deny Azure Policy), lifting the block on the control edges it was suppressing.'