Skip to main content

Use Cluster Access Manager API To Manage Access Controls

More Info:

The Cluster Access Manager API streamlines management of authenticated IAM principals for EKS clusters. Choose the appropriate authentication mode to centralize and secure access control.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS EKS

Triage and Remediation

Remediation

Manual Steps
  1. On any machine with kubectl access, confirm cluster identity and context to avoid changing the wrong cluster:

    kubectl config current-context
    kubectl config view --minify
  2. Still on the kubectl machine, check whether the legacy aws-auth ConfigMap is in use and inspect its contents:

    kubectl get configmap aws-auth -n kube-system -o yaml

    Review:

    • Whether mapRoles, mapUsers, or mapAccounts are present.
    • Who currently has access (IAM roles/users/accounts) and whether this matches your organization’s intended access model.
  3. In the AWS Management Console, navigate to Amazon EKS → your cluster → Access → Access configuration and review:

    • The “Cluster authentication mode” setting (EKS API vs ConfigMap).
    • Whether this matches your intended source of authenticated IAM principals (centralized via EKS Access Entries, or managed via aws-auth).
  4. If the cluster authentication mode does not align with your desired model and the cluster is newly created or being created via IaC, adjust it at creation time:

    • In the console: choose either EKS API or ConfigMap under “Cluster authentication mode” before provisioning.
    • In IaC (CloudFormation/Terraform/etc.): set the equivalent parameter for authentication mode so that future clusters are created with the correct setting.
  5. For existing clusters (where authentication mode cannot be changed), decide on your management model:

    • If using EKS API: ensure all required IAM principals are granted access via EKS Access Entries (console or IaC) and gradually phase out any reliance on aws-auth.
    • If using ConfigMap: keep aws-auth as the source of truth and maintain it via GitOps/IaC, ensuring its contents are regularly reviewed and audited.
  6. Re-verify configuration after any changes:

    • In the console: confirm the “Cluster authentication mode” under Access → Access configuration.
    • With kubectl: confirm aws-auth matches your intended mapping (or is empty/unused if you’ve fully moved to EKS API):
      kubectl get configmap aws-auth -n kube-system -o yaml
Using kubectl
# 1. Check aws-auth ConfigMap (any machine with kubectl access)
kubectl -n kube-system get configmap aws-auth -o yaml

Review points:

  • If the ConfigMap does not exist or is empty but you expect to be using ConfigMap authentication mode, that’s a problem.
  • If mapRoles / mapUsers / mapAccounts contain IAM principals that should not have cluster access, or use overly broad roles (e.g., admin roles for many users), that indicates a problem with access control design.
  • If there is an eks.amazonaws.com/role-arn mapping you don’t recognize or that grants cluster-admin privileges widely, that is a red flag.
# 2. Check which subjects currently have RBAC-level access (any machine with kubectl access)
kubectl get clusterrolebindings -o wide
kubectl get rolebindings -A -o wide

Review points:

  • Look for ClusterRoleBinding objects that bind cluster-admin (or other powerful roles) to subjects that correspond to IAM users/roles (often via system:masters group or mapped IAM entities in aws-auth) more broadly than intended.
  • Any binding that effectively grants admin rights to principals you did not intend to be administrators is a problem.
# 3. Inspect a specific powerful binding in detail (any machine with kubectl access)
kubectl get clusterrolebinding <binding-name> -o yaml

Review points:

  • Confirm that subjects match only the IAM-mapped Kubernetes users/groups that should have that level of access.
  • Mismatches between intended IAM principals and actual bound subjects indicate misaligned access control.
# 4. Confirm current authentication behavior at the API server level (any machine with kubectl access)
kubectl auth can-i --list

Review points:

  • Run this as different principals (e.g., assume different IAM roles and re-run kubectl auth can-i --list) to see what each IAM-mapped identity can do.
  • If non-admin IAM principals can perform cluster-admin-level actions (create clusterroles, clusterrolebindings, etc.) when they should not, that indicates a problem in your current combination of aws-auth mappings and RBAC.

Explanation of what kubectl cannot show:

  • kubectl cannot display or change the EKS Cluster Authentication Mode itself (EKS API vs ConfigMap); that setting is only visible and configurable via the AWS console/CLI/IaC at cluster creation time. Use the above commands to understand the effective access model and then review the cluster’s Authentication Mode manually in the AWS console as described in the remediation.
Automation
#!/usr/bin/env bash
# Report EKS Cluster Access Manager / authentication mode state
# Run on: any machine with kubectl and AWS CLI configured

set -euo pipefail

# Optional: restrict to a single region by setting AWS_REGION beforehand
: "${AWS_REGION:=}"

echo "=== Detecting EKS clusters and their authentication mode ===" >&2

