Skip to content

feat: replace credentialProviderName with outboundAuth for harness gateway tools#1083

Merged
notgitika merged 3 commits intopreviewfrom
feat/harness-outbound-auth
May 1, 2026
Merged

feat: replace credentialProviderName with outboundAuth for harness gateway tools#1083
notgitika merged 3 commits intopreviewfrom
feat/harness-outbound-auth

Conversation

@aidandaly24
Copy link
Copy Markdown
Contributor

Summary

  • Replace the incorrect credentialProviderName field on harness gateway tool config with the correct outboundAuth union to match the harness service model (Loopy)
  • The service expects outboundAuth with three variants: awsIam (SigV4), none, and oauth (Bearer token via AgentCore Identity)
  • Add CLI flags (--outbound-auth, --provider-arn, --scopes, --grant-type) to agentcore add tool
  • Add outbound auth type selection to the TUI harness wizard (3 new steps)
  • Add superRefine to reject legacy credentialProviderName with a helpful migration message
  • Fix DX: default indication in help text, scopes format example, TUI default label

Context

A customer reported that configuring a harness gateway tool to authenticate to a CUSTOM_JWT gateway via OAuth always fell back to SigV4, resulting in 401s. Investigation revealed the CLI schema had credentialProviderName (modeled after agent code gen) instead of outboundAuth (the actual service model). See bugbash/harness-gateway-auth-analysis.md for the full analysis.

Changes

File Change
src/schema/schemas/primitives/harness.ts Replace credentialProviderName with outboundAuth union schema + superRefine migration message
src/schema/schemas/primitives/index.ts Export new types
src/schema/schemas/agentcore-project.ts Re-export for consumer access
src/cli/commands/add/tool-command.ts Add --outbound-auth, --provider-arn, --scopes, --grant-type flags with DX improvements
src/cli/commands/add/tool-action.ts Validation + outboundAuth construction from flags
src/cli/primitives/HarnessPrimitive.ts Build outboundAuth in gateway tool construction
src/cli/tui/screens/harness/types.ts New wizard steps, config fields, options with default label
src/cli/tui/screens/harness/useAddHarnessWizard.ts Auth step routing + new setters
src/cli/tui/screens/harness/AddHarnessScreen.tsx Auth type select, provider ARN + scopes inputs
src/cli/tui/screens/harness/AddHarnessFlow.tsx Pass auth config to primitive
src/schema/schemas/primitives/__tests__/harness.test.ts 6 new outboundAuth tests
src/cli/operations/deploy/imperative/deployers/__tests__/harness-mapper.test.ts 4 mapper round-trip tests

Test plan

  • Schema tests: all 3 outboundAuth variants accepted, invalid rejected, credentialProviderName rejected with migration message (6 tests)
  • Mapper tests: round-trip for awsIam/none/oauth/omitted (4 tests)
  • CLI happy paths: add tool with each auth type, verify harness.json output (5 cases)
  • CLI error cases: invalid auth type, missing oauth fields, invalid ARN, flag conflicts (9 cases)
  • TUI wizard: full interactive OAuth flow via TUI harness MCP
  • E2E: CreateHarness API accepts outboundAuth config, runtime differentiates auth types
  • Full test suite: 4081 passed, 8 failed (all pre-existing)
  • agentcore validate surfaces credentialProviderName migration message

…teway tools

The CLI's harness schema for agentcore_gateway tools had a
credentialProviderName field that didn't exist in the harness service
model. The service expects an outboundAuth union with three members:
awsIam (SigV4), none, and oauth (Bearer token via AgentCore Identity).

- Replace credentialProviderName with outboundAuth union in harness
  schema (awsIam | none | oauth with providerArn, scopes, grantType,
  customParameters)
- Add superRefine to reject legacy credentialProviderName with
  migration message
- Add --outbound-auth, --provider-arn, --scopes, --grant-type flags
  to `agentcore add tool` command
- Add outbound auth type selection to TUI harness wizard (3 new steps)
- Update HarnessPrimitive to build outboundAuth config from options
- Add schema tests for all outboundAuth variants and mapper round-trip
  tests
When --outbound-auth is set to awsIam or none, the CLI now rejects
--provider-arn, --scopes, and --grant-type instead of silently
ignoring them.
- CLI help: indicate awsIam is the default when --outbound-auth is
  omitted, add scope format examples to --scopes description
- TUI: mark AWS IAM option as "(default)" in gateway auth selector
@aidandaly24 aidandaly24 requested a review from a team May 1, 2026 16:14
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label May 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 43.35% 9864 / 22750
🔵 Statements 42.61% 10472 / 24572
🔵 Functions 40.39% 1666 / 4124
🔵 Branches 39.92% 6344 / 15891
Generated in workflow #2297 for commit aec2546 by the Vitest Coverage Report Action

