Understanding IAM roles for service accounts, IRSA, on AWS EKS.
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.
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.
Below is a highly abstracted EKS cluster, inside which we have a
- 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
- 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,
- 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-
- 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 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,
- 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.
STS will issue security credentials for IAM Role ‘X’ to the 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.