Understanding IAM roles for service accounts, IRSA, on AWS EKS.

Ankit Wal
4 min readJul 9, 2022

Ankit is a Lead Platform Engineer at Thoughtworks, you can follow him on Linkedin and Medium. Views expressed are personal and do not represent those of his employer.

A simple visual explanation of how IRSA works to help you understand and remember.

The What and and Why

IRSA is the AWS EKS native way to allow applications running in EKS pods to access AWS API, using permissions configured in AWS IAM roles. It’s an improvement over the previous architecture of applications running in pods to use the IAM roles of the underlying EKS nodes. Being able to configure access to AWS API per service account tends towards the principle of least privilege, and more secure architecture.

The How

IRSA ties together elements from AWS IAM, OpenID Connect, K8s Service Accounts and Pods. Naturally it has a few moving parts that cut across the above concepts. Below is a simplified explanation of how various parts and configuration come together to allow applications running in a pod to use an IAM role.

The Setup

Below is a highly abstracted EKS cluster, inside which we have a

Pod ‘A’ and Service Account ‘SA’ with annotation pointing to a IAM Role ‘X’
  • Pod ‘A’, where our application is running,
  • Service Account ‘SA’, which describes via an annotation that it wants to use IAM Role ‘X’

In turn, shown below, the IAM Role ‘X’ has a trust relationship that points to

AWS IAM Trust Relationship pointing to the K8s OIDC Provider and Service Account
  • the K8s Service Account ‘SA’ that can assume that role.
  • the K8s OIDC Provider of the EKS Cluster

We want to configure Pod ‘A’ to use IAM Role ‘X’

Service Accounts and Service Accounts Tokens

When we create a Service Account in EKS, it also creates a Service Account Token,

Service account ‘SA’ comes withs a JWT service account token, stored in secret ‘SA’.
  • this Service Account Token is stored as a K8s Secret in the same namespace,
  • the token itself a is JWT, a Json Web Token.

Attaching the Service Account to the Pod

When we configure the Pod to use a Service Account, or in other words, attach a Service Account to a Pod, EKS does a couple of things-

ENV Vars and Token ‘SA-T’ injected into Pod ‘A’
  • the service account JWT, stored in the secret, is volume mounted into the Pod,
  • the following ENV VARs are injected into Pod
AWS_ROLE_ARN=<IAM ROLE ARN>
AWS_WEB_IDENTITY_TOKEN_FILE=<PATH TO SERVICE ACCOUNT TOKEN>

This is important, as now our application running inside the Pod has (via env vars, and volume mounts) access to

  • AWS_ROLE_ARN, the IAM Role ‘X’ ARN it should use, and
  • AWS_WEB_IDENTITY_TOKEN_FILE, the token it should use to try to assume the above role.

The assume role request

The AWS SDK, that runs with your application inside the pod knows to look at these ENV VARS for config.

It will send a request to AWS STS, requesting to assume the IAM Role ‘X’, and send the service account ‘SA’ JWT in that request.

The application in Pod ‘A’ requests AWS STS to allow it to assume IAM Role ‘X’

The request will contain

  • the ARN of IAM Role ‘X’
  • the JWT of Service Account ‘SA’

AWS STS will use the config in the Trust Relationship of IAM Role ‘X’ such that,

AWS STS validates the JWT
  • Get required keys and config form the trusted OIDC Discovery endpoint to ensure the presented service account JWT is valid and issued by the trusted cluster’s OIDC Provider
  • Ensure that the Service Account ‘SA’ is trusted to assume the IAM Role ‘X’.

This is possible because the K8s uses JWT standards for service account tokens and exposes an OIDC Discovery endpoints that allows third parties, like STS, to validate the JWTs.

On Success

STS will issue security credentials for IAM Role ‘X’ to the application in Pod ‘A’.

STS issues credentials for IAM Role ‘X’ to application in Pod ‘A’

Effectively ‘attaching’ IAM Role ‘X’ to Pod ‘A’ that is configured to use Service Account ‘SA’.

Fin. Thank you for reading.

Note: The terms EKS and K8s are used interchangeably, and the various sub-components/controllers are abstracted.

--

--