Skip to content

test: Complete IRSA to Pod Identity migration - #746

Open
theautoroboto wants to merge 5 commits into
openshift-online:mainfrom
theautoroboto:worktree-migrate-to-pod-identity
Open

test: Complete IRSA to Pod Identity migration#746
theautoroboto wants to merge 5 commits into
openshift-online:mainfrom
theautoroboto:worktree-migrate-to-pod-identity

Conversation

@theautoroboto

@theautoroboto theautoroboto commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

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

  1. Remove IRSA annotation from argocd/config/regional-cluster/thanos/templates/serviceaccount.yaml

    • Pod Identity associations already exist in Terraform (5 total for Thanos components)
    • IRSA annotation is ignored by EKS when Pod Identity is active
    • Zero downtime: ArgoCD GitOps sync
  2. Platform-wide Pod Identity documentation in docs/design/pod-identity-migration.md

    • Why Pod Identity over IRSA (simpler Terraform, better debugging, tighter scope)
    • Migration timeline (Karpenter, Thanos, 30+ prior migrations)
    • Standard 4-step implementation pattern
    • Reference implementations and debugging guide
  3. Implementation artifacts

    • Design spec: docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md
    • Implementation plan: docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md

Verification

  • ✅ Helm lint: All charts pass
  • ✅ Prettier: All markdown formatted
  • ✅ Pre-push validation: PASS (terraform-fmt, check-docs, helm-lint)
  • ✅ IRSA remnants: NONE (platform infrastructure clean)
  • ✅ Pod Identity associations verified in Terraform (5 for Thanos)

Deployment Impact

  • Zero downtime: Pod Identity already active, annotation removal is cleanup
  • No infrastructure changes: All Pod Identity associations already exist in Terraform
  • ArgoCD sync: Triggers Thanos operator pod restart to pick up updated ServiceAccount

Test Plan

Post-deployment verification:

  1. Verify ServiceAccount updated: kubectl get sa thanos-operator -n thanos -o yaml
  2. Verify Pod Identity env vars: kubectl get pods -n thanos -l app.kubernetes.io/name=thanos-operator -o yaml | grep AWS_
  3. Check Thanos logs for successful S3/KMS operations
  4. Monitor metrics ingestion (no gaps in Prometheus remote_write)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Added guidance for migrating platform authentication from IRSA to EKS Pod Identity.
    • Documented migration history, architecture, implementation patterns, credential flows, validation steps, troubleshooting, and rollback procedures.
    • Added an implementation plan and design specification for completing and verifying the migration.
  • Bug Fixes

    • Removed the automatically generated AWS IAM role annotation from the Thanos service account.
    • Existing user-provided service account annotations continue to be supported.

theautoroboto and others added 5 commits August 12, 2026 11:37
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>
@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign slopezz for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The 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.

Changes

Pod Identity migration

Layer / File(s) Summary
Remove the Thanos IRSA annotation
argocd/config/regional-cluster/thanos/templates/serviceaccount.yaml, docs/superpowers/plans/...
The Thanos ServiceAccount no longer generates the conditional IAM role annotation. The implementation plan records verification and Helm validation steps.
Document Pod Identity architecture
docs/design/pod-identity-migration.md, docs/superpowers/specs/..., docs/superpowers/plans/...
The documentation describes migration history, Terraform and Helm patterns, credential flow, reference deployments, and platform component coverage.
Define validation and operations
docs/design/pod-identity-migration.md, docs/superpowers/specs/..., docs/superpowers/plans/...
The documents add troubleshooting, failure handling, testing, monitoring, rollback, delivery, and self-review procedures.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: completing the migration from IRSA to EKS Pod Identity.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test on-demand-e2e

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🧹 Nitpick comments (1)
docs/design/pod-identity-migration.md (1)

1-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add 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

📥 Commits

Reviewing files that changed from the base of the PR and between 7bf0af1 and fb059a8.

📒 Files selected for processing (4)
  • argocd/config/regional-cluster/thanos/templates/serviceaccount.yaml
  • docs/design/pod-identity-migration.md
  • docs/superpowers/plans/2026-08-12-complete-pod-identity-migration.md
  • docs/superpowers/specs/2026-08-12-pod-identity-migration-design.md
💤 Files with no reviewable changes (1)
  • argocd/config/regional-cluster/thanos/templates/serviceaccount.yaml

Comment on lines +17 to +25
| 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 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


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

Comment on lines +55 to +78
### 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"
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


🏁 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.md

Repository: 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

Comment on lines +132 to +147
```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
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


🌐 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:


🌐 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:


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

Comment on lines +203 to +212
### 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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.md

Repository: 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:


🏁 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.md

Repository: 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

Comment on lines +56 to +64
- [ ] **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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 -300

Repository: 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:


🏁 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)
PY

Repository: 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 -150

Repository: 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

Comment on lines +169 to +183
```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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


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

Comment on lines +184 to +185
ArgoCD->>K8s: Apply ServiceAccount (no annotation)
ArgoCD->>K8s: Trigger pod restart (Deployment updated)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 240

Repository: 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/null

Repository: 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)))
PY

Repository: 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

Comment on lines +302 to +313
**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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 240

Repository: 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:


🌐 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:


🏁 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)))
PY

Repository: 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

Comment on lines +453 to +457
### 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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


🌐 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:


🏁 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")
PY

Repository: 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
done

Repository: 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

Comment on lines +487 to +505
```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"
]
}]
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


🌐 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])
PY

Repository: 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])
PY

Repository: 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:


🏁 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
done

Repository: 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

@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test terraform-validate
/test on-demand-e2e

@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test terraform-validate

@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test on-demand-e2e

@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test terraform-validate
/test on-demand-e2e

1 similar comment
@theautoroboto

Copy link
Copy Markdown
Contributor Author

/test terraform-validate
/test on-demand-e2e

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

@theautoroboto: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/terraform-validate fb059a8 link true /test terraform-validate
ci/prow/on-demand-e2e fb059a8 link true /test on-demand-e2e

Full PR test history. Your PR dashboard.

Details

Instructions 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant