azure-kv-decrypt-gates-readdata
CanDecrypt on the wrapping KV key completes CanReadData on an externally-stored, CMK-wrapped store.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?store data-plane control-plane read is present but the store is encrypted with customer-managed key ?key (storage/disk/SQL TDE wrapped by this KV key)
emit
| source | ?principal |
|---|---|
| target | ?store |
| permissions | Microsoft.KeyVault/vaults/keys/unwrap/action |
| conditions | key_permission |
| state logic | if ?principal lacks keys/unwrap|decrypt on ?key: CONDITIONAL(key_permission); else ACTIVE |
Narrative
{principal.name} can read CMK-encrypted store {store.name} because it can unwrap the wrapping key {key.name} (keys/unwrap).
Raw rule rules/derived/azure/keyvault.yaml
id: azure-kv-decrypt-gates-readdata
emits: CanReadData
description: CanDecrypt on the wrapping KV key completes CanReadData on an externally-stored, CMK-wrapped
store.
match:
- - principal: null
- CanReadData
- store: null
- - principal: null
- CanDecrypt
- key: null
where:
- ?store data-plane control-plane read is present but the store is encrypted with customer-managed key
?key (storage/disk/SQL TDE wrapped by this KV key)
emit:
source: ?principal
target: ?store
permissions:
- Microsoft.KeyVault/vaults/keys/unwrap/action
conditions:
- key_permission
state_logic: 'if ?principal lacks keys/unwrap|decrypt on ?key: CONDITIONAL(key_permission); else ACTIVE'
confidence: min(contributing_confidences) * 0.9
derived_from:
- <CanReadData edge_id>
- <CanDecrypt edge_id>
false_positive_note: "This gate is for EXTERNAL stores wrapped by a Key Vault key \u2014 NOT for reading\
\ secrets inside Key Vault itself (those decrypt transparently). Only apply when the store's CMK is\
\ this key; do not gate on unrelated keys."
narrative: '{principal.name} can read CMK-encrypted store {store.name} because it can unwrap the wrapping
key {key.name} (keys/unwrap).'