Unlocking AWS Power for Microservices: A Guide to IAM Roles for Service Accounts (IRSA)

Unlocking AWS Power for Microservices: A Guide to IAM Roles for Service Accounts (IRSA)

What is iRSA?

IAM Roles for Service Accounts (IRSA) is a system that automates the provisioning and rotation of IAM temporary credentials, known as Web Identity tokens, which a Kubernetes ServiceAccount can utilize for making AWS API calls. With IRSA, you can grant AWS service permissions, such as S3, SES, and SNS, to your microservices application.

In this article, I will demonstrate how to set up IRSA in your environment.

Prerequisite -

  • AWS console admin access

  • Running EKS cluster

Configuration -

Create an IAM OIDC Identity Provider:

If you haven't already, create an OIDC identity provider for your EKS cluster using the AWS CLI:

eksctl utils associate-iam-oidc-provider --region <region> --cluster <cluster-name> --approve

Create an IAM Role:

Create an IAM role that your pods will assume. This role should have the necessary permissions to access AWS resources. You can do this using the AWS Management Console or AWS CLI.

aws iam create-role --role-name <role-name> --assume-role-policy-document file://eks-oidc-trust-policy.json

Here, eks-oidc-trust-policy.json is a JSON file containing a trust policy allowing your EKS cluster to assume this role. Replace <role-name> with your desired role name.

Example trust policy (eks-oidc-trust-policy.json):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<account-id>:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<eks-cluster-id>"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.<region>.amazonaws.com/id/<eks-cluster-id>:sub": "system:serviceaccount:<namespace>:<service-account-name>"
        }
      }
    }
  ]
}

Replace <account-id>, <region>, <eks-cluster-id>, <namespace>, and <service-account-name> with appropriate values.

Attach IAM Policies to the IAM Role:

Attach the necessary IAM policies to the IAM role you created in the previous step. These policies should grant permissions to access AWS resources like S3, RDS, etc., as needed by your Nginx pods.

aws iam attach-role-policy --role-name <role-name> --policy-arn <policy-arn>

Replace <role-name> with your role name and <policy-arn> with the ARN of the IAM policy you want to attach.

For example, here I am giving S3readonly policy -

aws iam attach-role-policy --role-name <role-name> --policy-arn <policy-arn>

Create a Kubernetes Service Account:

Create a Kubernetes service account in your EKS cluster, and annotate it with the IAM role ARN that you created earlier. This annotation informs EKS to associate the IAM role with the service account.

Create a YAML file, e.g., service-account.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/<role-name>
  name: poc-sa

Apply this configuration to your cluster:

kubectl apply -f service-account.yaml

Create Your Deployment:

Create a deployment or pod that uses the service account you created. Ensure that the serviceAccountName field in your pod specification references the service account you created earlier.

Here I am using a simple Ubuntu image to show an example, you can use whatever you like or based on your requirements.

Example Deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    name: ubuntu
  name: ubuntu
  namespace: poc
spec:
  replicas: 1
  selector:
    matchLabels:
      name: ubuntu
  template:
    metadata:
      labels:
        name: ubuntu
    spec:
      containers:
      - command:
        - /bin/bash
        - -c
        - |
          sleep 900000000
        image: ubuntu
        imagePullPolicy: Always
        name: ubuntu
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - SYS_ADMIN
            - NET_ADMIN
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        workingDir: /code
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: regcred
      restartPolicy: Always
      schedulerName: default-scheduler
      serviceAccount: poc-sa
      serviceAccountName: poc-sa

Deploy your app:

kubectl apply -f deployment.yaml

Test Your Configuration:
To test the configuration login inside the pod and install awscli -

apt update ; apt install awscli -y

after installation is complete, run the following command -

aws s3 ls s3://<bucket name>

If previous configurations are correct it should display the object listing from your bucket.

Troubleshooting -
While creating a role and policy if you are making any mistakes you can get the following error -

An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity

If you are facing the same issue, please recheck arn, account-id, and cluster-id.

That's it! You've set up an app deployment with IRSA configuration in Amazon EKS. Your app pods will now have the necessary AWS permissions to access resources based on the IAM policies attached to the IAM role associated with the service account.

If still facing any errors please feel free to drop a comment.

Thanks

Did you find this article valuable?

Support Abhishek Singh by becoming a sponsor. Any amount is appreciated!