Working with Cross-Account AWS IAM Roles for EKS Service Accounts (IRSA)

Table of Contents

Introduction

Amazon EKS ia a managed Kubernetes platform. If your app running in an EKS pod needs to access AWS services like S3, it needs AWS credentials (access keys). The ideal way to provide access keys to an app is to use short-lived credentials that auto-renew periodically by assuming an IAM role, instead of using long-lived access keys of an IAM user.

You could attach the necessary IAM permissions to the EKS node’s IAM role (instance profile) & let the pod assume this role to get the AWS access it needs. But this would allow all other pods on that EKS node, access to those AWS services as well, even if they don’t need it. Enter IRSA! By assigning IAM roles to individual Kubernetes service accounts, you limit the scope of those permissions to just the pods using the service account.

Cross-Account IRSA

This works great when the AWS service you need, is in the same AWS account as your EKS cluster. But when that’s not the case, you must handle the cross-account role assumption yourself, in your app. Moreover, when IRSA credentials expire, EKS auto-renews them. But when the cross-account role credentials expire, you must renew them in your app. This article describes a simpler way to auto-renew credentials while still abstracting away the renewal from the app.

Python App in EKS

Consider a typical Python app. To call AWS APIs, you would use Boto3 as follows:

import boto3
s3 = boto3.client('s3')
# Call S3 APIs...

If this is a long-running app in EKS & it needs to access AWS services in another AWS account, first you create an IRSA & attach it to this pod’s service account. The IRSA only needs permission to assume the IAM role in the other account. That IAM role should of course allow it to be assumed by the IRSA. Once this setup is out of the way, you have 2 choices on where to assume the cross-account role:

  • Either assume the role just before starting the app in the container’s entrypoint script
  • Or assume the role inside the app’s Python code

Assume Role in App Environment

In the first case for example, your entrypoint script might look like this:

#!/usr/bin/env bash

aws sts assume-role --output yaml --role-session-name "$SESSION" \
--role-arn "arn:aws:iam::$ACCOUNT:role/$ROLE" > credentials.yaml

export AWS_ACCESS_KEY_ID=$(yq .Credentials.AccessKeyId credentials.yaml)
export AWS_SECRET_ACCESS_KEY=$(yq .Credentials.SecretAccessKey credentials.yaml)
export AWS_SESSION_TOKEN=$(yq .Credentials.SessionToken credentials.yaml)

rm credentials.yaml
# Start Python app...

Auto-Refresh Credentials

In both cases however, the app must keep an eye on the expiry of the cross-account role & renew its credentials periodically. Instead of custom building this logic, here’s a clever way to do it:

from boto3 import Session
from botocore.credentials import create_assume_role_refresher
from botocore.credentials import DeferredRefreshableCredentials

session = Session()
session._session._credentials = DeferredRefreshableCredentials(
  method = 'sts-assume-role',
  refresh_using = create_assume_role_refresher(
    session.client('sts'),
    {
      'RoleSessionName': RoleSessionName,
      'RoleArn': RoleARN,
    },
  ),
)

s3 = session.client('s3')
# Call S3 APIs...

You can now continue to use the S3 / Boto client as usual. The role credentials will renew automatically as long as the app is running!

Conclusion

This article explored how to setup cross-account IAM role access for EKS pods. We also addressed the challenge of keeping credentials fresh. Note that for security reasons, AWS does not auto-renew credentials in such cases, as it does for credentials of an EKS node role or EC2 instance profile. If the app needs them, it should renew credentials itself.

About the Author ✍🏻

Harish KM is a Principal DevOps Engineer at QloudX & a top-ranked AWS Ambassador since 2020. 👨🏻‍💻

With over a decade of industry experience as everything from a full-stack engineer to a cloud architect, Harish has built many world-class solutions for clients around the world! 👷🏻‍♂️

With over 20 certifications in cloud (AWS, Azure, GCP), containers (Kubernetes, Docker) & DevOps (Terraform, Ansible, Jenkins), Harish is an expert in a multitude of technologies. 📚

These days, his focus is on the fascinating world of DevOps & how it can transform the way we do things! 🚀

Leave a Reply

Your email address will not be published. Required fields are marked *