π Secure S3 Access from EKS Pod using IRSA (IAM Roles for Service Accounts)
Deliver Api needs s3 access to upload the customer invoices
To securely give your microservice in Amazon EKS access to S3 without using access keys or secret keys, use IAM Roles for Service Accounts (IRSA). This method enables your pod to assume an IAM role with defined permissions via a Kubernetes service account, eliminating the need to hardcode credentials.
β Step-by-Step Guide to Configure IRSA for S3 Access
π 1. Enable OIDC Provider for Your EKS Cluster
First, associate your EKS cluster with an IAM OIDC provider:
eksctl utils associate-iam-oidc-provider \
--region ap-south-1 \
--cluster <your-cluster-name> \
--approveπ 2. Create an IAM Policy for S3 Access
Define a policy that grants access to the required S3 bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": [
"arn:aws:s3:::tracemypods",
"arn:aws:s3:::tracemypods/*"
]
}
]
}Save this to a file (e.g., s3-access-policy.json) and create the policy via AWS CLI:
aws iam create-policy \
--policy-name tracemypods-invoices3-policy \
--policy-document file://tracemypods-invoices3-policy.jsonπ 3. Create IAM Role & Kubernetes Service Account with Policy
Create the Kubernetes service account and attach the IAM policy:
eksctl create iamserviceaccount \
--name tracemypods-invoices3-sa \
--namespace ai-assistant \
--cluster <your-cluster-name> \
--attach-policy-arn arn:aws:iam::<account-id>:policy/tracemypods-invoices3-policy \
--approve \
--override-existing-serviceaccountsThis command creates:
- A Kubernetes service account (
tracemypods-invoices3-sa) - An IAM role linked to it
- An OIDC trust relationship for secure role assumption
π 4. Annotate the Kubernetes Deployment
Update your deployment YAML to use the new service account:
Filename: deliverapi.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tracemypods-depliverapi # only this api need s3 bucket access to upload the invoices
spec:
replicas: 1
template:
spec:
serviceAccountName: tracemypods-invoices3-sa
containers:
- name: your-container
image: your-image[x] Terraform for IRSA
Filename: s3-sa.tf
# --------------------------------------------------------
# Terraform to setup IRSA for Deliver API in EKS
# --------------------------------------------------------
provider "aws" {
region = "ap-south-1"
}
# ------------------------------------------
# 1. Fetch OIDC provider from EKS Cluster
# ------------------------------------------
data "aws_eks_cluster" "cluster" {
name = var.cluster_name
}
data "aws_eks_cluster_auth" "cluster" {
name = var.cluster_name
}
resource "aws_iam_openid_connect_provider" "oidc" {
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [data.aws_eks_cluster.cluster.certificate_authority[0].data]
url = data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer
}
# ------------------------------------------
# 2. Create IAM Policy for S3 Access
# ------------------------------------------
resource "aws_iam_policy" "s3_access_policy" {
name = "tracemypods-invoices3-policy"
description = "Policy to allow Deliver API access to S3 bucket tracemypods"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = ["s3:*"]
Resource = [
"arn:aws:s3:::tracemypods",
"arn:aws:s3:::tracemypods/*"
]
}
]
})
}
# ------------------------------------------
# 3. Create IAM Role for Service Account
# ------------------------------------------
resource "aws_iam_role" "irsa_role" {
name = "tracemypods-invoices3-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = aws_iam_openid_connect_provider.oidc.arn
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}:sub" = "system:serviceaccount:ai-assistant:tracemypods-invoices3-sa"
}
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "attach_s3_policy" {
role = aws_iam_role.irsa_role.name
policy_arn = aws_iam_policy.s3_access_policy.arn
}
# ------------------------------------------
# 4. Create Kubernetes Service Account
# ------------------------------------------
resource "kubernetes_service_account" "irsa_sa" {
metadata {
name = "tracemypods-invoices3-sa"
namespace = "ai-assistant"
annotations = {
"eks.amazonaws.com/role-arn" = aws_iam_role.irsa_role.arn
}
}
}
# ------------------------------------------------------
# Variables
# ------------------------------------------------------
variable "cluster_name" {
description = "EKS cluster name"
type = string
}
# ------------------------------------------------------
# Output
# ------------------------------------------------------
output "irsa_role_arn" {
value = aws_iam_role.irsa_role.arn
}