azure-rediscache-listkeys-principal-read-credential

A principal with listKeys/action permission can retrieve the Redis access key via ARM, gaining read access to the credential.

derived azure emits CanReadCredential

match

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

{'principal': None} HasPermission {'cache': None} {'cache': None} ExposesCredential {'accessKey': None}

where

node_type(?cache) == Cache ?cache.provider_type == 'Microsoft.Cache/redis' node_type(?accessKey) == AccessKey ?principal has EFFECTIVE Microsoft.Cache/redis/listKeys/action at ?cache scope (Owner, Contributor, Redis Cache Contributor, or custom role)

emit

source typeIdentity
target typeAccessKey
source?principal
target?accessKey
permissionsMicrosoft.Cache/redis/listKeys/action
conditionsiam_permission
state logicif a deny assignment or deny Azure Policy covers listKeys/action at the effective scope: BLOCKED; else ACTIVE: the principal can call the ARM listKeys REST API (POST .../redis/{name}/listKeys) from any network and retrieve both the primaryKey and secondaryKey. This is an ARM control-plane action not gated by the Redis IP firewall (firewallRules) or publicNetworkAccess setting.

Narrative

{principal.name} holds Microsoft.Cache/redis/listKeys/action on {cache.name}, allowing retrieval of the primary and secondary access keys via ARM.

Raw rule rules/derived/azure/rediscache.yaml

id: azure-rediscache-listkeys-principal-read-credential
emits: CanReadCredential
description: A principal with listKeys/action permission can retrieve the Redis access key via ARM, gaining
  read access to the credential.
match:
- - principal: null
  - HasPermission
  - cache: null
- - cache: null
  - ExposesCredential
  - accessKey: null
where:
- node_type(?cache) == Cache
- ?cache.provider_type == 'Microsoft.Cache/redis'
- node_type(?accessKey) == AccessKey
- ?principal has EFFECTIVE Microsoft.Cache/redis/listKeys/action at ?cache scope (Owner, Contributor,
  Redis Cache Contributor, or custom role)
emit:
  source_type: Identity
  target_type: AccessKey
  source: ?principal
  target: ?accessKey
  permissions:
  - Microsoft.Cache/redis/listKeys/action
  conditions:
  - iam_permission
  state_logic: 'if a deny assignment or deny Azure Policy covers listKeys/action at the effective scope:
    BLOCKED; else ACTIVE: the principal can call the ARM listKeys REST API (POST .../redis/{name}/listKeys)
    from any network and retrieve both the primaryKey and secondaryKey. This is an ARM control-plane action
    not gated by the Redis IP firewall (firewallRules) or publicNetworkAccess setting.'
  confidence: '0.97'
  derived_from:
  - <HasPermission edge_id (listKeys/action)>
  - "<ExposesCredential edge_id (cache \u2192 accessKey)>"
  false_positive_note: "Verify the EFFECTIVE permission at the ?cache scope \u2014 do not infer from the\
    \ role name alone. Redis Cache Contributor includes listKeys/action. The \"Cosmos DB Operator\" and\
    \ \"SQL Server Contributor\" roles do NOT cover Microsoft.Cache resources. The ARM listKeys call succeeds\
    \ regardless of firewallRules or publicNetworkAccess; this CanReadCredential edge is always ACTIVE\
    \ when the RBAC grant is confirmed. Using the retrieved key against the Redis data-plane is separately\
    \ gated by network_reachability (see azure-rediscache-listkeys-can-read-data)."
  narrative: '{principal.name} holds Microsoft.Cache/redis/listKeys/action on {cache.name}, allowing retrieval
    of the primary and secondary access keys via ARM.'
move · open · esc close