Part of the agent action attribution roadmap — the AWS half. Companion to
the K8s-half impersonate-RBAC issue and to #38 (direct runtime).
Blocked on Phase 0 — settling the standing hub cluster. Don't start this
until the hub is validated + stable; the role lands on that substrate and can
only be validated against a live cluster + its CloudTrail. Tracking now so the
gap is visible.
What
Add a per-tenant session-broker IAM role that can carry a human/session
sts:SourceIdentity, so agent actions become attributable in CloudTrail.
The runtime (the attributable path — see #38, runs on AgentSandbox/direct) assumes
this role per session with sts:AssumeRole --source-identity=<id> (or
AssumeRoleWithWebIdentity with a custom JWT carrying the
https://aws.amazon.com/source_identity claim). Once set, SourceIdentity is
immutable for the session, survives role chaining, and AWS stamps it into
userIdentity.sessionContext.sourceIdentity on every downstream call — incl.
Bedrock InvokeModel on that session.
Why this shape (not Pod Identity, not plain IRSA)
Verified against AWS docs:
- Plain IRSA (the EKS-managed OIDC token used today) can't inject a dynamic
SourceIdentity — the token emits a fixed claim set (sub=system:serviceaccount:…,
aud=sts.amazonaws.com), no source_identity claim, no hook.
- EKS Pod Identity can't carry SourceIdentity either (no param; "can't add
custom tags") — it only auto-attaches infra session tags.
sts:SourceIdentity is only reachable via the AssumeRole family with
sts:SetSourceIdentity in the trust policy. Hence a deliberate broker role, not
a config flip on the existing tenant IRSA role.
Current state (the gap)
- Tenant IRSA trust conditions only on
:sub / :aud, no sts:SetSourceIdentity,
no SourceIdentity — operators/internal/controller/platform_iam.go:88-104
(assumeRolePolicyForOIDC); terraform/components/agent-iam/main.tf:27-40.
- No STS session role with a
SetSourceIdentity trust exists anywhere
(landing-zone / eks-fleet agent-iam grep is empty).
- fab already implements the client half (assume-with-source-identity) —
fab/src/attribution.ts, fab/docs/attribution.md:62-85. This issue is the
substrate role it assumes into.
Shape of the change
- New per-tenant session role in the IRSA factory (
agent-iam): trust policy
principal = the tenant tenant-runtime IRSA role, actions sts:AssumeRole +
sts:SetSourceIdentity; grants the runtime its model/k8s permissions. Optionally
a trust condition requiring SourceIdentity be set (so crossbearing's trust
check scores it attribution-capable rather than anonymous-by-default).
- Publish the role ARN (SSM, mirroring the existing IRSA outputs).
- Wire
FAB_SESSION_ROLE_ARN onto the dispatcher env (set per session alongside
the operator — see the K8s-half + per-session-operator issues).
Scope / guardrails
- Off-by-default; opt-in per tenant. Default tenants keep the authentic
unattributed path.
- Identity is a scoped synthetic
agent:<tenant>:<session>, not arbitrary
humans. SourceIdentity charset is [A-Za-z0-9_.,+=@-], 2–64 chars.
- One-tenant pilot before broad enablement.
Independence
crossbearing consumes platform-emitted logs only; nothing crossbearing-specific
lands here. This is a standalone platform capability.
Part of the agent action attribution roadmap — the AWS half. Companion to
the K8s-half impersonate-RBAC issue and to #38 (direct runtime).
What
Add a per-tenant session-broker IAM role that can carry a human/session
sts:SourceIdentity, so agent actions become attributable in CloudTrail.The runtime (the attributable path — see #38, runs on AgentSandbox/direct) assumes
this role per session with
sts:AssumeRole --source-identity=<id>(orAssumeRoleWithWebIdentity with a custom JWT carrying the
https://aws.amazon.com/source_identityclaim). Once set, SourceIdentity isimmutable for the session, survives role chaining, and AWS stamps it into
userIdentity.sessionContext.sourceIdentityon every downstream call — incl.Bedrock
InvokeModelon that session.Why this shape (not Pod Identity, not plain IRSA)
Verified against AWS docs:
SourceIdentity — the token emits a fixed claim set (
sub=system:serviceaccount:…,aud=sts.amazonaws.com), nosource_identityclaim, no hook.custom tags") — it only auto-attaches infra session tags.
sts:SourceIdentityis only reachable via the AssumeRole family withsts:SetSourceIdentityin the trust policy. Hence a deliberate broker role, nota config flip on the existing tenant IRSA role.
Current state (the gap)
:sub/:aud, nosts:SetSourceIdentity,no SourceIdentity —
operators/internal/controller/platform_iam.go:88-104(
assumeRolePolicyForOIDC);terraform/components/agent-iam/main.tf:27-40.SetSourceIdentitytrust exists anywhere(landing-zone / eks-fleet agent-iam grep is empty).
fab/src/attribution.ts,fab/docs/attribution.md:62-85. This issue is thesubstrate role it assumes into.
Shape of the change
agent-iam): trust policyprincipal = the tenant
tenant-runtimeIRSA role, actionssts:AssumeRole+sts:SetSourceIdentity; grants the runtime its model/k8s permissions. Optionallya trust condition requiring SourceIdentity be set (so crossbearing's trust
check scores it attribution-capable rather than anonymous-by-default).
FAB_SESSION_ROLE_ARNonto the dispatcher env (set per session alongsidethe operator — see the K8s-half + per-session-operator issues).
Scope / guardrails
unattributed path.
agent:<tenant>:<session>, not arbitraryhumans. SourceIdentity charset is
[A-Za-z0-9_.,+=@-], 2–64 chars.Independence
crossbearing consumes platform-emitted logs only; nothing crossbearing-specific
lands here. This is a standalone platform capability.