feat(fetch): support harness in fetch access (CLI + TUI)#1611
Conversation
Adds 'harness' as a resource type for fetch access, fetching a CUSTOM_JWT bearer token for a deployed harness via the existing fetchHarnessToken operation. CLI: - types: FetchResourceType += 'harness' - action: handleFetchHarnessAccess dispatch; agent + harness share one fetchTokenAccess helper - command: help text covers harness TUI: - new listHarnesses operation (project registry ∩ deployed-state, reads each harness.json for authorizerType) - useFetchAccessFlow loads harnesses alongside gateways/agents and routes the harness fetch through fetchHarnessToken - FetchAccessScreen labels the harness resource type Verified end-to-end against real AWS (us-west-2): deployed a CUSTOM_JWT harness backed by Cognito with the OAuth credential stored in AgentCore Identity, then fetched a valid bearer token via both 'fetch access --type harness' and the TUI picker. Unit tests: 48 passing across fetch-access (incl. 6 new harness cases).
|
Claude Security Review: no high-confidence findings. (run) |
Package TarballHow to installgh release download pr-1611-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.20.2.tgz |
agentcore-cli-automation
left a comment
There was a problem hiding this comment.
Nice cleanup factoring fetchTokenAccess out of the agent and harness paths. A couple of real issues to address before merge — see inline comments. The main one: --identity-name is silently ignored for harnesses because fetchHarnessToken doesn't accept that option, even though the CLI advertises the flag for all token-bearing resources.
One additional note (not file in this PR, so flagging here):
Telemetry — ResourceType in src/cli/telemetry/schemas/common-shapes.ts:93 is z.enum(['gateway', 'agent']) and backs the fetch.access resource_type attribute (see command-run.ts:173). Adding harness means that enum needs 'harness' for any future emission to be valid.
Separately, I couldn't find any actual cli.command_run emission for fetch.access — the schema entry exists but commands/fetch/command.tsx doesn't wrap the handler with withCommandRunTelemetry. That's a pre-existing gap, but per src/cli/telemetry/README.md adding telemetry to new features is expected. Worth wiring up while you're here so the new harness path doesn't go unobserved.
Coverage Report
|
- fetchHarnessToken: accept identityName and forward as credentialName, so
'fetch access --type harness --identity-name X' is honored instead of
silently using the default <name>-oauth (mirrors fetchRuntimeToken).
- listHarnesses: drop the silent AWS_IAM fallback on readHarnessSpec failure;
let the error propagate so a corrupt/missing harness.json for a deployed
harness surfaces instead of masking a CUSTOM_JWT harness as AWS_IAM.
- HarnessInfo.authType: type as RuntimeAuthorizerType (was string) to match
AgentInfo and get the TUI auth-type branches type-checked.
- tests: replace the objectContaining({}) matcher with exact-options
assertions and add a case proving --identity-name/--target are forwarded.
|
Claude Security Review: no high-confidence findings. (run) |
Set the CUSTOM_JWT harness up via 'add harness' with the JWT + OAuth-credential flags (--authorizer-type/--discovery-url/--allowed-audience/--client-id/ --client-secret) instead of patching harness.json directly. This registers the managed OAuth credential and .env.local secret — the real user flow — which are the prerequisites for fetch access to mint a token. Adds a step asserting 'fetch access --type harness' returns a CUSTOM_JWT bearer token and that the JWT's issuer/client_id claims match the Cognito pool. Depends on the fetch-access-harness feature (PR #1611); until that merges, this step exercises a command not yet on main. The e2e suite is manual/full-suite only, so this does not gate per-PR CI.
|
Looks good to merge from my pass. The three inline issues from the previous review ( The only outstanding item is the telemetry note from the previous review summary — it wasn't addressed and isn't a code-change blocker in this PR, but worth tracking:
Both are pre-existing gaps that this PR widens rather than introduces. Happy to see them addressed in a follow-up if you'd rather keep this PR scoped. |
|
Addressed the telemetry note from the review body in 2ad7236:
The three inline issues ( |
|
Claude Security Review: no high-confidence findings. (run) |
Update docs/commands.md 'fetch access' section: --type now lists harness, add a harness usage example, and note the CUSTOM_JWT token-fetch behavior (managed OAuth credential, --identity-name override, AWS_IAM has no token).
|
Claude Security Review: no high-confidence findings. (run) |
…WT (#1609) * test(e2e): add harness E2E coverage for lite_llm, attached tools, and CUSTOM_JWT Extends the harness E2E surface with three real-AWS scenarios that the provider matrix (bedrock/open_ai/gemini) doesn't cover: - harness-litellm.test.ts — lite_llm provider routed at a Bedrock model (no third-party key); deploy-only (skipInvoke) to prove the model config is accepted by CloudFormation. Extends harness-e2e-helper with modelId/apiBase/ additionalParams support. - harness-with-tool.test.ts — bedrock harness + agentcore_code_interpreter tool via 'add tool'; proves tool wiring survives synth/deploy and the harness still invokes. - harness-custom-jwt.test.ts — harness with a CUSTOM_JWT authorizer backed by a Cognito pool; asserts AuthorizerConfiguration in the CFN template, SigV4 rejection, and bearer-token invoke (mirrors byo-custom-jwt.test.ts). All self-skip without AWS creds. The per-PR e2e workflow auto-runs changed harness-*.test.ts files; the full suite shards everything. * test(e2e): add fetch access --type harness step to custom-jwt e2e Set the CUSTOM_JWT harness up via 'add harness' with the JWT + OAuth-credential flags (--authorizer-type/--discovery-url/--allowed-audience/--client-id/ --client-secret) instead of patching harness.json directly. This registers the managed OAuth credential and .env.local secret — the real user flow — which are the prerequisites for fetch access to mint a token. Adds a step asserting 'fetch access --type harness' returns a CUSTOM_JWT bearer token and that the JWT's issuer/client_id claims match the Cognito pool. Depends on the fetch-access-harness feature (PR #1611); until that merges, this step exercises a command not yet on main. The e2e suite is manual/full-suite only, so this does not gate per-PR CI.
) The harness-custom-jwt E2E (added in #1609) deployed the authorizer with --allowed-audience, which validates the token's aud claim. But the test authenticates via Cognito client_credentials (M2M), whose tokens carry a client_id claim and no aud. Combined with the harness auto-fetch flow from the main+preview merge (#1598, #1611) — where a registered managed OAuth credential makes a default invoke auto-fetch a JWT instead of using SigV4 — the service rejected every fetched token with 403 'missing required audience claim', which didn't match the test's expected client-side rejection. Switch the authorizer to --allowed-clients (the claim Cognito M2M tokens actually carry), assert AllowedClients in the deploy template check, and reframe the invoke tests to the real post-merge behavior: a default invoke auto-fetches a JWT and is accepted, and the bearer-token invoke returns exitCode 0. Test-only change; no shippable CLI behavior changes. Closes #1623
Summary
Adds harness as a resource type for
fetch access, so users can retrieve a CUSTOM_JWT bearer token for a deployed harness — both from the CLI (fetch access --type harness --name <name>) and the interactive TUI picker. Builds on the existingfetchHarnessTokenoperation (already used byinvokeauto-fetch); this exposes it through thefetchcommand surface.What changed
CLI
commands/fetch/types.ts—FetchResourceType+='harness'commands/fetch/action.ts—handleFetchHarnessAccessdispatch; the agent and harness handlers now share onefetchTokenAccesshelper (they were near-identical)commands/fetch/command.tsx—--type/--name/ description help text cover harnessTUI
operations/fetch-access/list-harnesses.ts— newlistHarnesses(project registry ∩ deployed-state, reads eachharness.jsonforauthorizerType); mirrorslistAgentsoperations/fetch-access/{types,index}.ts—HarnessInfotype + exportstui/screens/fetch-access/useFetchAccessFlow.ts— loads harnesses alongside gateways/agents; routes harness fetch throughfetchHarnessTokentui/screens/fetch-access/FetchAccessScreen.tsx— labels the harness resource typeTesting
Unit: 48 passing across fetch-access, including 6 new harness cases (3 CLI action, 3 TUI flow).
End-to-end against real AWS (account 346532552948 / us-west-2):
create-oauth2-credential-provider).fetch access --type harness --name <name>→success: true, returned a valid Cognito-issued JWT (verified claims: correct issuer, client_id,scope=agentcore/invoke,token_use=access).fetchflow → harness appears in the picker asHarness [JWT], selecting it fetches and displays the same valid token.Notes
AWS_IAMharness has no token to fetch — it surfaces the existing "use SigV4" guidance (same UX as the agent path). Token fetch applies only to CUSTOM_JWT harnesses with a managed OAuth credential.listHarnessesreads eachharness.jsonforauthorizerType(the project registry entry only carries name/path).