Skip to content

fix(broker): emit https://aws.amazon.com/tags claim so STS sets PrincipalTag#68

Closed
hanwencheng wants to merge 1 commit intomainfrom
fix/broker-aws-tags-claim
Closed

fix(broker): emit https://aws.amazon.com/tags claim so STS sets PrincipalTag#68
hanwencheng wants to merge 1 commit intomainfrom
fix/broker-aws-tags-claim

Conversation

@hanwencheng
Copy link
Copy Markdown
Member

Summary

The OIDC broker mints JWTs with agentkeys_user_wallet as a top-level claim, but AWS STS does not auto-promote arbitrary claims to session tags. It looks specifically for the magic-named https://aws.amazon.com/tags claim with principal_tags (and optionally transitive_tag_keys). Without that claim:

  • sts:AssumeRoleWithWebIdentity returns a session with no PrincipalTag
  • ${aws:PrincipalTag/agentkeys_user_wallet} in bucket policies expands to empty
  • The whole §4 federation-with-isolation story is inert — the cloud isn't enforcing anything, even though the runbook reads as if it is

This PR adds the AWS-magic claim to the JWT in mint_oidc_jwt and a regression-guard test assertion.

Spec: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#oidc-session-tags

Reproduction (before this fix)

End-to-end §4.5 against the deployed prod broker, with the §4.4 bucket policy correctly applied (PR #67) and the §3 inline-policy broad grant removed:

$ aws sts get-caller-identity
# → assumed-role/agentkeys-data-role/fed-proof-...

$ aws s3api list-objects-v2 --bucket "$BUCKET" --prefix "$WALLET/"
# Empty result, no AccessDenied — even though we expect bucket policy to allow our own prefix

$ aws s3api list-objects-v2 --bucket "$BUCKET" --prefix "0xdeadbeef/"
# Empty result, no AccessDenied — leaks across tenants

Both succeed because the bucket policy's ${aws:PrincipalTag/agentkeys_user_wallet} expands to empty (no tag set), and the StringLike "${tag}/*" condition then becomes StringLike "/*" which matches nothing — so the bucket policy denies both. Combined with the agentkeys-data-role-inline static-IAM grant the runbook also leaves attached (separate runbook fix in #67), the request falls through to broad-bucket access. Net: no tenant boundary anywhere.

Decoded JWT confirming the missing claim:

{
  "agentkeys_user_wallet": "0xe5cc...",
  "aud": "sts.amazonaws.com",
  "exp": 1778086977,
  "iat": 1778086677,
  "iss": "https://broker.litentry.org",
  "sub": "agentkeys:agent:0xe5cc..."
}

No https://aws.amazon.com/tags. After this PR's fix, the JWT will additionally carry:

"https://aws.amazon.com/tags": {
  "principal_tags": {
    "agentkeys_user_wallet": ["0xe5cc..."]
  },
  "transitive_tag_keys": ["agentkeys_user_wallet"]
}

Changes

crates/agentkeys-broker-server/src/handlers/oidc.rs

  • mint_oidc_jwt builds the https://aws.amazon.com/tags claim with principal_tags.agentkeys_user_wallet = [session.wallet]. transitive_tag_keys ensures the tag survives if the daemon role-chains.
  • Discovery doc claims_supported now advertises https://aws.amazon.com/tags.
  • Comment block above the claims construction explains why this is required (so the next person doesn't accidentally remove it as "unused magic").

crates/agentkeys-broker-server/tests/oidc_flow.rs

  • mint_oidc_jwt_signs_claims_for_session_wallet now asserts the JWT carries the AWS tags claim with the wallet under principal_tags and transitive_tag_keys set. Bug-regression guard: prevents this claim from being silently dropped in a future refactor.
  • discovery_returns_aws_compatible_shape (the claims_supported test) now asserts the tags claim is advertised in discovery.

Test plan

  • cargo test -p agentkeys-broker-server — all 9 + 6 + 0 tests pass locally.
  • After deploy: re-run §4.5 against the live broker. Expect 4a → success (empty list, no error), 4b → AccessDenied. JWT decode should show the https://aws.amazon.com/tags claim populated.
  • AWS-side: post-deploy, aws sts get-session-token (or any subsequent call with the assumed creds) should reflect the session tag. Could verify via CloudTrail event for the assume-role call (look for principalTags in the request).

Deploy notes

This needs to be built and rolled out to the broker host (broker.litentry.org) for §4.5 to actually pass. The runbook fix (PR #67) gets the AWS side correct; this PR gets the broker side correct; both are needed.

After merge:

  1. SSH to broker host
  2. git pull && cargo build --release -p agentkeys-broker-server
  3. sudo cp target/release/agentkeys-broker-server /usr/local/bin/
  4. sudo systemctl restart agentkeys-broker
  5. Re-run §4.5 — should now pass cleanly

Related

🤖 Generated with Claude Code

@hanwencheng
Copy link
Copy Markdown
Member Author

Consolidating with #67 into a single PR for the Stage 7 federation fix (docs + broker code together — same conceptual change).

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