# Get all clusters (optionally per-region if AWS_REGION is set)
if [ -n "${AWS_REGION}" ]; then
clusters=$(aws eks list-clusters --region "$AWS_REGION" --output text --query 'clusters[]')
else
# All regions
regions=$(aws ec2 describe-regions --output text --query 'Regions[].RegionName')
clusters=""
for r in $regions; do
c=$(aws eks list-clusters --region "$r" --output text --query 'clusters[]' || true)
if [ -n "$c" ]; then
for name in $c; do
clusters+="${r}:${name}"$'\n'
done
fi
done
fi

if [ -z "${clusters:-}" ]; then
echo "No EKS clusters found." >&2
exit 0
fi

printf "%-20s %-40s %-20s %-30s %-10s %-10s\n" "REGION" "CLUSTER_NAME" "AUTH_MODE" "ACCESS_ENTRY_COUNT" "HAS_CM" "CM_MODE"

if [ -n "${AWS_REGION}" ]; then
# clusters is just names when a single region is used
for name in $clusters; do
region="$AWS_REGION"
mode=$(aws eks describe-cluster \
--region "$region" \
--name "$name" \
--query 'cluster.accessConfig.authenticationMode' \
--output text 2>/dev/null || echo "UNKNOWN")

# Count EKS Access Entries (only useful if mode is EKS_API or API_AND_CONFIG_MAP)
entry_count=$(aws eks list-access-entries \
--region "$region" \
--cluster-name "$name" \
--query 'length(accessEntries)' \
--output text 2>/dev/null || echo "0")

# Inspect aws-auth ConfigMap via kubectl (if this cluster context exists)
# Assumes kubeconfig has a context matching the cluster name
has_cm="NO"
cm_mode="N/A"
if kubectl config get-contexts -o name | grep -qx "$name"; then
ctx="$name"
if kubectl --context "$ctx" get configmap aws-auth -n kube-system >/dev/null 2>&1; then
has_cm="YES"
# Very simple heuristic: if mapRoles or mapUsers are non-empty, say "ACTIVE"
data=$(kubectl --context "$ctx" get configmap aws-auth -n kube-system -o jsonpath='{.data}' 2>/dev/null || echo "")
if echo "$data" | grep -qE 'mapRoles:|mapUsers:'; then
cm_mode="ACTIVE"
else
cm_mode="EMPTY"
fi
fi
fi

printf "%-20s %-40s %-20s %-30s %-10s %-10s\n" "$region" "$name" "$mode" "$entry_count" "$has_cm" "$cm_mode"
done
else
# clusters is region:name lines
while IFS=: read -r region name; do
[ -z "$region" ] && continue

mode=$(aws eks describe-cluster \
--region "$region" \
--name "$name" \
--query 'cluster.accessConfig.authenticationMode' \
--output text 2>/dev/null || echo "UNKNOWN")

entry_count=$(aws eks list-access-entries \
--region "$region" \
--cluster-name "$name" \
--query 'length(accessEntries)' \
--output text 2>/dev/null || echo "0")

has_cm="NO"
cm_mode="N/A"
if kubectl config get-contexts -o name | grep -qx "$name"; then
ctx="$name"
if kubectl --context "$ctx" get configmap aws-auth -n kube-system >/dev/null 2>&1; then
has_cm="YES"
data=$(kubectl --context "$ctx" get configmap aws-auth -n kube-system -o jsonpath='{.data}' 2>/dev/null || echo "")
if echo "$data" | grep -qE 'mapRoles:|mapUsers:'; then
cm_mode="ACTIVE"
else
cm_mode="EMPTY"
fi
fi
fi

printf "%-20s %-40s %-20s %-30s %-10s %-10s\n" "$region" "$name" "$mode" "$entry_count" "$has_cm" "$cm_mode"
done <<< "$clusters"
fi

Explanation of output and what indicates a problem (for review):

  • AUTH_MODE:

    • API_AND_CONFIG_MAP (or similar mixed modes) requires review: both EKS Access Entries and aws-auth are in play.
    • EKSAUTH/EKS_API-only or CONFIG_MAP-only are consistent with a single source, but must match your intended design.
  • ACCESS_ENTRY_COUNT:

    • If AUTH_MODE is EKS_API (or equivalent) and ACCESS_ENTRY_COUNT is 0, access via IAM/EKS API may be misconfigured or overly restrictive.
  • HAS_CM / CM_MODE:

    • If AUTH_MODE is EKS_API but HAS_CM=YES and CM_MODE=ACTIVE, there are legacy aws-auth mappings that should be reviewed and possibly removed.
    • If AUTH_MODE is CONFIG_MAP and HAS_CM=NO or CM_MODE=EMPTY, the cluster may not have any IAM principal mappings configured.

This script does not change any configuration; it only surfaces current state so you can manually decide whether the Cluster Authentication Mode and aws-auth usage match your security requirements.