azure-aks-list-admin-cred
listClusterAdminCredential returns a static cluster-admin kubeconfig that bypasses AAD, giving unconditional cluster-admin access to the cluster.
match (effective permission)
{
"action": "Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action",
"scope_type": "resource|resourceGroup|subscription"
}
where
principal effectively holds the listClusterAdminCredential action at the cluster scope
emit
| source type | Identity |
|---|---|
| target type | Credential |
| source | <principal> |
| target | <cluster-admin kubeconfig (Credential) for the AKS cluster> |
| permissions | Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action |
| conditions | iam_permission service_state |
| state logic | ACTIVE when the cluster has localAccountsDisabled: false (default) — the returned client certificate is a fully valid static credential that requires no further Entra authentication. CONDITIONAL(deny_assignment) when localAccountsDisabled: true — the action still succeeds but returns an AAD-interactive kubeconfig, so the static-cert bypass does NOT apply; the cluster-admin cert path requires local accounts to be enabled. CONDITIONAL(service_state) if the cluster powerState.code is not Running. BLOCKED if a deny assignment covers this action at the cluster/RG/subscription scope. |
Narrative
{principal.name} holds listClusterAdminCredential/action on cluster {target.name} and can retrieve a static client-certificate kubeconfig for cluster-admin, bypassing AAD authentication entirely - any further kubectl command runs with full cluster-admin privilege.
Raw rule rules/derived/azure/aks.yaml
id: azure-aks-list-admin-cred
emits: CanReadCredential
description: listClusterAdminCredential returns a static cluster-admin kubeconfig that bypasses AAD, giving
unconditional cluster-admin access to the cluster.
match_effective_permission:
action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action
scope_type: resource|resourceGroup|subscription
where:
- principal effectively holds the listClusterAdminCredential action at the cluster scope
emit:
source_type: Identity
target_type: Credential
source: <principal>
target: <cluster-admin kubeconfig (Credential) for the AKS cluster>
permissions:
- Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action
conditions:
- iam_permission
- service_state
state_logic: "ACTIVE when the cluster has localAccountsDisabled: false (default) \u2014 the returned\
\ client certificate is a fully valid static credential that requires no further Entra authentication.\
\ CONDITIONAL(deny_assignment) when localAccountsDisabled: true \u2014 the action still succeeds\
\ but returns an AAD-interactive kubeconfig, so the static-cert bypass does NOT apply; the cluster-admin\
\ cert path requires local accounts to be enabled. CONDITIONAL(service_state) if the cluster powerState.code\
\ is not Running. BLOCKED if a deny assignment covers this action at the cluster/RG/subscription\
\ scope."
confidence: 0.97
false_positive_note: "When localAccountsDisabled: true (properties.disableLocalAccounts: true) the returned\
\ kubeconfig is AAD-gated, NOT a static cert \u2014 do NOT emit ACTIVE for the static-cert bypass;\
\ downgrade to CONDITIONAL(deny_assignment) with a note. Verify the cluster is running (powerState.code\
\ == Running) before emitting ACTIVE. Deny assignments covering this action block it entirely."
narrative: "{principal.name} holds listClusterAdminCredential/action on cluster {target.name} and can\
\ retrieve a static client-certificate kubeconfig for cluster-admin, bypassing AAD authentication\
\ entirely \u2014 any further kubectl command runs with full cluster-admin privilege."