azure-sb-sas-send-writedata

Holding a SAS connection string with Send rights (obtained via CanReadSecret/listKeys) grants data-plane send to the scoped namespace/queue/topic - equivalent to the Entra Data Sender role but credential-based.

derived azure emits CanWriteData

match

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

{'principal': None} CanReadSecret {'connstr': None}

where

node_type(?connstr) == ConnectionString ?connstr is a Service Bus SAS connection string whose rights include Send or Manage ?entity is the namespace, queue, or topic scoped by the connection string

emit

source typeIdentity
target typeMessaging
source?principal
target<queue or topic (Queue/Topic) or namespace (GenericMessaging) scoped by ?connstr>
state logicACTIVE when CanReadSecret(?principal, ?connstr) is ACTIVE (i.e., listKeys confirmed and disableLocalAuth=false) AND the connection string's rights include 'Send' or 'Manage'. CONDITIONAL if the CanReadSecret contributing edge is CONDITIONAL. A Manage right implicitly includes Send. BLOCKED if disableLocalAuth=true (no SAS active) or if the listKeys action is denied. Scoped to the entity the connection string was issued for: a queue-scoped Send SAS does NOT grant send to other queues or the namespace broadly.

Narrative

{principal.name} obtained a SAS connection string for {target.name} with Send rights (via listKeys); this credential grants data-plane send to {target.name} without Entra RBAC, equivalent to the Data Sender role.

Raw rule rules/derived/azure/servicebus.yaml

id: azure-sb-sas-send-writedata
emits: CanWriteData
description: "Holding a SAS connection string with Send rights (obtained via CanReadSecret/listKeys) grants\
  \ data-plane send to the scoped namespace/queue/topic \u2014 equivalent to the Entra Data Sender role\
  \ but credential-based."
match:
- - principal: null
  - CanReadSecret
  - connstr: null
where:
- node_type(?connstr) == ConnectionString
- ?connstr is a Service Bus SAS connection string whose rights include Send or Manage
- ?entity is the namespace, queue, or topic scoped by the connection string
emit:
  source_type: Identity
  target_type: Messaging
  source: ?principal
  target: <queue or topic (Queue/Topic) or namespace (GenericMessaging) scoped by ?connstr>
  permissions: []
  conditions: []
  state_logic: 'ACTIVE when CanReadSecret(?principal, ?connstr) is ACTIVE (i.e., listKeys confirmed and
    disableLocalAuth=false) AND the connection string''s rights include ''Send'' or ''Manage''. CONDITIONAL
    if the CanReadSecret contributing edge is CONDITIONAL. A Manage right implicitly includes Send. BLOCKED
    if disableLocalAuth=true (no SAS active) or if the listKeys action is denied. Scoped to the entity
    the connection string was issued for: a queue-scoped Send SAS does NOT grant send to other queues
    or the namespace broadly.'
  confidence: min(contributing_confidences)
  derived_from:
  - ?principal CanReadSecret ?connstr (azure-sb-namespace-listkeys or queue/topic equivalents)
  - connection string rights array includes 'Send' or 'Manage'
  - 'messaging-chains.yaml: messaging-publish-triggers-consumer (rule 1) consumes this CanWriteData'
  false_positive_note: 'Only emit when the rights array contains ''Send'' or ''Manage''. A Listen-only
    SAS key does NOT grant send. A Manage right includes Send implicitly (Manage = Send + Listen + Manage).
    Honor the scope of the connection string: a queue-scoped Send SAS covers only that queue; a namespace-scoped
    Send SAS covers all queues and topics. If disableLocalAuth=true, no SAS key is active and this edge
    must not be emitted.'
  narrative: '{principal.name} obtained a SAS connection string for {target.name} with Send rights (via
    listKeys); this credential grants data-plane send to {target.name} without Entra RBAC, equivalent
    to the Data Sender role.'
move · open · esc close