Skip to content

fix: source aware api-key flag + redact api key value from logging#1819

Open
nborges-aws wants to merge 1 commit into
refactorfrom
identity-fast-follow
Open

fix: source aware api-key flag + redact api key value from logging#1819
nborges-aws wants to merge 1 commit into
refactorfrom
identity-fast-follow

Conversation

@nborges-aws

Copy link
Copy Markdown
Contributor

Description

Expand api-key-credential-provider create/update operations with full source-aware flag surface.

Changes:

  • Source-aware --api-key: accepts inline values, file://path, or stdin so credentials never appear in shell history
  • External secrets: --api-key-secret-arn + --api-key-secret-json-key for existing Secrets Manager entries
  • Mutual exclusivity: --api-key and the pair of external secret cannot be mixed; the secret pair requires both values
  • Tags: --tags on create (JSON object)
  • Sensitive flag: --api-key marked sensitive so values are redacted from debug logs
  • readSource / readSourceText utility for source-aware flag values. Follows @aidandaly24 pattern for runtime invoke, but moved to shared location and adds convenience method for decoding to text value.
  • added unit tests for source utilities, and mutual exclusivity tests for source-aware create/update identity
  • updated fixture tests after latest changes

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

How have you tested the change?

  • I ran npm run test:unit and npm run test:integ
  • I ran npm run typecheck
  • I ran npm run lint
  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@github-actions github-actions Bot added agentcore-harness-reviewing AgentCore Harness review in progress and removed agentcore-harness-reviewing AgentCore Harness review in progress labels Jul 23, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.62069% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.88%. Comparing base (272e50e) to head (7538666).

Files with missing lines Patch % Lines
...ntity/api-key-credential-provider/update/index.tsx 95.45% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #1819      +/-   ##
============================================
+ Coverage     94.84%   94.88%   +0.03%     
============================================
  Files           143      144       +1     
  Lines          7120     7227     +107     
============================================
+ Hits           6753     6857     +104     
- Misses          367      370       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

"JSON key containing the API key in the secret",
z.string().optional(),
),
flag("tags", "tags as key=value (repeatable) or JSON object", z.string().optional()),

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.

This advertises repeatable key=value tags or a JSON object, but z.string() plus parseJsonFlag only accepts one JSON value. For example, --tags env=prod currently fails as invalid JSON. Could we implement and test both documented forms, including validating that the JSON form is a string map?

flag("api-key", "the API key value (inline, file://path, or -)", z.string().optional(), {
sensitive: true,
}),
flag("api-key-secret-arn", "existing Secrets Manager secret ARN", z.string().optional()),

@aidandaly24 aidandaly24 Jul 23, 2026

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.

In the doc discussion, the preferred external-secret representation was one structured-reference flag rather than separate ARN and JSON-key flags. Could we use something like --api-key-secret-reference '{"secretId":"...","jsonKey":"..."}' for create/update, mutually exclusive with --api-key? We should also have a successful external-reference request-mapping test, I think the current tests only cover invalid combinations.

Update should first retrieve the provider and preserve its existing apiKeySecretSource. A MANAGED provider should accept only --api-key, while an EXTERNAL provider should accept only the structured secret reference. I think we should reject mismatched input locally and test both directions instead of deriving the source mode from the supplied flags.

Comment thread src/handlers/source.tsx
// - "file://path" reads the file at path
// - "-" reads stdin to EOF
// - anything else is returned as-is (inline value encoded as UTF-8)
export async function readSource(

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.

I already implemented a version of source-aware input on another branch and I think it has some features we can use. Can we use that implementation (pasted below) as the shared behavior? The shared reader should remain byte-oriented so Runtime payloads are not decoded, while text-only credentials use strict UTF-8 decoding:

import { readFile } from "node:fs/promises";
import { addAbortSignal } from "node:stream";
import { buffer } from "node:stream/consumers";

export async function readSource(
  source: string,
  stdin?: NodeJS.ReadStream,
  signal?: AbortSignal,
): Promise<Uint8Array> {
  signal?.throwIfAborted();

  if (source.startsWith("file://")) {
    const path = source.slice("file://".length);
    try {
      return await readFile(path, { signal });
    } catch (error) {
      if (error instanceof Error && error.name === "AbortError") throw error;
      throw new TypeError(`unable to read source file: ${path}`);
    }
  }

  if (source !== "-") {
    return new TextEncoder().encode(source);
  }
  if (!stdin) {
    throw new TypeError("stdin is not available for this source");
  }

  return buffer(signal ? addAbortSignal(signal, stdin) : stdin);
}

export async function readSourceText(
  source: string,
  stdin?: NodeJS.ReadStream,
  signal?: AbortSignal,
): Promise<string> {
  const bytes = await readSource(source, stdin, signal);
  try {
    return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
  } catch {
    throw new TypeError("source must contain valid UTF-8");
  }
}

Runtime can import these functions while retaining its request-specific dual-stdin validation. Identity can use readSourceText for --api-key. What do you think? I can also make the change in my Runtime invoke PR so not a problem really just a suggestion.

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.

3 participants