azure-sub-move-out-of-guardrail
A principal who can move a resource/RG/subscription out of a guardrail's scope escapes the deny assignment without editing it.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal holds ONE OF: Microsoft.Resources/subscriptions/resourceGroups/moveResources/action (move a resource to an RG the guardrail does not cover); Microsoft.Resources/subscriptions/resourceGroups/write (create/repoint an RG outside scope); Microsoft.Management/managementGroups/subscriptions/write (move the subscription to an MG without the deny assignment)
the target guardrail's scope does NOT cover the destination (else the move does not escape it)
emit
| source type | Identity |
|---|---|
| target type | * |
| source | ?principal |
| target | ?scope_binding |
| permissions | Microsoft.Resources/subscriptions/resourceGroups/moveResources/action Microsoft.Management/managementGroups/subscriptions/write |
| conditions | destination_outside_guardrail |
| state logic | CONDITIONAL(destination_outside_guardrail): only escapes the guardrail if a destination scope exists that the deny assignment/policy does not also cover (a tenant-root deny assignment cannot be escaped by moving within the tenant). ACTIVE only when such a destination is confirmed. BLOCKED if the move action itself is denied. |
Narrative
{principal.name} can move the affected resource/subscription out of the guardrail {scope_binding.name}'s scope, escaping the deny assignment without editing it.
Raw rule rules/derived/azure/subscriptions.yaml
id: azure-sub-move-out-of-guardrail
emits: CanModifyConfiguration
description: A principal who can move a resource/RG/subscription out of a guardrail's scope escapes the
deny assignment without editing it.
match:
- - principal: null
- HasPermission
- scope_binding: null
where:
- '?principal holds ONE OF: Microsoft.Resources/subscriptions/resourceGroups/moveResources/action (move
a resource to an RG the guardrail does not cover); Microsoft.Resources/subscriptions/resourceGroups/write
(create/repoint an RG outside scope); Microsoft.Management/managementGroups/subscriptions/write (move
the subscription to an MG without the deny assignment)'
- the target guardrail's scope does NOT cover the destination (else the move does not escape it)
emit:
source_type: Identity
target_type: '*'
source: ?principal
target: ?scope_binding
permissions:
- Microsoft.Resources/subscriptions/resourceGroups/moveResources/action
- Microsoft.Management/managementGroups/subscriptions/write
conditions:
- destination_outside_guardrail
state_logic: 'CONDITIONAL(destination_outside_guardrail): only escapes the guardrail if a destination
scope exists that the deny assignment/policy does not also cover (a tenant-root deny assignment cannot
be escaped by moving within the tenant). ACTIVE only when such a destination is confirmed. BLOCKED
if the move action itself is denied.'
confidence: '0.7'
derived_from:
- <HasPermission edge_id (moveResources/action OR managementGroups/subscriptions/write @scope)>
note: Provides the OPTIONAL move-out branch of hierarchy-chains guardrail-removal-upgrades-blocked (its
optional CanModifyConfiguration clause). Either this or azure-sub-modify-deny-assignment suffices
to trigger the BLOCKED->ACTIVE upgrade there.
false_positive_note: "Moving a resource does not escape a guardrail whose scope also covers the destination\
\ \u2014 a subscription-wide or root-MG deny assignment is not escaped by an in-subscription move.\
\ Verify the destination is genuinely outside scope; otherwise do not treat as a removal path. moveResources\
\ also requires write on both source and destination and may be blocked by resource-type move constraints."
narrative: '{principal.name} can move the affected resource/subscription out of the guardrail {scope_binding.name}''s
scope, escaping the deny assignment without editing it.'