#!/usr/bin/env bash
#
# Audit EKS RBAC identities vs AWS IAM integration
# Run from: any machine with kubectl + aws CLI access to the cluster
# Requires: kubectl, aws, jq, base64
set -euo pipefail
# CONFIG: set your AWS region and EKS cluster name
AWS_REGION="us-east-1"
EKS_CLUSTER_NAME="my-eks-cluster"
echo "=== 1) AWS CLI version check ==="
aws --version || { echo "aws CLI not found in PATH"; exit 1; }
AWS_CLI_VERSION_RAW="$(aws --version 2>&1 | awk '{print $1}' | cut -d/ -f2)"
echo "Detected aws CLI version: ${AWS_CLI_VERSION_RAW}"
# Very small version comparator: returns 0 if v1 >= 1.16.156 or any v2+
ver_ge() {
# args: MAJOR.MINOR.PATCH MINOR_TH PATCHTH
local major="${1%%.*}"
local rest="${1#*.}"
local minor="${rest%%.*}"
local patch="${rest#*.}"
local t_major="$2" t_minor="$3" t_patch="$4"
if (( major > t_major )); then return 0; fi
if (( major < t_major )); then return 1; fi
if (( minor > t_minor )); then return 0; fi
if (( minor < t_minor )); then return 1; fi
if (( patch >= t_patch )); then return 0; fi
return 1
}
AWS_CLI_MAJOR="${AWS_CLI_VERSION_RAW%%.*}"
if [[ "$AWS_CLI_MAJOR" -ge 2 ]]; then
echo "OK: aws CLI v2 is in use; IAM Authenticator is not required."
else
if ver_ge "$AWS_CLI_VERSION_RAW" 1 16 156; then
echo "OK: aws CLI v1.${AWS_CLI_VERSION_RAW#1.} >= 1.16.156; IAM Authenticator is not required."
else
echo "POTENTIAL ISSUE: aws CLI is < 1.16.156. If you rely on aws eks get-token,"
echo "you should either upgrade aws CLI or ensure aws-iam-authenticator is used correctly."
fi
fi
echo
echo "=== 2) Identify likely EKS cluster from kubeconfig ==="
CURRENT_CTX="$(kubectl config current-context)"
echo "Current kubectl context: ${CURRENT_CTX}"
echo
echo "=== 3) Inspect current-context exec auth configuration ==="
kubectl config view -o json \
| jq --arg ctx "$CURRENT_CTX" '
.contexts[] | select(.name == $ctx) | .context.user as $userName
| {context: $ctx, userName: $userName}
'
echo
kubectl config view -o json \
| jq --arg ctx "$CURRENT_CTX" '
.contexts[] | select(.name == $ctx) | .context.user as $userName
| {userName: $userName}
as $u
| . as $root
| $root.users[]
| select(.name == $u.userName)
| {userName: .name, user: .user}
'
cat <<'EOF'
INTERPRETATION:
- If the 'user' block under the current context shows:
"exec": {
"apiVersion": "client.authentication.k8s.io/v1beta1",
"command": "aws",
"args": ["eks", "get-token", ...]
then authentication is using aws CLI, which is acceptable when tied to IAM identities.
- If the exec command is 'aws-iam-authenticator', authentication is via the AWS IAM Authenticator binary,
which is also acceptable when configured correctly.
- POTENTIAL PROBLEMS:
* No 'exec' section at all (e.g., using a static token, basic auth, or a client certificate not bound to IAM).
* 'exec' uses a non-AWS command (custom script / external OIDC token not backed by IAM),
which may mean RBAC users are not tied directly to AWS IAM identities.
EOF
echo "=== 4) Discover RBAC subjects that look like IAM identities ==="
echo "Collecting ClusterRoles/ClusterRoleBindings/RoleBindings..."
# Gather all RBAC bindings and show subjects
kubectl get clusterrolebinding,rolebinding --all-namespaces -o json \
| jq '
.items[]
| {
kind: .kind,
name: .metadata.name,
namespace: .metadata.namespace,
subjects: (.subjects // [])
}
'
cat <<'EOF'
INTERPRETATION:
- In EKS, subjects that map IAM to Kubernetes RBAC typically look like:
* kind: User
name: "arn:aws:iam::<ACCOUNT-ID>:user/..."
* kind: User
name: "arn:aws:iam::<ACCOUNT-ID>:role/..."
* kind: Group
name: "system:masters" (mapped via aws-auth ConfigMap from IAM entities)
- POTENTIAL PROBLEMS:
* Subjects with arbitrary usernames (e.g. "alice", "bob") not corresponding to IAM ARNs.
* Client-certificate subjects mapped directly to ClusterRoleBindings (kind: User) with non-IAM names.
* Service accounts are expected for in-cluster workloads, but *human* or external users
should normally be IAM identities mapped via the aws-auth ConfigMap.
EOF
echo "=== 5) Inspect aws-auth ConfigMap for IAM-to-RBAC mappings ==="
if kubectl get configmap aws-auth -n kube-system >/dev/null 2>&1; then
kubectl get configmap aws-auth -n kube-system -o yaml
else
echo "POTENTIAL ISSUE: aws-auth ConfigMap not found in kube-system namespace."
echo "This may indicate no explicit IAM role/user to RBAC mappings are configured."
fi
cat <<'EOF'
INTERPRETATION OF aws-auth:
- Under data.mapRoles and data.mapUsers you should see YAML entries like:
- rolearn: arn:aws:iam::<ACCOUNT-ID>:role/SomeRole
username: some-k8s-username
groups:
- system:masters
- some-other-group
- These entries show which IAM roles/users map into Kubernetes RBAC groups.
- POTENTIAL PROBLEMS:
* No mapRoles/mapUsers at all, but cluster access is granted via static kubeconfig
users unrelated to IAM.
* mapRoles/mapUsers names that imply shared or generic identities (e.g., "admin", "poweruser")
without clear IAM ownership and least privilege.
EOF
echo "=== 6) Optional: list who can get tokens using aws CLI on this machine ==="
echo "This does NOT enumerate all cluster users, only what the current AWS identity can do."
aws sts get-caller-identity --region "${AWS_REGION}"
aws eks describe-cluster \
--name "${EKS_CLUSTER_NAME}" \
--region "${AWS_REGION}" \
--query 'cluster.{name:name,arn:arn,endpoint:endpoint,version:version}'
cat <<'EOF'
HOW TO SPOT PROBLEMS OVERALL:
- You are NOT aligned with the benchmark intent if:
* Human/admin access uses static certificates, static bearer tokens, or generic local users
in kubeconfig instead of aws eks get-token or aws-iam-authenticator.
* Kubernetes RBAC bindings (ClusterRoleBindings/RoleBindings) primarily reference
non-IAM usernames for humans (e.g., "admin", "jane", "ops-user") that are not
IAM ARNs mapped via aws-auth.
* The aws-auth ConfigMap is missing or nearly empty while significant access
is granted to non-IAM users.
- The benchmark is BETTER satisfied when:
* All human/admin kubectl access authenticates via AWS IAM (aws eks get-token
or aws-iam-authenticator), and
* RBAC grants permissions to identities that originate from IAM roles/users
mapped through aws-auth.
NOTE:
- This script only reports; it does NOT change configuration.
- Use its output to decide:
* Whether to move non-IAM users to IAM-backed authentication, and
* Whether to adjust aws-auth mappings and RBAC bindings.
EOF