AWS IAM Roles for Service Accounts (IRSA) With Terraform
Introduction
In today’s world that is cloud-native, Kubernetes is the go-to framework for container orchestration. Amazon Elastic Kubernetes Service (EKS) gives you a managed Kubernetes service to use without having to install and operate your own Kubernetes control plane or nodes on AWS. Among the key features of EKS is IAM Roles for Service Accounts (IRSA) which offer temporarily limited access rights to AWS resources from pods running in a Kubernetes cluster. In this post, we will take a look at what IRSA means, why it matters, and how it can be implemented using Terraform.
What is IRSA?
IRSA stands for “IAM Roles for Service Accounts.” It’s a feature in Amazon Web Services (AWS) that allows you to associate an AWS Identity and Access Management (IAM) role with a Kubernetes service account.
Key Features of IRSA:
- Associating IAM Roles: IRSA enables you to associate an IAM role directly with a Kubernetes service account. This means that the pods running within a specific Kubernetes namespace and using that service account can assume the IAM role.
- Secure Access to AWS Resources: With IRSA, your applications running in Kubernetes can securely access AWS resources. This access is granted based on the IAM role permissions, eliminating the need to hardcode AWS access credentials within your application configuration.
Why IRSA?
Improved Security:
IRSA helps to improve the security posture of your Kubernetes workloads by avoiding the need to store AWS credentials within the pods. Instead, the pods assume IAM roles that have the necessary permissions to access AWS resources.
Granular Permissions:
IRSA allows you to grant fine-grained permissions to specific pods based on their service accounts. This minimizes the blast radius in case of a security incident.
Simplified Credential Management:
Managing AWS credentials becomes much simpler with IRSA. You no longer need to manage and rotate long-lived AWS access keys within your Kubernetes cluster.
Setting Up IRSA with Terraform
Now, let’s dive into how you can set up IRSA for your EKS cluster using Terraform.
Prerequisites:
- An existing EKS cluster.
- Terraform installed.
Step-by-Step Guide:
Step 1: Enable OIDC Provider for EKS
First, you need to enable the OpenID Connect (OIDC) identity provider for your EKS cluster.
data "aws_eks_cluster" "default" {
name = "cluster-name"
}
data "tls_certificate" "default" {
url = data.aws_eks_cluster.default.identity[0].oidc[0].issuer
}
resource "aws_iam_openid_connect_provider" "default" {
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [data.tls_certificate.default.certificates[0].sha1_fingerprint]
url = data.aws_eks_cluster.default.identity[0].oidc[0].issuer
}
Step 2: Create an IAM Role
Create an IAM role that the service account can assume. The role should have a trust relationship with the OIDC provider.
resource "aws_iam_role" "default" {
name = "eks-irsa-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Sid = ""
Effect = "Allow",
Principal = {
Federated = aws_iam_openid_connect_provider.default.arn
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"${aws_iam_openid_connect_provider.default.url}:sub" = "system:serviceaccount:default:my-service-account"
"${aws_iam_openid_connect_provider.default.url}:aud" = "sts.amazonaws.com"
}
}
}]
})
}
resource "aws_iam_role_policy" "default" {
name = "eks-irsa-policy"
role = aws_iam_role.default.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Action = [
"s3:ListBucket",
"s3:GetObject"
],
Resource = "*"
}]
})
}
Step 3: Create a Kubernetes Service Account
Create a Kubernetes service account and annotate it with the IAM role ARN.
resource "kubernetes_service_account" "example" {
metadata {
name = "my-service-account"
namespace = "default"
annotations = {
"eks.amazonaws.com/role-arn" = aws_iam_role.default.arn
}
}
}
Step 4: Deploy a Pod using the Service Account
Create a Kubernetes deployment that uses the service account. This pod will assume the IAM role associated with the service account.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-name
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: app-name
template:
metadata:
labels:
app: app-name
spec:
serviceAccountName: my-service-account
containers:
- name: my-container
image: amazonlinux
command: ["/bin/bash", "-c", "aws s3 ls"]
Conclusion
IAM Roles for Service Accounts (IRSA) is a powerful feature that enhances the security and manageability of Kubernetes workloads on Amazon EKS. By associating IAM roles with Kubernetes service accounts, you can grant pods temporary, fine-grained access to AWS resources without hardcoding AWS credentials. This blog post has shown you how to set up IRSA using Terraform, enabling you to leverage this feature in your EKS clusters.
If you have any questions or feedback, feel free to comment.
About The Author
Suraj Solanki
Senior DevOps Engineer
LinkedIn: https://www.linkedin.com/in/suraj-solanki
Topmate: https://topmate.io/suraj_solanki