> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Kubernetes RBAC Users With Azure AD

### More Info:

Integrate Azure Active Directory with Kubernetes RBAC so cluster access is governed by centrally managed Azure AD identities and group memberships.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS AKS

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Determine your AKS cluster’s auth model (Azure AD or local accounts)**
           * On any machine with `az` access, run:
             ```bash theme={null}
             az aks show \
               --resource-group <AKS_RESOURCE_GROUP> \
               --name <AKS_CLUSTER_NAME> \
               --query "{aadProfile:aadProfile, oidcIssuerProfile:oidcIssuerProfile, apiServerAccessProfile:apiServerAccessProfile}" \
               --output json
             ```
           * Review the output:
             * If `aadProfile` is `null` or empty and there is no `oidcIssuerProfile` in use with Azure AD Workload Identity, the cluster is not using Azure AD for client auth.
             * If `aadProfile.enableAzureRBAC` is `true`, AKS-managed Azure RBAC is used instead of Kubernetes-native RBAC; decide if this aligns with your org’s RBAC model.

        2. **Identify how kubectl clients currently authenticate (Azure AD vs static credentials)**
           * On any machine with `kubectl` access, inspect the kubeconfig being used:
             ```bash theme={null}
             kubectl config view --minify --raw
             ```
           * Look at the `users:` section:
             * `user.exec.command: az` or `kubelogin` and `exec.args` with `get-token` indicate Azure AD/OIDC-based auth.
             * `user.token`, `client-certificate-data`, or static `username`/`password` indicate non–Azure AD credentials (service accounts, client certs, or basic auth), which should be minimized for human users.

        3. **Review current Kubernetes RBAC subjects for non–Azure AD identities**
           * On any machine with `kubectl` access, list RBAC bindings and look for `User` subjects that are not Azure AD principals (for clusters already wired to AAD, user names are typically AAD UPNs or Object IDs):
             ```bash theme={null}
             kubectl get clusterrolebindings,rolebindings -A -o json \
               | jq '.items[].subjects // [] | .[] | select(.kind=="User")' 2>/dev/null
             ```
           * Flag any:
             * Local usernames or generic names (e.g., `admin`, `kube-admin`, `devops`) not traceable to Azure AD.
             * Tokens/certs issued outside Azure AD (service accounts are fine for workloads but not for human users).
           * Decide which of these should be re-mapped to Azure AD users or groups and plan to deprecate the non–AAD identities.

        4. **Verify Azure AD groups mapped into Kubernetes RBAC (if AAD is enabled)**
           * On any machine with `kubectl` access, inspect role bindings targeting `Group` subjects (these should correspond to Azure AD groups when Azure AD integration is used):
             ```bash theme={null}
             kubectl get clusterrolebindings,rolebindings -A -o json \
               | jq '.items[].subjects // [] | .[] | select(.kind=="Group")' 2>/dev/null
             ```
           * For each `name` value, confirm in the Azure portal (Azure AD → Groups) or via CLI:
             ```bash theme={null}
             az ad group show --group "<GROUP_NAME_OR_OBJECT_ID>"
             ```
           * Ensure:
             * Group membership is centrally managed in Azure AD (no per-user bindings where group-based bindings would work).
             * Privileged roles (e.g., bound to `cluster-admin`) are restricted to tightly controlled Azure AD groups.

        5. **If Azure AD is not integrated, plan and configure AAD-based access**
           * Decide, with your identity/security team, the target integration model:
             * AKS-managed Azure AD with Azure RBAC for Kubernetes authorization, or
             * AKS with AAD for auth and Kubernetes-native RBAC for authorization.
           * Implement using Azure documentation and IaC where possible. For example, to enable AKS-managed Azure AD and Azure RBAC on a new cluster (conceptual example; adapt to your environment):
             ```bash theme={null}
             az aks create \
               --resource-group <AKS_RESOURCE_GROUP> \
               --name <AKS_CLUSTER_NAME> \
               --enable-aad \
               --enable-azure-rbac \
               --aad-admin-group-object-ids <AAD_ADMIN_GROUP_OBJECT_ID> \
               --node-count 3 \
               --generate-ssh-keys
             ```
           * For existing clusters, review whether migration to Azure AD–backed auth is supported for your cluster version and apply changes using `az aks update` or redeploy via ARM/Bicep/Terraform per your standards.

        6. **Verify that Kubernetes RBAC is now governed by Azure AD identities**
           * On any machine with `az` access, obtain credentials using Azure AD:
             ```bash theme={null}
             az aks get-credentials \
               --resource-group <AKS_RESOURCE_GROUP> \
               --name <AKS_CLUSTER_NAME> \
               --overwrite-existing
             ```
           * Confirm that the active user is an Azure AD identity:
             ```bash theme={null}
             kubectl config view --minify -o jsonpath='{.users[0].user.exec.command}{" "}{.users[0].user.exec.args[*]}' && echo
             ```
           * Validate RBAC using Azure AD groups by attempting a namespaced operation as a member of an AAD group bound via RBAC (adjust namespace and group binding you configured):
             ```bash theme={null}
             kubectl auth can-i get pods --namespace kube-system
             ```
           * Confirm that:
             * Access outcomes (allowed/denied) match the Azure AD user/group memberships.
             * Human user access no longer relies on non–Azure AD static users/tokens, except for explicitly justified break-glass or automation accounts you documented.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to configure Azure AD integration for AKS; this setting is managed in the Azure portal / Azure CLI / IaC at the cloud-control-plane level. Refer to the Manual Steps section for guidance on how to review and configure Azure AD–based authentication and RBAC for your cluster.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Assess whether Kubernetes API access is integrated with Azure AD
        #   and whether RBAC is used (vs legacy mechanisms).
        #
        # Run on:
        #   Any machine with:
        #     - az CLI authenticated to the correct subscription/tenant (if AKS)
        #     - kubectl configured for the target cluster context

        set -euo pipefail

        echo "=== Context information ==="
        echo "kubectl current-context:"
        kubectl config current-context || echo "ERROR: kubectl not configured"

        echo
        echo "API server version:"
        kubectl version --short || echo "ERROR: cannot reach API server"

        echo
        echo "=== 1) Check if RBAC is enabled ==="
        # For managed AKS, this is usually always enabled on modern clusters,
        # but we confirm by inspecting API objects.
        echo "- ClusterRoleBindings (sample):"
        kubectl get clusterrolebindings.authorization.k8s.io -o name | head -n 10 || true

        echo
        echo "- Any legacy ABAC-related configuration present in apiserver config (if exposed as ConfigMap)?"
        echo "  (This is best-effort; many managed control planes do not expose it.)"
        kubectl get configmap -n kube-system -o name 2>/dev/null | grep -i 'apiserver' || echo "  No obvious apiserver configmap found (expected for AKS)."

        echo
        echo "Interpretation:"
        echo "  - Presence of ClusterRoles/ClusterRoleBindings indicates RBAC is in use."
        echo "  - If your provider documented ABAC support and you still rely on it, that is a concern."

        echo
        echo "=== 2) AKS-specific: Check AAD integration (requires az CLI) ==="
        echo "Attempting to detect AKS clusters in current subscription..."
        SUB_ID="$(az account show --query id -o tsv 2>/dev/null || echo '')"
        TENANT_ID="$(az account show --query tenantId -o tsv 2>/dev/null || echo '')"

        if [ -z "$SUB_ID" ]; then
          echo "WARNING: az CLI not logged in or not installed; skipping AKS AAD checks."
        else
          echo "Using subscription: $SUB_ID"
          echo "Tenant: $TENANT_ID"
          echo

          # List AKS clusters
          echo "Listing AKS clusters and their AAD integration status:"
          az aks list --query '[].{name:name, rg:resourceGroup, aadProfile: aadProfile, oidcIssuerProfile:oidcIssuerProfile}' -o table || {
            echo "ERROR: Unable to list AKS clusters."
          }

          echo
          echo "For the current kubectl context (if AKS), determine matching AKS cluster (best-effort):"
          CURRENT_SERVER="$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null || echo '')"
          if [ -n "$CURRENT_SERVER" ]; then
            echo "  API server URL from kubeconfig: $CURRENT_SERVER"
            echo
            echo "  NOTE: Match this URL with AKS cluster FQDNs from: az aks list -o table"
            echo "        to identify which AKS cluster your current context represents."
          else
            echo "  Could not determine API server URL from kubeconfig."
          fi

        fi

        echo
        echo "=== 3) Inspect Kubernetes subjects used in RBAC bindings ==="
        echo "Goal: Identify whether RBAC binds directly to local users/service accounts or"
        echo "      to well-known Azure AD identities/groups (based on naming conventions)."
        echo

        echo "- All ClusterRoleBindings with their subjects:"
        kubectl get clusterrolebinding -o json | jq -r '
          .items[] |
          .metadata.name as $crb |
          .subjects[]? |
          "\($crb)\t\(.kind)\t\(.apiGroup // "")\t\(.name)\t\(.namespace // "")"
        ' 2>/dev/null | column -t || echo "No ClusterRoleBindings or jq missing."

        echo
        echo "- All RoleBindings (namespace-scoped) with their subjects:"
        kubectl get rolebinding --all-namespaces -o json | jq -r '
          .items[] |
          .metadata.namespace as $ns |
          .metadata.name as $rb |
          .subjects[]? |
          "\($ns)\t\($rb)\t\(.kind)\t\(.apiGroup // "")\t\(.name)"
        ' 2>/dev/null | column -t || echo "No RoleBindings or jq missing."

        echo
        echo "Interpretation of RBAC subject listings (manual review):"
        echo "  Potential problems / items to investigate:"
        echo "    - Subjects of kind 'User' with opaque, non-AAD style names (e.g. 'admin', 'kube-admin')."
        echo "    - Bindings to broad or legacy users instead of Azure AD groups."
        echo "    - ClusterRoleBindings that grant cluster-admin or highly privileged roles to:"
        echo "        * Individual users instead of AAD groups"
        echo "        * ServiceAccounts in non-system namespaces without clear justification"
        echo "    - Any subjects that you cannot map to identities or groups in your Azure AD tenant."

        echo
        echo "Examples of desirable patterns (for reference during manual review):"
        echo "  - Subjects of kind 'Group' whose names match Azure AD group object IDs or UPN-style names,"
        echo "    and which are documented in your IAM model."
        echo "  - Minimal direct User bindings; preference for group-based access tied to AAD."

        echo
        echo "=== 4) Optional: enumerate ServiceAccounts with cluster-wide privileges ==="
        echo "These are not AAD-based, but often used for automation and should be documented."
        echo

        echo "- ServiceAccounts bound to cluster-admin:"
        kubectl get clusterrolebinding -o json 2>/dev/null | jq -r '
          .items[] |
          select(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin") |
          .metadata.name as $crb |
          .subjects[]? |
          select(.kind=="ServiceAccount") |
          "\($crb)\t\(.namespace)\t\(.name)"
        ' 2>/dev/null | column -t || echo "No cluster-admin bindings to ServiceAccounts found (or jq missing)."

        echo
        echo "Interpretation:"
        echo "  - Any ServiceAccount with cluster-admin should be explicitly justified and documented."
        echo "  - For human access, prefer Azure AD-backed identities and groups rather than ServiceAccounts."

        echo
        echo "=== How to interpret overall results ==="
        cat <<'EOF'
        You must make a manual decision on whether the cluster meets the intent:

        1) RBAC usage:
           - If RBAC is not being used (no ClusterRole/Role bindings, or provider docs show ABAC is active),
             this is a problem. Migration to RBAC and AAD integration should be planned.

        2) Identity source:
           - If kubectl access is granted via local kubeconfig users that are NOT backed by Azure AD:
               * e.g., client-certificate users, static admin credentials, 'clusterAdmin' accounts,
                 or users you cannot see in Azure AD
             then this indicates the cluster is not centrally governed by Azure AD.

        3) RBAC bindings:
           - If high-privilege roles (cluster-admin, admin) are bound directly to:
               * Individual users instead of groups, or
               * Identities not present/managed in Azure AD,
             this is a concern. Access should be shifted to Azure AD groups and identities.

        4) AKS AAD integration (if AKS):
           - From the 'az aks list' output:
               * If aadProfile is null/empty for the relevant AKS cluster,
                 the API server is not integrated with Azure AD.
               * If aadProfile is present but you still see non-AAD users in Role/ClusterRole bindings,
                 verify that:
                     - Users actually authenticate via Azure AD, and
                     - Bindings reference the correct AAD users/groups.

        No fully automated remediation is possible. Use this script's output to:
           - Inventory who/what has access via RBAC.
           - Cross-check these identities and groups against Azure AD.
           - Decide which bindings should be migrated to Azure AD groups or removed.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
