All IAM policy templates
AWS IAM policy template • EKS

EKS IRSA (IAM Roles for Service Accounts)

Bind a pod's ServiceAccount to an IAM role via OIDC — no long-lived node-wide credentials.

Policy

Replace the placeholder ARNs (YOUR-BUCKET-NAME, ACCOUNT_ID, REGION, etc.) with your real resource identifiers before use.

{
  "TrustPolicy": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.REGION.amazonaws.com/id/OIDC_ID"
        },
        "Action": "sts:AssumeRoleWithWebIdentity",
        "Condition": {
          "StringEquals": {
            "oidc.eks.REGION.amazonaws.com/id/OIDC_ID:sub": "system:serviceaccount:YOUR-NAMESPACE:YOUR-SERVICE-ACCOUNT",
            "oidc.eks.REGION.amazonaws.com/id/OIDC_ID:aud": "sts.amazonaws.com"
          }
        }
      }
    ]
  },
  "IdentityPolicy": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "ScopedToWhatThisWorkloadNeeds",
        "Effect": "Allow",
        "Action": [
          "s3:GetObject"
        ],
        "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
      }
    ]
  }
}

Why it's scoped this way

  • The trust-policy StringEquals condition on both :sub and :aud is what makes IRSA scoped — without it, any pod in the cluster (any namespace, any service account) using that OIDC provider could assume the role.
  • :sub is namespace-and-service-account-specific — a common mistake is matching only the namespace, which lets every ServiceAccount in that namespace assume the role.
  • The identity policy is a second, independent least-privilege boundary: even a correctly-scoped trust policy is only as safe as the permissions attached to the role.

Hardening it further

  • Never fall back to attaching this policy to the EC2 node-instance role instead — that grants every pod scheduled on that node the same access, defeating the point of IRSA.
  • Rotate/audit OIDC provider thumbprints per AWS guidance; a stale thumbprint can silently stop validating.

Paste your finished policy into the free AI-Powered IAM analyzer to catch anything you loosened while filling it in.

Related templates

Check your finished policy — free

Shieldly's AI-Powered analyzer flags privilege-escalation paths, wildcards, and risky PassRole in seconds. No signup, no AWS credentials. Also ships as CLI, VS Code extension, GitHub Action, and CDK Guard.

Amazon Web Services (AWS) is a trademark of Amazon.com, Inc. Shieldly is not affiliated with, endorsed by, or sponsored by Amazon Web Services.