IAM Roles for Service Accounts with EKS (IRSA) .. Good bye AWS Credentials

Maha Amer
4 min readDec 29, 2022

--

In Kubernetes version 1.12, support was added for a new ProjectedServiceAccountToken feature, which is an OIDC JSON web token that also contains the service account identity. The IAM roles for service accounts feature is available on Amazon EKS Kubernetes version 1.16 or higher.

Instead of creating and distributing your AWS credentials to the containers or using the Amazon EC2 instance’s role, you can associate an IAM role with a Kubernetes service account. The applications in a Kubernetes pod container can then use an AWS SDK or the AWS CLI to make API requests to authorized AWS services.

Unlike kube2iam or kiam, IRSA is the official AWS way to authenticate pods to AWS API.

IRSA, is a system that automates provisioning of IAM credentials that a Kubernetes ServiceAccount can use to call AWS APIs.

With only three steps demonstrate how to set up IRSA on an EKS cluster :

Step 1. Create an OIDC identity provider

Create an OpenID Connect (OIDC) identity provider for your EKS cluster using the eksctl utils command:

eksctl version 0.124.0 or later

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

Step 2. Create an IAM role with policy and K8s service account

Once you have the IAM OIDC Provider associated with the cluster, to create a IAM role bound to a service account

eksctl create iamserviceaccount --cluster=<clusterName> --name=<serviceAccountName> --namespace=<serviceAccountNamespace> --attach-policy-arn=<policyARN>

You can specify --attach-policy-arn multiple times to use more than one policy.By default, it will be created in default namespace, but you can specify any other namespace. If the namespace doesn’t exist already, it will be created.

eksctl create iamserviceaccount --cluster=<clusterName> --name=s3-read-only --namespace=s3-app --attach-policy-arn=arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --approved

##OUTPUT
2022-12-28 22:57:54 [ℹ] 5 existing iamserviceaccount(s) (kube-system/cluster-autoscaler,kube-system/ebs-csi-controller-sa,staging/get-sqs-irsa,staging/get-ssm-param,staging/get-ssm-params) will be excluded
2022-12-28 22:57:54 [ℹ] 1 iamserviceaccount (s3-app/s3-read-only) was included (based on the include/exclude rules)
2022-12-28 22:57:54 [!] serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2022-12-28 22:57:54 [ℹ] 1 task: {
2 sequential sub-tasks: {
create IAM role for serviceaccount "s3-app/s3-read-only",
create serviceaccount "s3-app/s3-read-only",
} }2022-12-28 22:57:54 [ℹ] building iamserviceaccount stack "eksctl-staging-addon-iamserviceaccount-s3-app-s3-read-only"
2022-12-28 22:57:54 [ℹ] deploying stack "eksctl-staging-addon-iamserviceaccount-s3-app-s3-read-only"
2022-12-28 22:57:54 [ℹ] waiting for CloudFormation stack "eksctl-staging-addon-iamserviceaccount-s3-app-s3-read-only"
2022-12-28 22:58:25 [ℹ] waiting for CloudFormation stack "eksctl-staging-addon-iamserviceaccount-s3-app-s3-read-only"
2022-12-28 22:58:25 [ℹ] created namespace "s3-app"
2022-12-28 22:58:25 [ℹ] created serviceaccount "s3-app/s3-read-only"

Step 3. Associate service account to your deployment

Service account already exists with on your cluster. However, it is still neccessary to associate the service account to your deployment.

Verify that your service account exists using kubectl describe:

kubectl describe serviceaccount s3-read-only -n s3-app

Note that the Amazon Resource Name (ARN) of the IAM role that you created set as an annotation for the service account.

Verify that the AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN environment variables exist for your K8s deployment or pod using kubectl describe :

# Note the deployment name
kubectl -n s3-app describe deployment <deployment name>

Oh.. How that happens ? Let’s discover How it works

How IRSA works

EKS has an admission controller that injects AWS session credentials into pods based on the annotation on the Service Account used by the pod,

the controller will create automatically following environment variables in the k8s pod manifest:

  • AWS_STS_REGIONAL_ENDPOINTS set to regional by default, tells the SDK to use the current region endpoint to issue STS API calls
  • AWS_DEFAULT_REGION and AWS_REGION set to the region in which the cluster is running
  • AWS_ROLE_ARN set to the ARN of the IAM role you specified in the eks.amazonaws.com/role-arn service-account annotation
  • AWS_WEB_IDENTITY_TOKEN_FILE contains the path where is stored the Kubernetes service account token. This token will be used to get temporary STS credentials (usually set to /var/run/secrets/eks.amazonaws.com/serviceaccount/token inside the pod )

When AWS clients or SDKs connect to an AWS API, they detect an AssumeRoleWithWebIdentity security token to assume the IAM role

Amazon EKS OIDC discovery endpoint per cluster containing the signing keys for the ProjectedServiceAccountToken JSON web tokens so IAM, can validate and accept the Kubernetes-issued OIDC tokens.

OIDC federation access allows you to assume IAM roles via the Secure Token Service (STS), enabling authentication with an OIDC provider, receiving a JSON Web Token (JWT), which in turn can be used to assume an IAM role.

Kubernetes, on the other hand, can issue so-called projected service account tokens, which happen to be valid OIDC JWTs for pods. Our setup equips each pod with a cryptographically-signed token that can be verified by STS against the OIDC provider of your choice to establish the pod’s identity.

Next … Part 2: IAM Roles for Service Accounts with EKS (IRSA) using Terraform

References

--

--

Maha Amer
Maha Amer

Written by Maha Amer

I am passionate about Cloud Computing development, I've been working as Site Reliability Engineer and architect/design SWVL/Capiter infrastructure system

No responses yet