AWS IRSA
This guide covers creating and configuring IAM roles for Kubernetes workloads running on EKS. IRSA enables your pods to securely access AWS services without managing static credentials.
How IRSA Works
IRSA uses OpenID Connect (OIDC) federation to allow Kubernetes service accounts to assume IAM roles:
EKS exposes an OIDC provider endpoint for your cluster
IAM trusts tokens issued by this OIDC provider
Pods use projected service account tokens to authenticate
AWS STS exchanges these tokens for temporary IAM credentials
This eliminates the need for long-lived access keys and provides fine-grained, pod-level access control.
Prerequisites
EKS cluster with OIDC provider configured (enabled by default on new clusters)
IAM permissions to create roles and policies
Your cluster's OIDC provider URL (found in the EKS console or via
aws eks describe-cluster)
Creating an IAM Role
Step 1: Get Your OIDC Provider Information
Step 2: Create the IAM Trust Policy
Create a trust policy that allows the service account to assume the role. Replace the placeholders with your values:
💡 Multiple Service Accounts
To allow multiple service accounts to assume the same role, use
StringLikewith a wildcard pattern:Use this carefully - it grants access to all service accounts in the namespace.
Step 3: Create the IAM Role
Step 4: Attach Policies to the Role
Attach the required policies for your application's AWS access:
Step 5: Configure Your Application
Add the role ARN annotation to your ServiceAccount configuration:
Common IAM Policies
AWS Secrets Manager (Read-Only)
For applications using External Secrets to fetch secrets:
S3 Bucket Access
For applications that need to read/write to S3:
SQS Queue Access
For ScaledJobs processing SQS messages:
DynamoDB Table Access
🔒 Least Privilege
Always scope policies to specific resources using ARNs rather than wildcards (
*). This limits the blast radius if credentials are compromised.
Terraform Example
If you manage infrastructure with Terraform, here's a complete example:
Troubleshooting
Pod Cannot Assume Role
Error: An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation
Verify the trust policy includes the correct OIDC provider ARN
Check the service account name and namespace in the trust policy condition match exactly
Ensure the
audcondition is set tosts.amazonaws.comVerify the ServiceAccount annotation matches the role ARN exactly
Access Denied to AWS Resources
Error: An error occurred (AccessDenied) when calling the <Action> operation
Verify the IAM policy is attached to the role
Check resource ARNs in the policy match your actual resources
Ensure the policy actions include all required permissions
Check for any SCPs (Service Control Policies) that might be blocking access
Token Expired or Invalid
Error: ExpiredTokenException or InvalidIdentityToken
Ensure the OIDC provider is correctly configured in IAM
Verify the EKS cluster OIDC issuer URL matches the IAM OIDC provider
Check that the pod's service account token is being projected correctly
Debugging in Argo CD
Check Pod Logs:
Navigate to your application in the Argo CD UI
Expand the application tree to find your Pod
Click on the Pod resource
Select the Logs tab to view container output
Look for AWS SDK errors or authentication failures
Check ServiceAccount Configuration:
In the application tree, click on the ServiceAccount resource
Select the Live Manifest tab
Verify the
eks.amazonaws.com/role-arnannotation is present and correct
Check Pod Environment:
Click on the Pod resource
Select the Live Manifest tab
Look for the
AWS_ROLE_ARNandAWS_WEB_IDENTITY_TOKEN_FILEenvironment variables (injected automatically)Verify the projected service account token volume is mounted
Check Events:
Click on the Pod or Deployment resource
Select the Events tab
Look for warnings related to service account tokens or IAM authentication
Best Practices
🔒 Security Recommendations
One role per application: Create dedicated roles for each workload to isolate permissions
Use specific resource ARNs: Avoid wildcards in resource specifications
Namespace scoping: Include the namespace in trust policy conditions
Regular audits: Review and remove unused roles and policies
Use conditions: Add additional conditions (e.g., source IP, MFA) where appropriate
Tag resources: Tag IAM roles with application and team identifiers for cost allocation and auditing
Related Documentation
PGT Application Deployment - ServiceAccount configuration
PGT Secrets - Using IRSA with External Secrets
PGT CronJob - ServiceAccount for scheduled jobs
PGT ScaledJob - ServiceAccount for event-driven jobs
Azure Workload Identity - Azure equivalent
Last updated
Was this helpful?
