azure-vnet-cross-tenant-peering

A Connected VNet peering that crosses Entra tenant boundaries (emitted from explicit azure-vnet-peering-record) extends network reachability AND establishes a cross-tenant trust boundary - a critical lateral-movement fact.

derived azure emits PeeredWithCrossTenantTrust

match

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

{'localVNet': None} PeeredWith {'remoteVNet': None}

where

?localVNet.tenant_id != ?remoteVNet.tenant_id (tenant boundary crossed) peeringState == Connected on both sides (from explicit record)

emit

Raw rule rules/derived/azure/vnet.yaml

id: azure-vnet-cross-tenant-peering
emits:
- PeeredWith
- CrossTenantTrust
description: "A Connected VNet peering that crosses Entra tenant boundaries (emitted from explicit azure-vnet-peering-record)\
  \ extends network reachability AND establishes a cross-tenant trust boundary \u2014 a critical lateral-movement\
  \ fact."
match:
- - localVNet: null
  - PeeredWith
  - remoteVNet: null
where:
- ?localVNet.tenant_id != ?remoteVNet.tenant_id (tenant boundary crossed)
- peeringState == Connected on both sides (from explicit record)
emit:
- edge_type: PeeredWith
  source_type: VirtualNetwork
  target_type: VirtualNetwork
  source: <local VNet node>
  target: <remote VNet node, peered across the tenant boundary>
  permissions: []
  state_logic: "ACTIVE when cross-tenant peering is confirmed Connected on both sides. CONDITIONAL(network_reachability)\
    \ if remote-side state is unconfirmed (collection gap \u2014 remote tenant not in collection scope)."
  derived_from:
  - azure-vnet-peering-record
- edge_type: CrossTenantTrust
  source_type: Tenant
  target_type: Tenant
  source: <Tenant node containing local VNet>
  target: <Tenant node containing remote VNet>
  permissions: []
  properties:
    cross_tenant: true
    local_tenant: '{localVNet.tenant_id}'
    remote_tenant: '{remoteVNet.tenant_id}'
  state_logic: "ACTIVE when cross-tenant peering is confirmed Connected on both sides. CONDITIONAL(network_reachability)\
    \ if remote-side state is unconfirmed (collection gap \u2014 remote tenant not in collection scope).\
    \ Cross-tenant peering requires explicit role grant (peer/action or Contributor) on the local VNet\
    \ to the remote-tenant principal; this is a prerequisite for peering to complete, not a differentiator\
    \ between ACTIVE and CONDITIONAL."
  derived_from:
  - azure-vnet-peering-record
  false_positive_note: The peering bridges network paths only; it does NOT grant ARM control in either
    direction. Use the properties.cross_tenant flag for analyst-query filtering. Verify tenant enrollment
    by comparing subscription tenant IDs from both peering sides. Cross-tenant peering with ApplicationIdentity
    principals (B2B service principals) is a common integration pattern; assess the trust relationship
    separately.
  narrative: VNet {localVNet.name} (tenant {source.id}) is peered with VNet {remoteVNet.name} (tenant
    {target.id}); a foothold in that tenant grants network-layer reach across the tenant boundary without
    crossing any internet boundary.
move · open · esc close