test: Complete IRSA to Pod Identity migration - #746
Conversation
Spec for completing IRSA to EKS Pod Identity migration by removing the last remaining IRSA annotation from Thanos service account template. Documents platform-wide Pod Identity architecture, migration history, and why Pod Identity is the platform standard over IRSA. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
4-task plan for completing IRSA to Pod Identity migration: 1. Pre-migration verification (Pod Identity associations exist) 2. Remove IRSA annotation from Thanos service account 3. Create Pod Identity migration ADR documentation 4. Final validation and summary Each task has bite-sized steps (2-5 min) with exact commands and expected outputs following TDD-style verification. Refs: docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Pod Identity associations already exist in Terraform for all 5 Thanos service accounts (receiver, store, compact, ruler, ingester). The IRSA annotation is ignored by EKS when Pod Identity is active (Pod Identity takes precedence). This completes the platform's migration to Pod Identity as the single authentication mechanism for all AWS IAM workloads. Refs: docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Documents platform-wide Pod Identity architecture, migration timeline, and standard implementation patterns. - Why Pod Identity over IRSA (simpler, better debugging, tighter scope) - Migration history (Karpenter, Thanos, 30+ prior migrations) - Standard 4-step pattern (role, policy, association, ServiceAccount) - Reference implementations (simple, multi-SA, cross-account) - Debugging guide and CloudTrail visibility Refs: docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The karpenter-node-provisioning.md file exists on branch karpenter-pod-identity but not on main. Replace the link with a commit reference to avoid a broken link when this branch merges. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
📝 WalkthroughWalkthroughThe PR removes the remaining Thanos IRSA annotation and adds migration documentation, implementation patterns, credential-flow details, validation procedures, and rollback guidance for EKS Pod Identity. ChangesPod Identity migration
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
/test on-demand-e2e |
There was a problem hiding this comment.
Actionable comments posted: 17
🧹 Nitpick comments (1)
docs/design/pod-identity-migration.md (1)
1-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd explicit ADR decision sections.
This file is used as the platform architecture ADR, but it contains only Summary and Context sections. Add
Status,Decision,Alternatives,Consequences, and validation ownership. Explain how Terraform remains the CLM source of truth for cluster state and how the design keeps regions operationally independent.As per path instructions: “Review design decisions for ADR format compliance. Ensure decisions are well-justified and align with the regional architecture goals.” As per coding guidelines: “Maintain CLM as the single source of truth for cluster state. Keep regions operationally independent with minimal cross-region dependencies.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/design/pod-identity-migration.md` around lines 1 - 15, Expand the EKS Pod Identity Migration ADR with explicit Status, Decision, Alternatives, Consequences, and validation ownership sections. Document Terraform as the CLM source of truth for cluster state, justify Pod Identity over alternatives, and state how the design preserves regional operational independence with minimal cross-region dependencies.Sources: Coding guidelines, Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/design/pod-identity-migration.md`:
- Around line 17-25: The comparison table’s IRSA scope and CloudTrail claims are
inaccurate. In the table near the IRSA/Pod Identity rows, change IRSA Scope to
“Namespace + ServiceAccount” and qualify or substantiate the IRSA CloudTrail
Visibility entry instead of asserting “Only IAM role ARN.”
- Around line 203-212: Update the CloudTrail guidance in the “Check CloudTrail
for AssumeRole Events” section to list the actual EKS Pod Identity session-tag
names: eks-cluster-name, kubernetes-namespace, and kubernetes-service-account,
removing the eks: prefix and incorrect namespace/service-account keys.
- Around line 55-78: Harden the Pod Identity trust policy for
aws_iam_role.example by adding an aws:SourceOrgId condition using the platform
Organization ID. Apply the same condition to all Pod Identity role trust-policy
implementations, including the Zoa IAM and regional-cluster configurations, and
document any intentional exception.
- Around line 132-147: Update the Pod Identity sequence diagram and associated
runbook to replace the IRSA environment variables and AssumeRoleWithWebIdentity
flow with AWS_CONTAINER_CREDENTIALS_FULL_URI,
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, the injected token volume, and the EKS
Pod Identity Agent calling eks-auth:AssumeRoleForPodIdentity. Add CloudTrail
guidance to look up AssumeRoleForPodIdentity events from eks-auth.amazonaws.com,
while documenting sts:AssumeRole as a separate event.
In `@docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md`:
- Line 316: Remove the premature four-backtick Markdown fence near the embedded
document in the plan, preserving the outer markdown fence that begins earlier
and the intended closing fence at the later document boundary. Ensure the
embedded content remains inside the outer fence so the later fence is parsed
correctly.
- Around line 561-564: Update the expected-output code fence near the clean
working-tree output to specify the text language, changing the unlabeled fence
to a text-labeled fence while preserving its contents.
- Line 448: Update the Pod Identity session-tag documentation to use the actual
EKS tag names: replace eks:eks-cluster-name, eks:namespace, and
eks:service-account-name with eks-cluster-name, kubernetes-namespace, and
kubernetes-service-account, respectively, so IAM policy condition examples
reference the correct keys.
- Around line 369-384: Update the credential-flow diagram and related validation
steps to use the EKS Pod Identity Agent and EKS Auth AssumeRoleForPodIdentity
flow. Replace IRSA-specific webhook injection, AWS_ROLE_ARN,
AWS_WEB_IDENTITY_TOKEN_FILE, and STS AssumeRoleWithWebIdentity references with
AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE,
and update CloudTrail checks to query AssumeRoleForPodIdentity instead of
AssumeRole.
- Around line 56-64: Update Step 1 to validate the target cluster rather than
only grepping Terraform source: verify all five live Pod Identity associations,
confirm the eks-pod-identity-agent is ready, restart a Thanos pod, and verify
the Thanos image uses a supported AWS SDK with the default credential chain. For
credential validation, check AWS_CONTAINER_CREDENTIALS_FULL_URI and
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, and do not use the IRSA-specific
AWS_ROLE_ARN or AWS_WEB_IDENTITY_TOKEN_FILE variables.
- Around line 253-261: Update the comparison table’s Scope row to state that
IRSA supports exact namespace-and-ServiceAccount restrictions via the OIDC sub
condition, rather than “Namespace-level.” Revise the CloudTrail Visibility row
to accurately describe fields supported by the deployed configuration, including
that Pod Identity session tags are configurable and may be disabled; do not
imply IRSA lacks CloudTrail auditing.
- Around line 293-315: Update the example aws_iam_role trust policy to either
add a parameterized aws:SourceOrgId condition, consistently applying it to
corresponding role policies, or document why the unconditioned trust is
intentional. If retaining it, document the aws:RequestTag/kubernetes-namespace
and aws:RequestTag/kubernetes-service-account restrictions and their
tighter-scoping purpose near the policy example.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md`:
- Around line 169-183: Update the pod identity migration design’s diagrams and
validation steps to consistently describe the EKS Pod Identity flow: use
AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE,
the EKS Pod Identity Agent, and AssumeRoleForPodIdentity via the EKS Auth API.
Remove references to AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, and
AssumeRoleWithWebIdentity from all affected sections, and validate the container
credential variables and agent-based retrieval instead.
- Around line 302-313: Update the “Pre-Deployment” validation steps in the Pod
Identity migration design to query aws eks list-pod-identity-associations for
active target-cluster associations instead of relying on Terraform state, verify
the eks-pod-identity-agent is Ready on every node, and create a fresh pod using
the affected ServiceAccount to confirm AWS_CONTAINER_CREDENTIALS_FULL_URI,
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, and a successful AWS API call before
removing IRSA. Remove the incorrect AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE
checks.
- Around line 184-185: Update the deployment flow in the pod identity migration
design to remove the unsupported claims that ArgoCD applies the ServiceAccount
without annotation and triggers a pod restart. Revise the statements around the
ServiceAccount application and the related lines 193–198 to describe the actual
rollout mechanism, including the required Deployment change or explicit restart
hook that causes existing Thanos pods to restart.
- Around line 453-457: Update the IRSA comparisons in both security sections to
state that IRSA can scope roles to an exact namespace and service account
through the OIDC sub condition, while aud only constrains the intended audience.
Qualify the CloudTrail audit claim to account for Pod Identity session tags
being disabled and IRSA audit details varying with the configured event and
trust policy.
- Around line 487-505: Add a StringEquals condition for aws:SourceOrgId equal to
aws:ResourceOrgId within the assume_role_policy Statement of
aws_iam_role.example, preserving the existing pod service principal and actions.
- Around line 30-35: Update the Assumptions section to require the EKS Pod
Identity Agent add-on for standard clusters, noting that only supported EKS Auto
Mode clusters manage it automatically. Add prerequisites for the
eks-auth:AssumeRoleForPodIdentity permission, EKS Auth API connectivity, and a
supported AWS SDK in the Thanos image for every target cluster; replace the
AWS_WEB_IDENTITY_TOKEN_FILE credential check with
AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
checks.
---
Nitpick comments:
In `@docs/design/pod-identity-migration.md`:
- Around line 1-15: Expand the EKS Pod Identity Migration ADR with explicit
Status, Decision, Alternatives, Consequences, and validation ownership sections.
Document Terraform as the CLM source of truth for cluster state, justify Pod
Identity over alternatives, and state how the design preserves regional
operational independence with minimal cross-region dependencies.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 132567bc-75d7-4ebd-a6ab-5f8f0eb147f9
📒 Files selected for processing (4)
argocd/config/regional-cluster/thanos/templates/serviceaccount.yamldocs/design/pod-identity-migration.mddocs/superpowers/plans/2026-08-12-complete-pod-identity-migration.mddocs/superpowers/specs/2026-08-12-pod-identity-migration-design.md
💤 Files with no reviewable changes (1)
- argocd/config/regional-cluster/thanos/templates/serviceaccount.yaml
| | Aspect | IRSA | Pod Identity | | ||
| | ------------------------- | -------------------------------------------- | ------------------------------------- | | ||
| | **Terraform** | OIDC provider, tls_certificate, tls provider | Just role + association | | ||
| | **Service Account** | Annotation with role ARN | No annotation needed | | ||
| | **Helm Values** | Must inject role ARN from Terraform | No Helm values needed | | ||
| | **Trust Policy** | Complex OIDC conditions (issuer, aud, sub) | Simple `pods.eks.amazonaws.com` | | ||
| | **Debugging** | Trace annotation → values → Terraform | `kubectl describe pod` shows env vars | | ||
| | **Scope** | Namespace-level | Namespace + ServiceAccount | | ||
| | **CloudTrail Visibility** | Only IAM role ARN | Pod namespace, SA, cluster name | |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
file="$(fd -t f -p 'docs/design/pod-identity-migration.md' . | head -n 1)"
printf 'FILE=%s\n' "$file"
wc -l "$file"
ast-grep outline "$file"
sed -n '1,80p' "$file"Repository: openshift-online/rosa-hyperfleet
Length of output: 3224
🌐 Web query:
AWS EKS Pod Identity versus IRSA scope exact namespace service account sub trust policy CloudTrail session context fields
💡 Result:
AWS EKS Pod Identity and IAM Roles for Service Accounts (IRSA) are both methods for granting IAM permissions to EKS workloads, but they differ fundamentally in architecture, configuration, and scoping mechanisms [1][2][3]. Scope and Trust Policy Structure IRSA relies on an OIDC provider associated with the specific EKS cluster [3]. The trust policy for an IRSA-enabled role explicitly binds the role to a Kubernetes service account in a specific namespace using a string match on the OIDC provider's 'sub' claim [2]. Because the OIDC issuer URL is cluster-specific, IRSA roles often require per-cluster trust policy updates [1][3]. EKS Pod Identity uses a centralized EKS-managed credential broker (the pods.eks.amazonaws.com service principal) [1][2][3]. The trust policy is configured once to trust this service principal and can be reused across any number of EKS clusters without modification [1][3]. Scoping is enforced by EKS Pod Identity associations managed through the EKS API, which maps a role to a namespace and service account [1][4]. You can further restrict this role in the trust policy using Attribute-Based Access Control (ABAC) by checking the session tags injected by EKS [5][6]. CloudTrail Session Context When analyzing CloudTrail logs, the visibility of the requester differs: IRSA: Requests are made directly by the pod using STS AssumeRoleWithWebIdentity [2]. The userIdentity field in CloudTrail reflects the OIDC provider and the assumed role session, but it does not natively include the structured namespace/service-account tags found in Pod Identity events [2]. EKS Pod Identity: The EKS Auth service performs the AssumeRole operation on behalf of the pod [7]. Consequently, CloudTrail logs show calls to AssumeRoleForPodIdentity (or similar) [7]. The sessionContext contains session tags (e.g., kubernetes-namespace, kubernetes-service-account, eks-cluster-name) [6][7]. These fields allow administrators to definitively identify the exact namespace and service account triggering the request within the CloudTrail event metadata [7]. Summary of Key Differences - Trust Model: IRSA uses OIDC federation (cluster-specific trust) [2][3]. EKS Pod Identity uses a service-principal-based trust policy (reusable across clusters) [1][3]. - Configuration: IRSA requires a ServiceAccount annotation [8]. EKS Pod Identity uses an explicit association object (no annotation required) [4][2]. - Scoping: IRSA scoping is hard-coded in the trust policy's 'sub' condition [2]. EKS Pod Identity scoping is managed by the EKS association and verified via session tags [5][6].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 2: https://www.systemshardening.com/articles/cross-cutting/aws-irsa-workload-identity/
- 3: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 6: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html
- 7: https://kloudvin.com/article/eks-irsa-to-pod-identity-migration-fine-grained-access/
- 8: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
Correct the IRSA scope comparison.
Replace Namespace-level with Namespace + ServiceAccount. IRSA can bind a role to an exact namespace and service account through the OIDC sub condition. Qualify or substantiate the CloudTrail row because Only IAM role ARN is too absolute.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/design/pod-identity-migration.md` around lines 17 - 25, The comparison
table’s IRSA scope and CloudTrail claims are inaccurate. In the table near the
IRSA/Pod Identity rows, change IRSA Scope to “Namespace + ServiceAccount” and
qualify or substantiate the IRSA CloudTrail Visibility entry instead of
asserting “Only IAM role ARN.”
Source: MCP tools
| ### 1. IAM Role with Pod Identity Trust Policy | ||
|
|
||
| ```hcl | ||
| resource "aws_iam_role" "example" { | ||
| name = "${var.cluster_id}-example" | ||
|
|
||
| assume_role_policy = jsonencode({ | ||
| Version = "2012-10-17" | ||
| Statement = [{ | ||
| Effect = "Allow" | ||
| Principal = { | ||
| Service = "pods.eks.amazonaws.com" | ||
| } | ||
| Action = [ | ||
| "sts:AssumeRole", | ||
| "sts:TagSession" | ||
| ] | ||
| }] | ||
| }) | ||
|
|
||
| tags = { | ||
| Name = "${var.cluster_id}-example" | ||
| } | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- target document ---'
sed -n '1,130p' docs/design/pod-identity-migration.md
printf '%s\n' '--- related trust-policy and SourceOrgId references ---'
rg -n -C 3 'pods\.eks\.amazonaws\.com|SourceOrgId|assume_role_policy|Pod Identity' --glob '*.tf' --glob '*.md' .Repository: openshift-online/rosa-hyperfleet
Length of output: 50393
🌐 Web query:
AWS EKS Pod Identity trust policy aws:SourceOrgId pods.eks.amazonaws.com official documentation
💡 Result:
AWS recommends using the global condition key aws:SourceOrgId in the trust policy for IAM roles used with EKS Pod Identity to prevent the cross-service confused deputy problem [1][2]. By including this condition, you ensure that the IAM role can only be assumed when the request originates from an AWS service principal acting on behalf of an account within your specified AWS Organization [1][2]. The following example illustrates how to incorporate aws:SourceOrgId into the trust policy for the pods.eks.amazonaws.com service principal [1]: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:SourceOrgId": "o-xxxxxxxxxx" } } } ] } In this policy, you replace o-xxxxxxxxxx with your actual AWS Organization ID [1]. When EKS Pod Identity assumes the role, it passes the Organization ID associated with the cluster's account as the value for aws:SourceOrgId, which is then validated against your policy [1]. Beyond aws:SourceOrgId, you can also use other condition keys such as aws:SourceArn (to restrict to a specific cluster) or session tags (to restrict to specific Kubernetes namespaces or service accounts) to further refine access control [3][4][1].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html
- 2: https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 4: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- Terraform IAM roles and Pod Identity associations ---'
rg -l 'aws_iam_role|aws_eks_pod_identity_association' terraform | head -80
printf '%s\n' '--- trust-policy implementations ---'
rg -n -C 12 'assume_role_policy|pods\.eks\.amazonaws\.com' terraform --glob '*.tf' | head -240
printf '%s\n' '--- relevant design-document sections ---'
sed -n '130,520p' docs/design/pod-identity-migration.mdRepository: openshift-online/rosa-hyperfleet
Length of output: 22898
Harden all Pod Identity trust policies.
Add aws:SourceOrgId with the platform Organization ID to the reference policy and Pod Identity role implementations, including terraform/modules/zoa/iam.tf and terraform/config/regional-cluster/main.tf. Document any intentional exception.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/design/pod-identity-migration.md` around lines 55 - 78, Harden the Pod
Identity trust policy for aws_iam_role.example by adding an aws:SourceOrgId
condition using the platform Organization ID. Apply the same condition to all
Pod Identity role trust-policy implementations, including the Zoa IAM and
regional-cluster configurations, and document any intentional exception.
Source: MCP tools
| ```mermaid | ||
| sequenceDiagram | ||
| participant Pod as Application Pod | ||
| participant Webhook as Pod Identity Webhook<br/>(EKS-managed DaemonSet) | ||
| participant STS as AWS STS | ||
| participant S3 as AWS Service<br/>(S3, KMS, etc.) | ||
|
|
||
| Pod->>Webhook: Pod creation intercepted | ||
| Webhook->>Webhook: Find aws_eks_pod_identity_association<br/>matching namespace + SA | ||
| Webhook->>Pod: Inject env vars:<br/>AWS_ROLE_ARN<br/>AWS_WEB_IDENTITY_TOKEN_FILE<br/>AWS_REGION | ||
| Pod->>Pod: AWS SDK reads env vars | ||
| Pod->>STS: AssumeRoleWithWebIdentity | ||
| STS-->>Pod: Temporary credentials | ||
| Pod->>S3: API call with temp creds | ||
| S3-->>Pod: Response | ||
| ``` |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
file=$(fd -t f -i '^pod-identity-migration\.md$' . | head -n 1)
printf 'FILE=%s\n' "$file"
wc -l "$file"
sed -n '1,240p' "$file"
printf '\n--- related identity terms ---\n'
rg -n -i 'webhook|IRSA|AssumeRoleWithWebIdentity|AssumeRoleForPodIdentity|AWS_CONTAINER|AWS_WEB_IDENTITY|pod identity agent|credential' "$file"Repository: openshift-online/rosa-hyperfleet
Length of output: 8943
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide EKS Pod Identity how it works AWS_CONTAINER_CREDENTIALS_FULL_URI AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE AssumeRoleForPodIdentity
💡 Result:
Amazon EKS Pod Identity simplifies credential management for applications running on EKS by providing temporary AWS credentials to pods via a local agent [1][2]. This mechanism is designed to be a simpler alternative to IAM Roles for Service Accounts (IRSA) and functions similarly to how EC2 instance profiles provide credentials to EC2 instances [1][2]. How it works: When a pod uses a service account with an EKS Pod Identity association, Amazon EKS injects specific environment variables and a volume mount into the pod container [1]. Environment Variables and Token Mount: 1. AWS_CONTAINER_CREDENTIALS_FULL_URI: This environment variable points to the local loopback address of the EKS Pod Identity Agent (e.g., http://169.254.170.23/v1/credentials) [1][3]. AWS SDKs use this URI to request temporary credentials from the agent [1]. 2. AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: This variable specifies the path to a file containing a Kubernetes service account token (/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token) [1][4]. This token is used to authenticate the pod's request to the agent [1]. Credential Retrieval Process: 1. When an AWS SDK within the pod needs credentials, it inspects these environment variables [1][2]. 2. The SDK sends a request to the EKS Pod Identity Agent using the AWS_CONTAINER_CREDENTIALS_FULL_URI, including the token from the file specified by AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE [1]. 3. The agent, running as a pod on the same node, receives the request and interacts with the EKS Auth API [1][3]. 4. The agent performs the AssumeRoleForPodIdentity action against the EKS Auth API to retrieve temporary AWS credentials [1][3]. Note that AssumeRoleForPodIdentity is an internal EKS Auth API operation that the node-level agent uses to securely exchange the pod's identity for AWS credentials [1][3]. 5. The EKS Auth service assumes the configured IAM role (using sts:AssumeRole) and returns the temporary credentials to the agent, which then passes them back to the pod's SDK [1][5][6]. This flow centralizes credential management and reduces the load on the AWS Security Token Service (STS) because the agent handles credential requests for all pods on a node, rather than each individual SDK in every pod making its own separate calls [2].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-configure-pods.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 6: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide EKS Pod Identity Agent webhook AssumeRoleForPodIdentity CloudTrail event
💡 Result:
The AssumeRoleForPodIdentity action is a specific API operation in the Amazon EKS Auth API that the Amazon EKS Pod Identity Agent uses to retrieve temporary credentials for workloads running on a node [1][2]. Key details regarding this action and its visibility in AWS CloudTrail: 1. Function: When a pod needs credentials, the EKS Pod Identity Agent on the node calls the AssumeRoleForPodIdentity operation [1]. This call is made using the node's IAM role, which must have permission to perform this action (typically granted by the AmazonEKSWorkerNodePolicy or a specific custom policy) [3][2][4]. 2. CloudTrail Visibility: Because AssumeRoleForPodIdentity is an API call to the Amazon EKS Auth API (not the AWS STS API), it is logged in AWS CloudTrail under the Amazon EKS service (events with the service name eks-auth.amazonaws.com or associated with EKS API logging) [1][5]. This allows administrators to audit which nodes and workloads are requesting credentials [6]. 3. Distinction from STS: It is important to distinguish this from the actual assumption of the pod's IAM role. The EKS Auth service itself performs the sts:AssumeRole and sts:TagSession calls when it processes the request from the agent to provide the final temporary credentials to the pod [7][8]. Consequently, you will see AssumeRoleForPodIdentity events in CloudTrail attributed to the node role, while the sts:AssumeRole events (if logged for the role being assumed) will show the EKS service (pods.eks.amazonaws.com) as the principal [7][8]. 4. Webhook context: While there is a Kubernetes mutating webhook involved in configuring pods to use EKS Pod Identity (often named pod-identity-webhook), this webhook is a Kubernetes-level component that injects the necessary environment variables and volume mounts into the pod [9][6]. It does not perform the AssumeRoleForPodIdentity call itself; that is the responsibility of the EKS Pod Identity Agent daemonset running on the node [1][6].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/security-iam-awsmanpol.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/logging-using-cloudtrail.html
- 6: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 7: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 8: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 9: https://docs.aws.amazon.com/eks/latest/userguide/addon-id-troubleshoot.html
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html mutating webhook EKS Pod Identity Agent AWS_CONTAINER_CREDENTIALS_FULL_URI CloudTrail AssumeRoleForPodIdentity
💡 Result:
The EKS Pod Identity Agent facilitates secure credential delivery to pods through an automated process involving environment variable injection and the AssumeRoleForPodIdentity API action [1]. When a pod is associated with an EKS Pod Identity, the Amazon EKS control plane injects specific configuration into the pod manifest, typically during the pod creation process [1]. This includes setting the following environment variables: - AWS_CONTAINER_CREDENTIALS_FULL_URI: Set to http://169.254.170.23/v1/credentials, which points the AWS SDKs inside the container to the local EKS Pod Identity Agent running on the node [1]. - AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: Points to a mounted volume containing a service account token used to authorize the credential request [1]. Once the pod is scheduled, the EKS Pod Identity Agent on the node intercepts requests to the URI [1]. The agent then performs an AssumeRoleForPodIdentity call to the EKS Auth API to exchange the pod's service account token for temporary AWS security credentials [1]. This action is logged in CloudTrail as AssumeRoleForPodIdentity, allowing you to audit which IAM roles were assumed by which pods [1]. The agent then provides these temporary credentials back to the AWS SDK running within the container, enabling seamless authentication without requiring manual configuration of credentials [1].
Citations:
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide EKS Pod Identity CloudTrail lookup-events AssumeRoleForPodIdentity AssumeRole
💡 Result:
In Amazon EKS Pod Identity, the process involves two distinct actions that appear in AWS CloudTrail logs. It is important to distinguish between the API call made by the EKS Pod Identity Agent to retrieve credentials and the action performed by the EKS service to assume the IAM role on behalf of the pod [1][2][3]. 1. eks-auth:AssumeRoleForPodIdentity The Amazon EKS Pod Identity Agent running on your worker nodes calls the eks-auth:AssumeRoleForPodIdentity API to retrieve temporary credentials [1][4]. This action is logged in CloudTrail under the eks-auth service. You can search for these events in CloudTrail to audit which nodes are requesting credentials [2][5]. The worker node's IAM role must have permission to perform this action [4][6]. 2. sts:AssumeRole Once the EKS service receives the request, it performs an sts:AssumeRole action to assume the target IAM role configured in your Pod Identity association [3]. This action is logged in CloudTrail under the AWS STS service [3]. The IAM role being assumed must have a trust policy that allows the pods.eks.amazonaws.com principal to perform sts:AssumeRole and sts:TagSession [3]. To locate these events in CloudTrail: - To audit credential requests by nodes, filter by Event name: AssumeRoleForPodIdentity and Event source: eks-auth.amazonaws.com [4][5]. - To audit the actual role assumption by the EKS service, filter by Event name: AssumeRole and Event source: sts.amazonaws.com, specifically looking for events where the assumed role matches your Pod Identity role [3]. These events help verify that the agent is successfully requesting credentials and that the EKS service is correctly assuming the assigned IAM roles [2][7].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/security-iam-awsmanpol.html
- 6: https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html
- 7: https://docs.aws.amazon.com/eks/latest/userguide/addon-id-troubleshoot.html
Correct the Pod Identity diagram and runbook.
EKS injects AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, and the token volume. The EKS Pod Identity Agent serves the credential endpoint and calls eks-auth:AssumeRoleForPodIdentity. Replace the IRSA variables and AssumeRoleWithWebIdentity flow. Add a CloudTrail lookup for AssumeRoleForPodIdentity from eks-auth.amazonaws.com; sts:AssumeRole remains a separate event.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/design/pod-identity-migration.md` around lines 132 - 147, Update the Pod
Identity sequence diagram and associated runbook to replace the IRSA environment
variables and AssumeRoleWithWebIdentity flow with
AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, the
injected token volume, and the EKS Pod Identity Agent calling
eks-auth:AssumeRoleForPodIdentity. Add CloudTrail guidance to look up
AssumeRoleForPodIdentity events from eks-auth.amazonaws.com, while documenting
sts:AssumeRole as a separate event.
Source: MCP tools
| ### Check CloudTrail for AssumeRole Events | ||
|
|
||
| ```bash | ||
| aws cloudtrail lookup-events \ | ||
| --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \ | ||
| --max-results 10 | ||
| ``` | ||
|
|
||
| Pod Identity events include `eks:eks-cluster-name`, `eks:namespace`, `eks:service-account-name` in | ||
| session tags. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target excerpt ---'
sed -n '180,225p' docs/design/pod-identity-migration.md
printf '%s\n' '--- session-tag references ---'
rg -n -C 3 'eks-cluster-name|kubernetes-namespace|kubernetes-service-account|session tags|session tags|AssumeRole' docs/design/pod-identity-migration.mdRepository: openshift-online/rosa-hyperfleet
Length of output: 2890
🌐 Web query:
AWS EKS Pod Identity actual session tag names eks-cluster-name kubernetes-namespace kubernetes-service-account
💡 Result:
Amazon EKS Pod Identity automatically attaches six predefined session tags to the assumed IAM role session when an application requests credentials [1][2][3]. These tags are transitively passed, meaning they persist if the workload assumes further roles [1]. To reference these tags in IAM policies or trust policy conditions, you use the format ${aws:PrincipalTag/TagKey} [1]. The actual session tag names (keys) are as follows: - eks-cluster-arn [1][2] - eks-cluster-name [1][2] - kubernetes-namespace [1][2] - kubernetes-service-account [1][2] - kubernetes-pod-name [1][2] - kubernetes-pod-uid [1][2] When using these tags in trust policy conditions (e.g., to restrict which pods can assume a role), you use the aws:RequestTag/TagKey condition key [4]. For example, a condition for a namespace and service account would be: "Condition": { "StringEquals": { "aws:RequestTag/kubernetes-namespace": ["your-namespace"], "aws:RequestTag/kubernetes-service-account": ["your-service-account"] } } [4] If you encounter size limitations (e.g., PackedPolicyTooLarge errors), you can disable these automatic session tags for a specific EKS Pod Identity association by setting disableSessionTags to true [1][5].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html
- 2: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
- 3: https://computingforgeeks.com/amazon-eks-pod-identity-complete-guide/
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 5: https://docs.aws.amazon.com/eks/latest/APIReference/API_CreatePodIdentityAssociation.html
🏁 Script executed:
#!/bin/bash
set -eu
sed -n '180,225p' docs/design/pod-identity-migration.md
rg -n -C 3 'eks-cluster-name|kubernetes-namespace|kubernetes-service-account|session tags|AssumeRole' docs/design/pod-identity-migration.mdRepository: openshift-online/rosa-hyperfleet
Length of output: 2836
Use the actual EKS Pod Identity session-tag names.
Use eks-cluster-name, kubernetes-namespace, and kubernetes-service-account. Do not use the eks: prefix or the eks:namespace and eks:service-account-name keys.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/design/pod-identity-migration.md` around lines 203 - 212, Update the
CloudTrail guidance in the “Check CloudTrail for AssumeRole Events” section to
list the actual EKS Pod Identity session-tag names: eks-cluster-name,
kubernetes-namespace, and kubernetes-service-account, removing the eks: prefix
and incorrect namespace/service-account keys.
Source: MCP tools
| - [ ] **Step 1: Verify Pod Identity associations exist in Terraform** | ||
|
|
||
| Run: | ||
|
|
||
| ```bash | ||
| grep -A 5 "resource \"aws_eks_pod_identity_association\"" terraform/modules/thanos-infrastructure/main.tf | grep -E "thanos_receiver|thanos_store|thanos_compact|thanos_ruler|thanos_receive_ingester" | ||
| ``` | ||
|
|
||
| Expected output: 5 Pod Identity association resource blocks |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
file="docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md"
printf '%s\n' '--- target document ---'
sed -n '1,120p' "$file"
printf '%s\n' '--- pod identity references ---'
rg -n -i 'pod identity|aws eks|thanos|IRSA|AssumeRoleWithWebIdentity|trust policy|agent|SDK|rollback|validate|list-pod-identity' "$file"
printf '%s\n' '--- relevant repository files ---'
git ls-files | rg '(^|/)(main\.tf|.*thanos.*|.*pod.*identity.*|.*helm.*|.*deployment.*|.*daemonset.*)$' | head -200
printf '%s\n' '--- Terraform association and agent references ---'
rg -n -i 'aws_eks_pod_identity_association|pod-identity-agent|pod identity|thanos_receiver|thanos_store|thanos_compact|thanos_ruler|thanos_receive_ingester' terraform docs .github 2>/dev/null | head -300Repository: openshift-online/rosa-hyperfleet
Length of output: 50390
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide/pod-identities.html EKS Pod Identity Agent AWS SDK supported versions
💡 Result:
To use EKS Pod Identity, your application containers must use AWS SDK versions that support assuming an IAM role via the EKS Pod Identity Agent [1]. You must use the following minimum versions (or later) for your AWS SDKs: - Java (Version 2): 2.21.30 [1] - Java (Version 1): 1.12.746 [1] - Go v1: v1.47.11 [1] - Go v2: release-2023-11-14 [1] - Python (Boto3): 1.34.41 [1] - Python (botocore): 1.34.41 [1] - AWS CLI v1: 1.30.0 [1] - AWS CLI v2: 2.15.0 [1] - JavaScript v2: 2.1550.0 [1] - JavaScript v3: v3.458.0 [1] - Kotlin: v1.0.1 [1] - Ruby: 3.188.0 [1] - Rust: release-2024-03-13 [1] - C++: 1.11.263 [1] -.NET: 3.7.734.0 [1] - PowerShell: 4.1.502 [1] - PHP: 3.289.0 [1] Applications must use the default credential chain, which allows the SDK to automatically discover and use the credentials provided by the EKS Pod Identity Agent [2][3]. The agent runs as a DaemonSet on the node and provides these credentials via environment variables [2][3]. For the most current information, you should refer to the official AWS documentation on minimum SDK versions for EKS Pod Identity [1].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
🏁 Script executed:
#!/bin/bash
set -e
plan="docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md"
tf="terraform/modules/thanos-infrastructure/main.tf"
printf '%s\n' '--- plan validation/debugging sections ---'
sed -n '400,465p;620,650p' "$plan"
printf '%s\n' '--- Thanos associations and IAM trust ---'
sed -n '135,355p' "$tf"
printf '%s\n' '--- EKS Pod Identity agent addon configuration ---'
sed -n '135,190p' terraform/modules/eks-cluster/main.tf
printf '%s\n' '--- Thanos chart service accounts and images ---'
rg -n -C 4 'serviceAccount|image:|repository:|tag:|thanos_receiver|thanos_store|thanos_compact|thanos_ruler|thanos_receive_ingester' \
argocd/config/regional-cluster/thanos terraform/modules/thanos-infrastructure
printf '%s\n' '--- exact Markdown fences in the plan ---'
python3 - <<'PY'
from pathlib import Path
p = Path("docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md")
lines = p.read_text().splitlines()
fences = [(i+1, line) for i, line in enumerate(lines) if line.strip().startswith("```")]
print(f"fence_count={len(fences)}")
for item in fences:
print(item)
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 25190
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE AWS_CONTAINER_CREDENTIALS_FULL_URI Pod Identity
💡 Result:
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE and AWS_CONTAINER_CREDENTIALS_FULL_URI are environment variables automatically injected into Kubernetes Pods by Amazon EKS when an EKS Pod Identity association is configured for that Pod's service account [1]. These variables enable the AWS SDKs and tools within the container to retrieve temporary IAM credentials managed by the EKS Pod Identity Agent [1]. The mechanism functions as follows: 1. AWS_CONTAINER_CREDENTIALS_FULL_URI: This variable points to the local HTTP endpoint (typically http://169.254.170.23/v1/credentials) exposed by the EKS Pod Identity Agent running on the node [1]. The AWS SDK uses this URI to request temporary security credentials [1]. 2. AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: This variable points to the file path of a projected service account token (/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token) [1]. The AWS SDK reads this token from the file system and presents it to the EKS Pod Identity Agent to authorize the credential request [1]. By using these variables, the AWS SDK automatically authenticates with the local EKS Pod Identity Agent, which in turn calls the EKS Auth API's AssumeRoleForPodIdentity action to provide the container with the temporary credentials associated with the IAM role defined in the EKS Pod Identity configuration [1]. This process removes the need for manual credential configuration within the application code [1].
Citations:
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- Thanos image configuration ---'
rg -n -C 3 -i 'image|repository|tag|version|thanos' \
argocd/config/regional-cluster/thanos/values.yaml \
argocd/config/regional-cluster/thanos/templates/*.yaml \
argocd/config/regional-cluster/thanos/Chart.yaml \
argocd/config/regional-cluster/thanos-operator/values.yaml \
argocd/config/regional-cluster/thanos-operator/Chart.yaml
printf '%s\n' '--- Thanos CR and ServiceAccount names ---'
rg -n -C 5 -i 'serviceAccount|service-account|thanos-store|thanos-compact|thanos-ruler|thanos-receive|image' \
argocd/config/regional-cluster/thanos/templates/*.yaml \
argocd/config/regional-cluster/thanos/values.yaml
printf '%s\n' '--- all Pod Identity credential-variable references ---'
rg -n -i 'AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE|AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE|AWS_CONTAINER_CREDENTIALS_FULL_URI|grep AWS_' docs argocd terraform | head -150Repository: openshift-online/rosa-hyperfleet
Length of output: 32875
Validate the target cluster before removing the IRSA annotation.
The Terraform grep checks only source text. Verify all five live associations, eks-pod-identity-agent readiness, and a restarted Thanos pod. Confirm the Thanos image uses a supported AWS SDK and the default credential chain. Use AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE for the Pod Identity check; AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE are IRSA variables.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md` around
lines 56 - 64, Update Step 1 to validate the target cluster rather than only
grepping Terraform source: verify all five live Pod Identity associations,
confirm the eks-pod-identity-agent is ready, restart a Thanos pod, and verify
the Thanos image uses a supported AWS SDK with the default credential chain. For
credential validation, check AWS_CONTAINER_CREDENTIALS_FULL_URI and
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, and do not use the IRSA-specific
AWS_ROLE_ARN or AWS_WEB_IDENTITY_TOKEN_FILE variables.
Source: MCP tools
| ```mermaid | ||
| sequenceDiagram | ||
| participant Dev as Developer | ||
| participant Git as Git Repository | ||
| participant CI as CI Pipeline | ||
| participant ArgoCD as ArgoCD | ||
| participant K8s as Kubernetes API | ||
| participant PodID as Pod Identity Webhook | ||
| participant Pod as Thanos Pod | ||
|
|
||
| Dev->>Git: Push updated serviceaccount.yaml | ||
| Git->>CI: Trigger make pre-push | ||
| CI->>CI: helm-lint, prettier, terraform-validate | ||
| CI-->>Git: ✓ Validation passed | ||
| Git->>ArgoCD: Detect chart changes |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file="docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md"
printf '%s\n' '--- target sections ---'
sed -n '145,220p' "$file"
sed -n '350,405p' "$file"
printf '%s\n' '--- identity-related references ---'
rg -n -C 2 'IRSA|Pod Identity|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE|AWS_CONTAINER_CREDENTIALS_FULL_URI|AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE|AssumeRoleWithWebIdentity|AssumeRoleForPodIdentity|webhook|restart|Terraform state|credential' "$file"Repository: openshift-online/rosa-hyperfleet
Length of output: 17055
🌐 Web query:
AWS EKS Pod Identity how it works EKS Pod Identity Agent AWS_CONTAINER_CREDENTIALS_FULL_URI AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE AssumeRoleForPodIdentity official documentation
💡 Result:
Amazon EKS Pod Identity provides a secure, scalable mechanism for granting Kubernetes pods temporary IAM credentials to access AWS services [1][2]. It replaces the need to distribute static AWS credentials or rely on the node's IAM instance profile [2]. How it Works The process relies on an EKS-managed webhook, an EKS Auth API, and the EKS Pod Identity Agent [1][3]. 1. Association and Mutation: When you create an EKS Pod Identity association, you link an IAM role to a Kubernetes service account [2][4]. When a pod using that service account is scheduled, the EKS cluster's control plane automatically mutates the pod manifest, injecting specific environment variables and a projected volume containing a service account token [1][3]. 2. Credential Request: Inside the pod, the AWS SDK or CLI detects the environment variables and makes a request to the local EKS Pod Identity Agent, which runs as a DaemonSet on each node [1][3]. 3. Token Exchange (AssumeRoleForPodIdentity): The Agent takes the pod's service account token and calls the EKS Auth API's AssumeRoleForPodIdentity action [1][5]. The API validates the association and returns temporary AWS credentials [3][5]. 4. Credential Delivery: The Agent provides these temporary credentials back to the pod's application [1][3]. Key Components and Environment Variables - EKS Pod Identity Agent: A mandatory add-on that runs on each node [6][3]. It listens on a specific local IP (169.254.170.23 for IPv4) to intercept credential requests from pods [1][6]. - AWS_CONTAINER_CREDENTIALS_FULL_URI: Points to the local EKS Pod Identity Agent endpoint (http://169.254.170.23/v1/credentials) where the application's AWS SDK retrieves temporary credentials [1][3]. - AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: Specifies the path to a projected service account token file on the pod's filesystem, which is used to authorize the credential request [1][3][7]. - AssumeRoleForPodIdentity: An internal EKS Auth API action used exclusively by the EKS Pod Identity Agent to exchange a service account token for IAM credentials [5][8]. It requires the node's IAM role to have the eks-auth:AssumeRoleForPodIdentity permission [6]. For applications, the entire process is transparent: modern AWS SDKs and the AWS CLI automatically recognize these environment variables and handle the credential retrieval process without requiring code changes [1][8].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 3: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 5: https://docs.aws.amazon.com/eks/latest/APIReference/API_auth_AssumeRoleForPodIdentity.html
- 6: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
- 7: https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html
- 8: https://docs.aws.amazon.com/boto3/latest/reference/services/eks-auth/client/assume_role_for_pod_identity.html
Use the EKS Pod Identity credential flow in all diagrams and validation steps.
EKS Pod Identity does not use AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, or AssumeRoleWithWebIdentity. The EKS control plane injects configuration for the EKS Pod Identity Agent, which uses AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, then calls AssumeRoleForPodIdentity through the EKS Auth API. Validate the container credential variables and agent-based retrieval instead of the IRSA variables in all affected sections.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md` around
lines 169 - 183, Update the pod identity migration design’s diagrams and
validation steps to consistently describe the EKS Pod Identity flow: use
AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE,
the EKS Pod Identity Agent, and AssumeRoleForPodIdentity via the EKS Auth API.
Remove references to AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, and
AssumeRoleWithWebIdentity from all affected sections, and validate the container
credential variables and agent-based retrieval instead.
Source: MCP tools
| ArgoCD->>K8s: Apply ServiceAccount (no annotation) | ||
| ArgoCD->>K8s: Trigger pod restart (Deployment updated) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
file="docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md"
printf '%s\n' '--- target lines ---'
sed -n '160,210p' "$file"
printf '%s\n' '--- relevant terms and references ---'
rg -n -C 3 'ServiceAccount|pod restart|rollout|Deployment|ArgoCD|Thanos|Pod Identity|restart' "$file"
printf '%s\n' '--- repository references to the affected workload ---'
rg -n -C 2 'thanos|serviceAccountName|serviceAccount' docs charts deploy terraform .github 2>/dev/null | head -n 240Repository: openshift-online/rosa-hyperfleet
Length of output: 41530
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- candidate chart files ---'
fd -i 'thanos|serviceaccount|application' argocd/config/regional-cluster/thanos argocd/config/regional-cluster/thanos-operator terraform/modules/thanos-infrastructure 2>/dev/null | head -n 120
printf '%s\n' '--- chart structure ---'
find argocd/config/regional-cluster/thanos -maxdepth 3 -type f -print 2>/dev/null | sort
printf '%s\n' '--- ServiceAccount and workload references ---'
rg -n -C 4 'kind: (ServiceAccount|Deployment|StatefulSet|DaemonSet)|serviceAccount(Name)?|rollout|restart|reloader|checksum|sync-wave|hook' argocd/config/regional-cluster/thanos argocd/config/regional-cluster/thanos-operator 2>/dev/null
printf '%s\n' '--- Pod Identity associations ---'
rg -n -C 6 'aws_eks_pod_identity_association|service_account|thanos_' terraform/modules/thanos-infrastructure 2>/dev/nullRepository: openshift-online/rosa-hyperfleet
Length of output: 19379
🏁 Script executed:
#!/bin/bash
set -e
python3 - <<'PY'
from pathlib import Path
import re
spec = Path("docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md").read_text()
chart = Path("argocd/config/regional-cluster/thanos")
templates = "\n".join(p.read_text() for p in sorted((chart / "templates").glob("*.yaml")))
tf = Path("terraform/modules/thanos-infrastructure/main.tf").read_text()
print("spec_has_serviceaccount_restart_claim=", "Trigger pod restart (Deployment updated)" in spec)
print("chart_has_deployment_or_statefulset=", bool(re.search(r"kind:\s*(Deployment|StatefulSet|DaemonSet)", templates)))
print("chart_has_rollout_or_restart_hook=", bool(re.search(r"rollout|restart|argocd.argoproj.io/hook|sync-wave|checksum", templates, re.I)))
print("chart_serviceaccount_names=", re.findall(r"name:\s*\{\{\s*\.Values\.serviceAccount\.name\s*\}\}", (chart / "templates/serviceaccount.yaml").read_text()))
print("pod_identity_association_for_thanos_operator=", bool(re.search(
r'aws_eks_pod_identity_association"\s+"thanos_receiver".*?service_account\s*=\s*var\.thanos_service_account',
tf, re.S
)))
print("pod_identity_association_count=", len(re.findall(r'resource\s+"aws_eks_pod_identity_association"', tf)))
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 455
Correct the deployment flow
The chart has no Deployment rollout or ArgoCD restart hook. An ArgoCD sync that changes only the ServiceAccount does not restart existing Thanos pods. Correct the statements at lines 184–185 and 193–198.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md` around
lines 184 - 185, Update the deployment flow in the pod identity migration design
to remove the unsupported claims that ArgoCD applies the ServiceAccount without
annotation and triggers a pod restart. Revise the statements around the
ServiceAccount application and the related lines 193–198 to describe the actual
rollout mechanism, including the required Deployment change or explicit restart
hook that causes existing Thanos pods to restart.
Source: MCP tools
| **Pre-Deployment (required):** | ||
|
|
||
| 1. Verify Pod Identity associations exist in target cluster's Terraform state | ||
| 2. Run `make pre-push` to validate Helm chart renders correctly | ||
| 3. Check current ServiceAccount has IRSA annotation (to confirm what's being removed) | ||
|
|
||
| **Post-Deployment (monitoring):** | ||
|
|
||
| 1. Verify ServiceAccount updated with no annotation | ||
| 2. Confirm Pod Identity env vars injected (`AWS_ROLE_ARN`, `AWS_WEB_IDENTITY_TOKEN_FILE`) | ||
| 3. Monitor Thanos operator logs for successful AWS API calls (S3, KMS) | ||
| 4. Check Prometheus metrics for continued ingestion (no gaps) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file="docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md"
printf '%s\n' '--- target section ---'
sed -n '250,340p' "$file"
printf '%s\n' '--- relevant terms in the document ---'
rg -n -i \
'IRSA|Pod Identity|pod identity|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE|terraform state|association|agent|restart|reconcile|SDK|credential|Thanos' \
"$file"
printf '%s\n' '--- repository references to the migration and validation steps ---'
rg -n -i \
'pod.identity|Pod Identity|terraform state list|AWS_WEB_IDENTITY_TOKEN_FILE|AWS_ROLE_ARN|Thanos operator' \
--glob '!node_modules' --glob '!build' --glob '!dist' .Repository: openshift-online/rosa-hyperfleet
Length of output: 50390
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- Thanos Pod Identity resources ---'
rg -n -C 8 \
'aws_eks_pod_identity_association|thanos_(receiver|store|compact|ruler|receive_ingester)' \
terraform/modules/thanos-infrastructure terraform/config/regional-cluster
printf '%s\n' '--- Thanos ServiceAccount and workload templates ---'
fd -i 'serviceaccount.yaml|deployment.yaml|statefulset.yaml|daemonset.yaml|values.yaml' \
argocd/config/regional-cluster/thanos |
while read -r f; do
printf '\n--- %s ---\n' "$f"
rg -n -C 5 \
'ServiceAccount|serviceAccount|thanos-operator|podLabels|env:|restart|annotation|role-arn' \
"$f" || true
done
printf '%s\n' '--- AWS CLI and Kubernetes validation examples in repository ---'
rg -n -C 3 \
'list-pod-identity-associations|describe-pod-identity-association|pod-identity-agent|aws-node|kubectl get pods|rollout status|argocd app sync' \
docs terraform argocd deploy \
--glob '*.md' --glob '*.tf' --glob '*.yaml' --glob '*.yml' \
| head -n 240Repository: openshift-online/rosa-hyperfleet
Length of output: 28369
🌐 Web query:
AWS EKS Pod Identity official documentation injected environment variables AWS_CONTAINER_CREDENTIALS_FULL_URI AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE versus AWS_ROLE_ARN AWS_WEB_IDENTITY_TOKEN_FILE
💡 Result:
Amazon EKS injects specific environment variables into pods to provide them with AWS IAM credentials based on the security model in use: EKS Pod Identity or IAM Roles for Service Accounts (IRSA) [1][2][3][4]. EKS Pod Identity When using EKS Pod Identity, the EKS control plane injects the following variables [3][5]: - AWS_CONTAINER_CREDENTIALS_FULL_URI: Set to http://169.254.170.23/v1/credentials. This directs the AWS SDK to connect to the Amazon EKS Pod Identity Agent (a DaemonSet running on the node) to retrieve temporary credentials [1][2][6]. - AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: Points to a projected Kubernetes service account token file (typically located at /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token) which is used for authorization with the EKS Auth API [2][3][5]. IAM Roles for Service Accounts (IRSA) When using IRSA, the EKS control plane injects these variables [6]: - AWS_ROLE_ARN: The Amazon Resource Name (ARN) of the IAM role assigned to the pod [6]. - AWS_WEB_IDENTITY_TOKEN_FILE: Points to the path of the projected Kubernetes service account token used to assume the IAM role via the AWS STS AssumeRoleWithWebIdentity API [6]. Key Differences - Architecture: EKS Pod Identity relies on a node-level agent to manage and cache credentials, reducing the load on the AWS STS API [1][2][6]. IRSA relies on the application pod itself directly assuming the role via the STS regional endpoint [6]. - Configuration: EKS Pod Identity is configured via EKS API associations and does not require annotations on the ServiceAccount object [7][6]. IRSA requires specific annotations on the Kubernetes ServiceAccount (e.g., eks.amazonaws.com/role-arn) [3][6]. - Precedence: If both are configured on the same ServiceAccount, EKS Pod Identity takes precedence; the EKS admission webhook will inject the Pod Identity environment variables and ignore the IRSA configuration [3][6].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
- 3: https://computingforgeeks.com/amazon-eks-pod-identity-complete-guide/
- 4: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
- 5: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
- 6: https://dev.to/himaatluri/eks-security-deep-dive-irsa-vs-eks-pod-identity-4562
- 7: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
🌐 Web query:
AWS EKS Pod Identity official documentation list-pod-identity-associations Pod Identity Agent prerequisites supported AWS SDK versions
💡 Result:
Amazon EKS Pod Identity is a feature that allows Kubernetes applications to receive IAM permissions via EKS API-configured associations [1]. Below are the details regarding your request. ListPodIdentityAssociations The list-pod-identity-associations operation lists EKS Pod Identity associations in a cluster [2][3]. - Operation: It supports filtering by Kubernetes namespace and service account [2][3]. - Parameters: Supported parameters include clusterName (required), namespace, serviceAccount, maxResults (1–100), and nextToken for pagination [2][4]. - Documentation: Detailed API references are available in the Amazon EKS API Reference [2], AWS CLI Command Reference [3], and SDK documentation (e.g., Boto3) [4]. EKS Pod Identity Agent Prerequisites To use the EKS Pod Identity feature, the EKS Pod Identity Agent must be running on the cluster nodes [5][6]. - Access: Nodes must have network access to the EKS Auth API. If using private subnets, an AWS PrivateLink interface endpoint for the EKS Auth API is required [7]. - Permissions: The node's IAM role must have permission to perform the eks-auth:AssumeRoleForPodIdentity action [7]. - Compatibility: The cluster must meet minimum platform or Kubernetes version requirements [7][5]. The agent is recommended to be installed as an EKS add-on [7][6]. Supported AWS SDK Versions Applications must use an AWS SDK version that supports EKS Pod Identity, as they rely on the default credential chain to interact with the agent [8][9]. Minimum supported versions include [8]: - Java (v2): 2.21.30 - Java (v1): 1.12.746 - Go v1: v1.47.11 - Go v2: release-2023-11-14 - Python (Boto3/botocore): 1.34.41 - AWS CLI (v1): 1.30.0 - AWS CLI (v2): 2.15.0 - JavaScript (v2): 2.1550.0 - JavaScript (v3): v3.458.0 - Kotlin: v1.0.1 - Ruby: 3.188.0 - Rust: release-2024-03-13 - C++: 1.11.263 -.NET: 3.7.734.0 - PowerShell: 4.1.502 - PHP: 3.289.0 For the most current list and full installation instructions, consult the official documentation [8].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/eksctl/pod-identity-associations.html
- 2: https://docs.aws.amazon.com/eks/latest/APIReference/API_ListPodIdentityAssociations.html
- 3: https://docs.aws.amazon.com/cli/latest/reference/eks/list-pod-identity-associations.html
- 4: https://boto3.amazonaws.com/v1/documentation/api/1.35.43/reference/services/eks/client/list_pod_identity_associations.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 6: https://github.com/aws/eks-pod-identity-agent
- 7: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
- 8: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk.html
- 9: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
spec = Path("docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md").read_text()
tf = Path("terraform/modules/thanos-infrastructure/main.tf").read_text()
eks = Path("terraform/modules/eks-cluster/main.tf").read_text()
association_names = re.findall(
r'resource\s+"aws_eks_pod_identity_association"\s+"([^"]+)"\s*\{',
tf,
)
expected = {
"thanos_receiver",
"thanos_store",
"thanos_compact",
"thanos_ruler",
"thanos_receive_ingester",
}
print("Terraform Thanos associations:", association_names)
print("All five expected associations declared:", set(association_names) == expected)
print("Pod Identity Agent add-on declared:",
'addon_name = "eks-pod-identity-agent"' in eks)
for name in ("AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE",
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
"AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE"):
print(f"{name}: documented={name in spec}")
print("Live AWS association command documented:",
"aws eks list-pod-identity-associations" in spec)
print("Agent readiness command documented:",
bool(re.search(r'kubectl\s+(get|wait|describe)[^\n]*pod[- ]identity', spec, re.I)))
print("New test-pod command documented:",
bool(re.search(r'kubectl\s+run\b', spec)))
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 697
Make pre-deployment validation live.
terraform state list does not prove that the target EKS cluster has active associations or a ready Pod Identity Agent. Before removing IRSA, query aws eks list-pod-identity-associations, verify the eks-pod-identity-agent is Ready on all nodes, and create a fresh pod with the affected ServiceAccount to validate credential injection and an AWS API call. Check AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE; AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE are IRSA variables, not Pod Identity indicators.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md` around
lines 302 - 313, Update the “Pre-Deployment” validation steps in the Pod
Identity migration design to query aws eks list-pod-identity-associations for
active target-cluster associations instead of relying on Terraform state, verify
the eks-pod-identity-agent is Ready on every node, and create a fresh pod using
the affected ServiceAccount to confirm AWS_CONTAINER_CREDENTIALS_FULL_URI,
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, and a successful AWS API call before
removing IRSA. Remove the incorrect AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE
checks.
Source: MCP tools
| ### Security | ||
|
|
||
| - **Least Privilege:** Pod Identity associations scope roles to specific namespace + service account (tighter than IRSA's namespace-only scoping via OIDC audience) | ||
| - **No Annotation Injection:** IRSA required plumbing role ARN through Helm values (could be misconfigured); Pod Identity associations are declarative Terraform resources | ||
| - **Audit Trail:** All role assumptions logged to CloudTrail with pod identity (IRSA logged only IAM role ARN, not pod identity) |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file="$(git ls-files 'docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md')"
test -n "$file"
sed -n '430,565p' "$file"
printf '\n--- references ---\n'
rg -n -i 'least privilege|namespace-only|annotation injection|audit trail|CloudTrail|session tag|service account|trust policy|Pod Identity|IRSA' "$file"Repository: openshift-online/rosa-hyperfleet
Length of output: 12783
🌐 Web query:
AWS EKS Pod Identity versus IRSA service account scoping CloudTrail session tags exact event behavior
💡 Result:
The primary distinction in how EKS Pod Identity and IAM Roles for Service Accounts (IRSA) handle session tags and CloudTrail logging stems from their architectural approaches to credential issuance [1][2]. EKS Pod Identity explicitly incorporates session tags as a core feature of its design to facilitate Attribute-Based Access Control (ABAC) [3][4]. When EKS Pod Identity assumes an IAM role, it automatically attaches six predefined, transitive session tags to the temporary credentials [3][1][5]: - eks-cluster-arn - eks-cluster-name - kubernetes-namespace - kubernetes-service-account - kubernetes-pod-name - kubernetes-pod-uid These tags are embedded in the AWS STS AssumeRole requests and appear directly within CloudTrail event logs under the requestParameters section as principalTags [3][1][4][6]. This provides a native, highly granular audit trail that allows administrators to identify precisely which pod, namespace, and cluster initiated an action without needing external logging agents [7][5]. Because these tags are transitive, they persist if the workload chains roles into other AWS accounts [3][8]. In contrast, IRSA does not automatically apply these predefined session tags [1][4]. While IAM roles can technically support session tags when assumed via OIDC providers, IRSA typically relies on the OIDC provider's claims (often parsed via the trust policy's condition block) to enforce scoping [7]. IRSA-based CloudTrail events do not contain the standardized Pod Identity session tags unless manually configured or passed through specific OIDC identity provider mechanisms [1][4][8]. Key Behavioral Differences: 1. Visibility: CloudTrail logs for EKS Pod Identity contain consistent, structured metadata (the six session tags) for every assume-role event [1][5]. IRSA logs generally lack this structured metadata unless specifically injected [4][7]. 2. Enforcement: EKS Pod Identity requires the sts:TagSession permission in the IAM role's trust policy to successfully assume the role, as it must attach these tags during the STS call [9][1]. 3. Reusability: Because EKS Pod Identity uses session tags for identification, a single IAM role can be used across multiple clusters or namespaces while maintaining unique, tag-based access boundaries [3][4]. IRSA often requires more complex, distinct trust policy conditions (e.g., parsing the subject claim) to achieve similar isolation [1][7]. In summary, EKS Pod Identity provides a standardized, built-in mechanism for injecting pod-level context into session tags and CloudTrail logs, whereas IRSA relies on OIDC-based trust policies that are generally more rigid and less transparent in standard audit logs [1][4][7].
Citations:
- 1: https://kloudvin.com/article/eks-irsa-to-pod-identity-migration-fine-grained-access/
- 2: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html
- 4: https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/
- 5: https://computingforgeeks.com/amazon-eks-pod-identity-complete-guide/
- 6: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html
- 7: https://safeguard.sh/resources/blog/aws-eks-pod-identity-vs-irsa-supply-chain
- 8: https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html
- 9: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide EKS Pod Identity session tags CloudTrail namespace service account IRSA sub condition
💡 Result:
EKS Pod Identity automatically includes session tags when assuming IAM roles, enabling attribute-based access control (ABAC) and improved auditability in AWS CloudTrail [1][2]. These tags are transitively passed during role assumptions, allowing for granular control across clusters and accounts [1]. Session Tags and Attributes By default, EKS Pod Identity attaches the following tags to the temporary security credentials provided to pods [1]: - eks-cluster-arn - eks-cluster-name - kubernetes-namespace - kubernetes-service-account - kubernetes-pod-name - kubernetes-pod-uid You can reference these tags in IAM policies using the syntax ${aws:PrincipalTag/tag-key} [1]. Using Session Tags in Trust Policies You can restrict which service accounts and namespaces are authorized to assume a specific IAM role by adding a condition block to the role's trust policy. This ensures that only pods meeting specific criteria can obtain credentials [3][4]. Example Trust Policy Condition: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:RequestTag/kubernetes-namespace": ["my-namespace"], "aws:RequestTag/kubernetes-service-account": ["my-service-account"] } } } ] } Auditability in CloudTrail EKS Pod Identity leverages AWS CloudTrail to log access and events, providing visibility into which pods (identified by namespace, service account, and other tags) are assuming roles and accessing AWS resources [5]. Because session tags are part of the STS request, they provide a clear audit trail for security teams to verify workload activity [1]. Key Differences from IRSA Unlike IAM Roles for Service Accounts (IRSA), which relies on OIDC and does not natively support session tags in the same way, EKS Pod Identity simplifies configuration by removing the need for OIDC provider management in the cluster [2]. While IRSA relies on token-based authentication, Pod Identity explicitly uses STS session tags, allowing administrators to reuse a single IAM role for multiple service accounts and enforce access boundaries based on those tags [1][2].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html
- 2: https://docs.aws.amazon.com/eks/latest/userguide/service-accounts.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import urlopen
from html import unescape
import re
urls = {
"pod-id-abac": "https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html",
"pod-id-role": "https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html",
"cross-account": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
}
terms = (
"session tag", "CloudTrail", "kubernetes-namespace", "kubernetes-service-account",
"sub", "StringEquals", "sts:TagSession", "service account"
)
for name, url in urls.items():
print(f"\n--- {name} ---")
try:
html = urlopen(url, timeout=20).read().decode("utf-8", "replace")
except Exception as exc:
print(f"FETCH ERROR: {exc}")
continue
text = re.sub(r"<script.*?</script>|<style.*?</style>", " ", html,
flags=re.I | re.S)
text = unescape(re.sub(r"<[^>]+>", " ", text))
text = re.sub(r"\s+", " ", text)
lower = text.lower()
found = False
for term in terms:
start = 0
while True:
pos = lower.find(term.lower(), start)
if pos < 0:
break
found = True
print(text[max(0, pos-220):pos+420])
start = pos + len(term)
if not found:
print("No target terms found")
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 679
🏁 Script executed:
#!/bin/bash
set -eu
for spec in \
"pod-id-abac|https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html" \
"pod-id-role|https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html" \
"cross-account|https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
do
name="${spec%%|*}"
url="${spec#*|}"
echo "--- $name ---"
curl -ksL --max-time 20 "$url" |
sed -E 's/<script[^>]*>.*<\/script>|<style[^>]*>.*<\/style>/ /Ig; s/<[^>]+>/ /g' |
tr '\n' ' ' |
sed -E 's/[[:space:]]+/ /g' |
grep -Eio '.{0,220}(session tag|CloudTrail|kubernetes-namespace|kubernetes-service-account|StringEquals|sts:TagSession|sub claim|service account).{0,420}' |
head -n 40 || true
doneRepository: openshift-online/rosa-hyperfleet
Length of output: 10467
Correct the IRSA comparison.
IRSA can restrict a role to an exact service account with the OIDC sub condition; the OIDC aud condition does not provide namespace-only scoping. Update the scope claims in both sections. Qualify the CloudTrail claim because Pod Identity session tags can be disabled and IRSA audit fields depend on the configured event and trust policy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md` around
lines 453 - 457, Update the IRSA comparisons in both security sections to state
that IRSA can scope roles to an exact namespace and service account through the
OIDC sub condition, while aud only constrains the intended audience. Qualify the
CloudTrail audit claim to account for Pod Identity session tags being disabled
and IRSA audit details varying with the configured event and trust policy.
Source: MCP tools
| ```hcl | ||
| # 1. IAM role with Pod Identity trust policy | ||
| resource "aws_iam_role" "example" { | ||
| name = "${var.cluster_id}-example" | ||
|
|
||
| assume_role_policy = jsonencode({ | ||
| Version = "2012-10-17" | ||
| Statement = [{ | ||
| Effect = "Allow" | ||
| Principal = { | ||
| Service = "pods.eks.amazonaws.com" | ||
| } | ||
| Action = [ | ||
| "sts:AssumeRole", | ||
| "sts:TagSession" | ||
| ] | ||
| }] | ||
| }) | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file='docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md'
printf '%s\n' '--- target excerpt ---'
sed -n '460,525p' "$file"
printf '%s\n' '--- related trust-policy and SourceOrgId references ---'
rg -n -C 3 'pods\.eks\.amazonaws\.com|SourceOrgId|SourceAccount|trust policy|trust-policy' "$file"Repository: openshift-online/rosa-hyperfleet
Length of output: 4105
🌐 Web query:
AWS EKS Pod Identity trust policy aws:SourceOrgId condition official documentation
💡 Result:
The aws:SourceOrgID condition key is a global AWS IAM condition key that can be used within an IAM role trust policy to restrict the entities allowed to assume that role [1][2]. In the context of Amazon EKS Pod Identity, you can include this condition to ensure that only requests originating from your specific AWS Organization are permitted to assume the IAM role [2][3]. While the official Amazon EKS documentation provides a standard trust policy template using the pods.eks.amazonaws.com service principal [4][5], it also notes that you can use condition keys to further secure these roles [4][5]. The aws:SourceOrgID key acts as a guardrail to prevent the role from being assumed by entities outside of your defined organization [6][2]. Example usage in an IAM role trust policy: { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowEksAuthToAssumeRoleForPodIdentity", "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:SourceOrgID": "o-xxxxxxxxxx" } } } ] } Key considerations: - The aws:SourceOrgID key evaluates to the organization ID of the caller [2]. - This provides an organization-wide control that simplifies policy management, as you do not need to update the trust policy when individual accounts are added to or removed from your organization [7][2]. - For more granular control at the pod level (such as restricting by Kubernetes namespace or service account), Amazon EKS recommends using session tag condition keys like aws:RequestTag/kubernetes-namespace and aws:RequestTag/kubernetes-service-account [4][5].
Citations:
- 1: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
- 2: https://aws.amazon.com/blogs/security/use-scalable-controls-for-aws-services-accessing-your-resources/
- 3: https://hidekazu-konishi.com/entry/amazon_eks_pod_identity_and_irsa_decision_guide.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
- 6: https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html
- 7: https://aws.amazon.com/about-aws/whats-new/2023/11/organization-wide-iam-condition-keys-restrict-aws-service-to-service-requests/
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html aws:SourceOrgId "pods.eks.amazonaws.com"
💡 Result:
The service principal pods.eks.amazonaws.com is used in the trust policy of an IAM role to allow Amazon EKS Pod Identity to assume the role on behalf of a Kubernetes pod [1]. While you can restrict access to an IAM role by using condition keys in the trust policy—such as restricting by kubernetes-namespace or kubernetes-service-account using aws:RequestTag—there is no documented support for using aws:SourceOrgId as a condition key specifically with the pods.eks.amazonaws.com service principal [1]. In an EKS Pod Identity trust policy, the configuration typically looks like this [1]: { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowEksAuthToAssumeRoleForPodIdentity", "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:RequestTag/kubernetes-namespace": "your-namespace", "aws:RequestTag/kubernetes-service-account": "your-service-account" } } } ] } If you are attempting to restrict access based on an AWS Organization, ensure you are using supported condition keys, as aws:SourceOrgId is a global condition key but is not explicitly identified in official documentation as a control for EKS Pod Identity trust policies [1].
Citations:
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import urlopen
from bs4 import BeautifulSoup
urls = [
"https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html",
"https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html",
]
for url in urls:
print(f"--- {url} ---")
html = urlopen(url, timeout=20).read()
text = BeautifulSoup(html, "html.parser").get_text(" ", strip=True)
needles = ("SourceOrgId", "SourceAccount", "pods.eks.amazonaws.com",
"aws:RequestTag/kubernetes-namespace",
"aws:RequestTag/kubernetes-service-account")
for needle in needles:
pos = text.find(needle)
if pos >= 0:
print(text[max(0, pos-350):pos+700])
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 286
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import Request, urlopen
from html import unescape
import re
url = "https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html"
req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
html = urlopen(req, timeout=20).read().decode("utf-8", "replace")
text = unescape(re.sub(r"<[^>]+>", " ", html))
text = re.sub(r"\s+", " ", text)
for needle in [
"SourceOrgId", "SourceAccount", "pods.eks.amazonaws.com",
"RequestTag/kubernetes-namespace",
"RequestTag/kubernetes-service-account",
]:
print(f"--- {needle} ---")
positions = [m.start() for m in re.finditer(re.escape(needle), text, re.I)]
if not positions:
print("not found")
for pos in positions[:5]:
print(text[max(0, pos-500):pos+1000])
PYRepository: openshift-online/rosa-hyperfleet
Length of output: 2456
🌐 Web query:
AWS EKS Pod Identity aws:SourceOrgId supported condition key pods.eks.amazonaws.com trust policy
💡 Result:
The aws:SourceOrgId condition key is a supported and recommended security best practice for EKS Pod Identity IAM role trust policies to help prevent the cross-service confused deputy problem [1][2]. When configuring an IAM role for EKS Pod Identity, the service principal pods.eks.amazonaws.com must be allowed to perform sts:AssumeRole and sts:TagSession [1][3][4]. AWS explicitly recommends adding a Condition block using aws:SourceOrgId to ensure that only requests originating from within your specific AWS Organization can assume the role [1]. Below is an example of an IAM role trust policy incorporating this condition [1]: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:SourceOrgId": "${aws:ResourceOrgId}" } } } ] } In this configuration, ${aws:ResourceOrgId} is a policy variable that automatically resolves to the Organization ID of the account owning the IAM role [1]. By including this condition, you restrict the ability of the EKS Pod Identity service to assume the role only when the request is made on behalf of an account within your designated organization [1][2]. For more granular security, you can also use session tag condition keys (such as aws:RequestTag/kubernetes-namespace and aws:RequestTag/kubernetes-service-account) to restrict access to specific namespaces or service accounts within your EKS clusters [3][5].
Citations:
- 1: https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html
- 2: https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html
- 3: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html
- 4: https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html
- 5: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
🏁 Script executed:
#!/bin/bash
set -eu
for url in \
'https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html' \
'https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html'
do
echo "--- $url ---"
curl -Lks --max-time 20 "$url" |
tr '\n' ' ' |
sed 's/<[^>]*>/ /g; s/[[:space:]]\\+/ /g' |
grep -oE '.{0,500}(SourceOrgId|SourceAccount|pods\\.eks\\.amazonaws\\.com|RequestTag/kubernetes-namespace|RequestTag/kubernetes-service-account).{0,1000}' |
head -20 || true
doneRepository: openshift-online/rosa-hyperfleet
Length of output: 3386
🌐 Web query:
site:docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html "SourceOrgId"
💡 Result:
SourceOrgId, specifically referenced as aws:SourceOrgId in the context of AWS IAM, is a global condition key used in trust policies to help prevent the cross-service confused deputy problem [1]. In an IAM role trust policy, aws:SourceOrgId is used as a condition to ensure that the entity assuming the role belongs to a specific AWS Organization [1]. It is often compared or used in conjunction with aws:ResourceOrgId, which represents the Organization ID of the AWS account associated with the resource [1]. By requiring that these IDs match, administrators can restrict role assumption to only those services or identities originating from within their own organization [1]. An example of its application in an EKS Pod Identity trust policy is shown below: { "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "pods.eks.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "aws:SourceOrgId": "${aws:ResourceOrgId}" } } } ] } [1]
Citations:
Add the organization boundary to the trust policy.
Add StringEquals: { "aws:SourceOrgId": "${aws:ResourceOrgId}" } to the example. This limits Pod Identity role assumption to the account’s AWS Organization and reduces confused-deputy risk.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md` around
lines 487 - 505, Add a StringEquals condition for aws:SourceOrgId equal to
aws:ResourceOrgId within the assume_role_policy Statement of
aws_iam_role.example, preserving the existing pod service principal and actions.
Source: MCP tools
|
/test terraform-validate |
|
/test terraform-validate |
|
/test on-demand-e2e |
|
/test terraform-validate |
1 similar comment
|
/test terraform-validate |
|
@theautoroboto: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
Summary
Completes the platform's migration from IRSA to EKS Pod Identity by removing the last IRSA annotation from the Thanos service account and documenting the platform-wide Pod Identity architecture.
Test PR for pipeline validation
Changes
Remove IRSA annotation from
argocd/config/regional-cluster/thanos/templates/serviceaccount.yamlPlatform-wide Pod Identity documentation in
docs/design/pod-identity-migration.mdImplementation artifacts
docs/superpowers/specs/2026-08-12-pod-identity-migration-design.mddocs/superpowers/plans/2026-08-12-complete-pod-identity-migration.mdVerification
Deployment Impact
Test Plan
Post-deployment verification:
kubectl get sa thanos-operator -n thanos -o yamlkubectl get pods -n thanos -l app.kubernetes.io/name=thanos-operator -o yaml | grep AWS_🤖 Generated with Claude Code
Summary by CodeRabbit
Documentation
Bug Fixes