Giving EKS Pods IAM Roles via IRSA using Terraform
How to use AWS IAM-Roles for Service Accounts to Assign Permissions to Kubernetes Pods on EKS using Terraform
Relevant Links:
IRSA stands for IAM Roles for Service Accounts. It sounds a bit vague when thinking about it from a pure IAM perspective, but it allows you to create specific roles that can be assumed by pods running on a Kubernetes (k8s) cluster. In the before times, pods running on the cluster would act like docker containers and be bound to the node's IAM role of which they were running on. You used to have to do some trickery as shown Here.
Now, you can easily add your own custom IAM roles and their subsequent policies to specific pods on a k8s cluster. For example, if you have 3 pods running on one node, each pod can have a specific role giving it specific permissions that are not limited to the node's role -- in fact, best practice now would dictate the node role should have very limited permissions, perhaps a simple SSM policy that allows logging in directly to the node for troubleshooting.
See below for a simple diagram of what this looks like:
In a nutshell, when you use IRSA, you are creating a role that can be assumed by a pod. How does this work? Basically an OIDC provider is created, in the background. An IAM role is created, with a specific pod-policy attached. The role specifies the principal as A federated OIDC provider that was created for you. This role can only be assumed by a k8s service account (SA). That SA is annotated in K8s with the specific IAM role name.
All of this is taken care of for you in the background, and EKS does the hard work behind the scenes of figuring out the mapping between the Annotated SA and which pods are using that service account. Once everything is created, you should see the following from running:
kubectl get sa [service-account-name]
So how do we implement this in Terraform? We use the this Terraform Module. This module makes everything incredibly easy for creating the proper IAM resources needed to deploy your IRSA role. The actual tying of it to the pods should be done via a helm chart, but all that usually involves is setting the proper annotations for the EKS service account. The module conveniently outputs the role arn, so you can reference it in other places in Terraform.
Take a look at the following piece of code.
- It references the module name and source
- It references the role name to be created. This can be anything
- It gives the full URL of the OIDC provider. This can be retrieved from your cluster in Terraform, or if you cluster was created outside of Terraform in EKS, it can be retrieved from the console (or in code, of course)
- It references the local role policies with role_policy_arns. This is a Terraform list or set of IAM policies. You must use their full ARN's.
- It sets the qualified subjects to assume that role. This will be your service account name, prefixed by the type.
As mentioned before, all you need to do is reference this module's iam_role_arn output in Terraform wherever your annotations are being set for your service accounts, then ensure your pods are set to use that service account.
You'll know you did it correctly if you check your pods yaml file and see the following env variables:
Please check out my GitHub github.com/hrmcardle0 for other examples.
Thank you for reading.