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.

derived azure emits CanModifyPolicy

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} HasPermission {'guardrail': None}

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 typeIdentity
target type*
source?principal
target?guardrail
permissionsMicrosoft.Authorization/policyAssignments/write Microsoft.Authorization/policyAssignments/delete Microsoft.Blueprint/blueprintAssignments/delete Microsoft.Solutions/applications/delete
conditionsguardrail_owner_write
state logicACTIVE 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.'
move · open · esc close