IAM Roles for Service Accounts IRSA Lab

Provision an OpenID Connect (OIDC) identity provider, map an AWS IAM Role to a Kubernetes Service Account, and verify access using a test Pod.

Prerequisites

  • An active Amazon EKS cluster.
  • kubectl, eksctl, and aws CLI tools configured and authenticated.

Step 1: Associate an OIDC Provider

EKS clusters have an OIDC issuer URL. You must associate an IAM OIDC provider with this cluster so IAM can validate the tokens generated by Kubernetes.

Bash
# Replace <cluster-name> and <region> with your cluster details
export CLUSTER_NAME="eks-cluster"
export AWS_REGION="us-east-1"

eksctl utils associate-iam-oidc-provider \
    --cluster $CLUSTER_NAME \
    --region $AWS_REGION \
    --approve

Step 2: Create an AWS IAM Policy

Create a policy that defines the exact AWS permissions the Pod requires. In this lab, we will grant read-only access to Amazon S3.

Bash
cat <<EOF > s3-readonly-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "*"
        }
    ]
}
EOF

# Create the policy and capture the ARN
POLICY_ARN=$(aws iam create-policy \
    --policy-name EKSS3ReadOnlyPolicy \
    --policy-document file://s3-readonly-policy.json \
    --query 'Policy.Arn' \
    --output text)

echo $POLICY_ARN

Step 3: Create the IAM Role and Kubernetes Service Account

This step creates an IAM role, attaches the policy from Step 2, and creates a Kubernetes Service Account annotated with the IAM Role ARN. It establishes the trust relationship.

Bash
eksctl create iamserviceaccount \
    --name s3-reader-sa \
    --namespace default \
    --cluster $CLUSTER_NAME \
    --region $AWS_REGION \
    --attach-policy-arn $POLICY_ARN \
    --approve \
    --override-existing-serviceaccounts

Step 4: Deploy a Test Pod

Deploy an AWS CLI Pod configured to use the newly created Service Account (s3-reader-sa).

Bash
cat <<EOF > test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli-tester
  namespace: default
spec:
  serviceAccountName: s3-reader-sa
  containers:
  - name: aws-cli
    image: amazon/aws-cli:latest
    command: ["sleep", "3600"]
  restartPolicy: Never
EOF

kubectl apply -f test-pod.yaml

Wait for the Pod to be in the Running state:

Bash
kubectl get pods aws-cli-tester -w

Step 5: Verify IRSA Configuration

Exec into the Pod and verify that the AWS CLI is automatically picking up the injected web identity token.

1: Check the environment variables: Kubernetes automatically injects AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE when the Service Account is annotated.

    Bash
    kubectl exec -it aws-cli-tester -- env | grep AWS

    2: Verify Identity: Check which IAM role the Pod is assuming.

    Bash
    kubectl exec -it aws-cli-tester -- aws sts get-caller-identity

    Expected Output: The Arn should reflect the IAM role created in Step 3, not the worker node’s IAM role.

    3: Test S3 Access:

    Bash
    kubectl exec -it aws-cli-tester -- aws s3 ls

    Expected Output: A list of S3 buckets in your account.

    4: Test Unauthorized Access (Validation): Attempt to create an S3 bucket to ensure the least privilege policy is enforced.

    Bash
    kubectl exec -it aws-cli-tester -- aws s3 mb s3://my-irsa-test-bucket-12345

    Expected Output: AccessDenied error.

      Step 6: Teardown

      Remove the resources to avoid any ongoing configuration drift or clutter.

      Bash
      kubectl delete -f test-pod.yaml
      
      eksctl delete iamserviceaccount \
          --name s3-reader-sa \
          --namespace default \
          --cluster $CLUSTER_NAME \
          --region $AWS_REGION
      
      aws iam delete-policy --policy-arn $POLICY_ARN
      rm s3-readonly-policy.json test-pod.yaml

      Leave a Comment

      Your email address will not be published. Required fields are marked *

      Scroll to Top