azure-rediscache-listkeys-can-read-data
Retrieving the cache access key via listKeys/action yields full data-plane read of all cached data, subject to network reachability of the Redis endpoint.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanReadCredential {'accessKey': None}
{'accessKey': None} CredentialsFor {'cache': None}
where
node_type(?cache) ==
Cache
?cache.provider_type == 'Microsoft.Cache/redis'
node_type(?accessKey) == AccessKey
emit
| source type | Identity |
|---|---|
| target type | Cache |
| source | ?principal |
| target | ?cache |
| permissions | Microsoft.Cache/redis/listKeys/action |
| conditions | iam_permission network_reachability |
| state logic | if a deny assignment or deny Azure Policy covers listKeys/action: BLOCKED; elif ?cache.properties.publicNetworkAccess == 'Disabled' AND no private endpoint reachable from caller: CONDITIONAL(network_reachability) — key is obtainable via ARM but the data-plane is not reachable; the path is possible if the caller gains a foothold in the VNet (e.g., via a private endpoint or VNet peering); elif ?cache.properties.publicNetworkAccess == 'Enabled' AND firewallRules restrict the caller's network: CONDITIONAL(network_reachability); elif ?cache.properties.publicNetworkAccess == 'Enabled' AND (firewallRules is empty OR contains a rule allowing the caller's IP): ACTIVE — the caller can retrieve the key via ARM and immediately connect to the Redis data endpoint. Note: Premium VNet-injected instances have publicNetworkAccess forced Disabled; treat as CONDITIONAL(network_reachability) unless the caller has VNet access. |
Narrative
{principal.name} can retrieve the access key for {cache.name} via listKeys/action (ARM, network-unrestricted), then authenticate to the Redis data endpoint and read all cached data. Full data-plane access includes KEYS, GET, SCAN, DUMP, and CONFIG commands. Network reachability to the Redis endpoint is required for the data-plane step; the ARM key retrieval is unconditional.
Raw rule rules/derived/azure/rediscache.yaml
id: azure-rediscache-listkeys-can-read-data
emits: CanReadData
description: Retrieving the cache access key via listKeys/action yields full data-plane read of all cached
data, subject to network reachability of the Redis endpoint.
match:
- - principal: null
- CanReadCredential
- accessKey: null
- - accessKey: null
- CredentialsFor
- cache: null
where:
- node_type(?cache) == Cache
- ?cache.provider_type == 'Microsoft.Cache/redis'
- node_type(?accessKey) == AccessKey
emit:
source_type: Identity
target_type: Cache
source: ?principal
target: ?cache
permissions:
- Microsoft.Cache/redis/listKeys/action
conditions:
- iam_permission
- network_reachability
state_logic: "if a deny assignment or deny Azure Policy covers listKeys/action: BLOCKED; elif ?cache.properties.publicNetworkAccess\
\ == 'Disabled' AND no private endpoint reachable from caller: CONDITIONAL(network_reachability) \u2014\
\ key is obtainable via ARM but the data-plane is not reachable; the path is possible if the caller\
\ gains a foothold in the VNet (e.g., via a private endpoint or VNet peering); elif ?cache.properties.publicNetworkAccess\
\ == 'Enabled' AND firewallRules restrict the caller's network: CONDITIONAL(network_reachability);\
\ elif ?cache.properties.publicNetworkAccess == 'Enabled' AND (firewallRules is empty OR contains\
\ a rule allowing the caller's IP): ACTIVE \u2014 the caller can retrieve the key via ARM and immediately\
\ connect to the Redis data endpoint. Note: Premium VNet-injected instances have publicNetworkAccess\
\ forced Disabled; treat as CONDITIONAL(network_reachability) unless the caller has VNet access."
confidence: '0.95'
derived_from:
- "<CanReadCredential edge_id (principal \u2192 accessKey)>"
- "<CredentialsFor edge_id (accessKey \u2192 cache)>"
false_positive_note: "The key retrieval (ARM listKeys via CanReadCredential) is always ACTIVE when the\
\ RBAC grant is confirmed; this CanReadData edge additionally requires network reachability to the\
\ Redis data-plane endpoint (port 6380/SSL or 6379/non-SSL). When publicNetworkAccess=Disabled, the\
\ data-plane is only reachable via private endpoint or (for Premium) the injected VNet \u2014 downgrade\
\ to CONDITIONAL(network_reachability). For Standard/Premium tier, the Redis endpoint only accepts\
\ key-based authentication (no Entra ID data-plane token auth); this rule correctly models the key-based\
\ path. Do NOT emit ACTIVE for VNet-injected Premium instances without confirming VNet reachability."
narrative: '{principal.name} can retrieve the access key for {cache.name} via listKeys/action (ARM,
network-unrestricted), then authenticate to the Redis data endpoint and read all cached data. Full
data-plane access includes KEYS, GET, SCAN, DUMP, and CONFIG commands. Network reachability to the
Redis endpoint is required for the data-plane step; the ARM key retrieval is unconditional.'