azure-openai-listkeys

listKeys or regenerateKey on an Azure OpenAI account retrieves symmetric API keys that authenticate to all model deployments.

derived azure emits CanReadSecret

match (effective permission)

{ "any_of": [ { "action": "Microsoft.CognitiveServices/accounts/listKeys/action", "scope_type": [ "resource", "resourceGroup", "subscription" ] }, { "action": "Microsoft.CognitiveServices/accounts/regenerateKey/action", "scope_type": [ "resource", "resourceGroup", "subscription" ] } ] }

where

account.properties.disableLocalAuth != true # key-based auth is not disabled node_type(account) == GenericData and account.kind in [OpenAI, AIServices, CognitiveServices]

emit

source typeIdentity
target typeAPIKey
source<principal>
target<Cognitive Services account API keys (primary and secondary)>
permissionsMicrosoft.CognitiveServices/accounts/listKeys/action Microsoft.CognitiveServices/accounts/regenerateKey/action
conditionsiam_permission
state logicif account.properties.disableLocalAuth == true: BLOCKED # keys disabled at account level elif principal has listKeys/action OR regenerateKey/action effective at resource|RG|sub scope: ACTIVE else: do not emit

Narrative

{principal.name} can call listKeys (or regenerateKey) on Azure OpenAI account {account.name} (Microsoft.CognitiveServices/accounts/listKeys/action or …/regenerateKey/action), retrieving the symmetric API key that authenticates to all model deployments in the account without Entra RBAC.

Raw rule rules/derived/azure/openai.yaml

id: azure-openai-listkeys
emits: CanReadSecret
description: listKeys or regenerateKey on an Azure OpenAI account retrieves symmetric API keys that authenticate
  to all model deployments.
match_effective_permission:
  any_of:
  - action: Microsoft.CognitiveServices/accounts/listKeys/action
    scope_type:
    - resource
    - resourceGroup
    - subscription
  - action: Microsoft.CognitiveServices/accounts/regenerateKey/action
    scope_type:
    - resource
    - resourceGroup
    - subscription
where:
- 'account.properties.disableLocalAuth != true   # key-based auth is not disabled'
- node_type(account) == GenericData and account.kind in [OpenAI, AIServices, CognitiveServices]
emit:
  source_type: Identity
  target_type: APIKey
  source: <principal>
  target: <Cognitive Services account API keys (primary and secondary)>
  permissions:
  - Microsoft.CognitiveServices/accounts/listKeys/action
  - Microsoft.CognitiveServices/accounts/regenerateKey/action
  state_logic: 'if account.properties.disableLocalAuth == true: BLOCKED  # keys disabled at account level

    elif principal has listKeys/action OR regenerateKey/action effective at resource|RG|sub scope: ACTIVE

    else: do not emit

    '
  conditions:
  - iam_permission
  conditions_from: []
  derived_from:
  - iam_permission:principal:Microsoft.CognitiveServices/accounts/listKeys/action
  - iam_permission:principal:Microsoft.CognitiveServices/accounts/regenerateKey/action
  false_positive_note: "BLOCKED when disableLocalAuth is true \u2014 in that configuration Azure OpenAI\
    \ rejects key-based authentication entirely and listKeys returns an error. regenerateKey/action alone\
    \ is sufficient: the regenerated key value is returned in the response, so the caller obtains a usable\
    \ key even without listKeys/action. Honor the action scope: a role assignment scoped to a different\
    \ account does NOT grant key retrieval for this account. Do NOT model the API key as yielding CanExecuteAs\
    \ \u2014 Azure OpenAI exposes no managed identity or execution role to key holders."
  narrative: "{principal.name} can call listKeys (or regenerateKey) on Azure OpenAI account {account.name}\
    \ (Microsoft.CognitiveServices/accounts/listKeys/action or \u2026/regenerateKey/action), retrieving\
    \ the symmetric API key that authenticates to all model deployments in the account without Entra RBAC."
move · open · esc close