Explain the difference between IAM roles, policies, and instance profiles. How would you implement least-privilege access for a microservices architecture on EKS?
Quick Answer
Roles define WHO can assume permissions, policies define WHAT actions are allowed, instance profiles attach roles to EC2 instances. For EKS, use IRSA (IAM Roles for Service Accounts) to give each pod its own IAM role.
Detailed Answer
IAM Concepts
- IAM Policy: A JSON document defining permissions (Allow/Deny on specific Actions for specific Resources). Policies alone do nothing — they must be attached to an identity.
- IAM Role: An identity that can be assumed by trusted entities (EC2, Lambda, EKS pods, other accounts). Unlike users, roles have no permanent credentials — they use temporary STS tokens.
- Instance Profile: A container for an IAM role that's attached to an EC2 instance. The instance's metadata service (169.254.169.254) provides temporary credentials.
EKS Least-Privilege with IRSA (IAM Roles for Service Accounts)
Without IRSA, all pods on a node share the node's IAM role — a single compromised pod can access all permissions. IRSA solves this:
1. Create an IAM OIDC provider for the EKS cluster 2. Create per-service IAM roles with trust policy referencing the Kubernetes ServiceAccount 3. Annotate the Kubernetes ServiceAccount with the IAM role ARN 4. Pod gets its own credentials via projected service account token (not instance metadata)
Best Practices
- One IAM role per microservice, scoped to exactly what it needs - Use IAM policy conditions: aws:RequestedRegion, aws:ResourceTag, kms:ViaService - Deny by default, allow explicitly - Use AWS Access Analyzer to identify unused permissions and tighten policies - Rotate to short-lived credentials (IRSA tokens expire in 12 hours by default) - Block IMDS access from pods to prevent credential theft from node role
Code Example
# IRSA: Terraform for per-service IAM role
resource "aws_iam_role" "order_service" {
name = "eks-order-service"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.eks.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"${var.oidc_issuer}:sub" = "system:serviceaccount:orders:order-service"
}
}
}]
})
}
# Kubernetes ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: order-service
namespace: orders
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/eks-order-serviceInterview Tip
IRSA is the answer Amazon interviewers want for EKS security. Show you understand the OIDC trust chain and why it's superior to node-level IAM roles. Mention blocking IMDS from pods as an extra security measure.