@agentcore-cli-automation
Copy link
Copy Markdown

Silent OAuth fallback in HarnessPrimitive (TUI path) — reintroduces the bug this PR is fixing

In src/cli/primitives/HarnessPrimitive.ts (lines 110–139), when gatewayOutboundAuth === 'oauth' but gatewayProviderArn or gatewayScopes are missing/empty, the else if chain silently falls through and the resulting agentCoreGateway config is emitted without outboundAuth. Since an omitted outboundAuth defaults to SigV4 on the service side, this is exactly the silent "OAuth intended but SigV4 used → 401" failure mode this PR is trying to eliminate.

The TUI path can produce this state today:

  • The scopes TextInput validator only checks value.trim().length > 0, so inputs like ",,," or ", ," pass validation.
  • AddHarnessFlow.tsx then does scopes.split(',').map(s => s.trim()).filter(Boolean), which yields [].
  • HarnessPrimitive sees gatewayScopes.length > 0 is false, falls through, writes agentCoreGateway with no outboundAuth, and the user ends up deployed on SigV4 again.

The CLI flag path (tool-action.ts) correctly returns an error when the post-split scopes array is empty, so the gap is specifically in the TUI + primitive.

A few options to fix:

  1. Throw in HarnessPrimitive when gatewayOutboundAuth === 'oauth' but providerArn/scopes aren't valid — this makes the invariant explicit rather than silently degrading. (Symmetric with tool-action.ts behavior.)
  2. Tighten the TUI scopes validator to validate the post-split result, e.g. value.split(',').map(s => s.trim()).filter(Boolean).length > 0 ? true : 'At least one non-empty scope is required'. (Plus maybe still do option 1 as a defense-in-depth.)
  3. Validate in AddHarnessFlow.tsx before calling the primitive and surface the error to the user.

Option 1 + 2 together is probably the safest — make the primitive strict about its invariants, and catch bad input earlier in the TUI for a better UX.

@agentcore-cli-automation
Copy link
Copy Markdown

Missing IAM permission for OAuth outbound auth in CDK-vended harness execution role

This PR enables users to configure outboundAuth: { oauth: { providerArn, scopes, ... } } for a gateway tool, but the harness execution role created by the AgentCoreHarnessRole CDK construct in aws/agentcore-l3-cdk-constructs doesn't grant the permissions needed to actually fetch an OAuth2 token at runtime.

Looking at src/cdk/constructs/components/primitives/harness/AgentCoreHarnessRole.ts in the constructs repo, the role only grants bedrock-agentcore:GetResourceApiKey (conditionally, for model API keys). It doesn't grant bedrock-agentcore:GetResourceOauth2Token on the OAuth2 credential provider / token vault, which is what the harness will need to call the credential provider when outboundAuth.oauth is configured (cf. the equivalent policy in components/mcp/Gateway.ts and AgentCoreRuntime.ts).

Since harness-deployer.ts resolves executionRoleArn from CDK outputs by default, any user who follows the default path and configures oauth outbound auth will deploy a harness whose role can't fetch the token → runtime 403 instead of the 401 they had before. Users who supply their own harnessSpec.executionRoleArn would be unaffected, but that's not the default experience.

This is cross-repo so it doesn't necessarily need to land in this PR, but it should either:

  1. Ship together with a companion PR to aws/agentcore-l3-cdk-constructs that adds GetResourceOauth2Token (and any related GetWorkloadAccessToken if not already covered) scoped to the token vault / oauth2credentialprovider ARN when a gateway tool has outboundAuth.oauth, and bump the pinned constructs version here, or
  2. Be tracked as a follow-up with a clearly filed issue referenced from the PR description, so users who pick this up on preview aren't surprised.

Worth calling out explicitly in the PR description either way so the full fix isn't lost.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label May 1, 2026
Copy link
Copy Markdown
Contributor

@notgitika notgitika left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Contributor

@tejaskash tejaskash left a comment

Choose a reason for hiding this comment

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

Good PR -- fixes a real customer issue with a clean, well-tested approach. Three items to consider.

Comment thread src/cli/primitives/HarnessPrimitive.ts
Comment thread src/schema/schemas/primitives/harness.ts
Comment thread src/cli/tui/screens/harness/useAddHarnessWizard.ts
@notgitika
Copy link
Copy Markdown
Contributor

^ these can be follow up PRs

@notgitika notgitika merged commit f818286 into preview May 1, 2026
20 checks passed
@notgitika notgitika deleted the feat/harness-outbound-auth branch May 1, 2026 16:25
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.

4 participants