How to assign AWS IAM Role to Service Account with Terraform?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
On Amazon EKS, the standard way to give a pod AWS permissions is to bind an IAM role to a Kubernetes service account through IRSA, short for IAM Roles for Service Accounts. With Terraform, you model the trust policy, the IAM permissions, and the annotated Kubernetes service account so the whole setup is repeatable and reviewable.
Understand the IRSA Flow
IRSA works by letting the pod present a projected Kubernetes service account token to AWS. AWS then checks whether the IAM role trust policy allows that token issuer and that exact service account identity to assume the role.
At a high level, you need four pieces:
- An EKS cluster with an OIDC provider associated to it.
- An IAM policy describing the AWS permissions.
- An IAM role whose trust policy allows the target service account.
- A Kubernetes service account annotated with the IAM role ARN.
Build the Trust Policy in Terraform
A common pattern is to read the cluster identity and construct the trust relationship from that data.
Then create the role trust document for one namespace and one service account:
That sub condition is what ties the role to one exact service account identity.
Attach Permissions and Create the Role
Next, define the permissions the pod should receive:
This keeps the trust relationship separate from the permission policy, which makes later review easier.
Annotate the Kubernetes Service Account
Finally, create the service account with the IAM role annotation:
Pods that run with this service account can now assume the attached IAM role.
Verify the Configuration
After applying Terraform, confirm the service account annotation and test from a pod using that service account.
A useful runtime check from inside a pod is:
If IRSA is working, the returned identity should reflect the IAM role associated with the service account.
Common Pitfalls
The most common mistake is creating the IAM role but forgetting the cluster OIDC provider. Without that federated identity provider, the trust chain is incomplete.
Another issue is getting the sub claim wrong. The namespace and service account name must match exactly, including case.
People also attach the role to the service account correctly but forget to make the workload use that service account. The pod spec must reference the intended account.
Finally, do not give the role broader permissions than the workload needs. IRSA works best when each service account has a narrowly scoped role.
Summary
- IRSA links an IAM role to a Kubernetes service account in EKS.
- Terraform should manage the OIDC provider, trust policy, IAM role, and service account annotation together.
- The trust policy must match the exact
system:serviceaccountidentity. - Attach only the AWS permissions the workload actually needs.
- Verify the role from inside a pod with
aws sts get-caller-identity.

