feat(credentials): configurable audience for keyless AWS, Databricks, Snowflake, Microsoft, and Google credentials

Merged
WA
2d ago
+1229-211

Summary

  • Keyless saved credentials can set their own audience (the aud claim of the token Sim signs). A trust configuration can then pin a value specific to the customer instead of the shared default, so a Sim token isn't accepted somewhere it wasn't meant for. This covers all five keyless providers:
    • AWS: the IAM OIDC provider client ID and the trust policy aud condition
    • Databricks: federation policy audiences. Databricks' own default is the account ID.
    • Snowflake: OIDC_AUDIENCE_LIST. Snowflake's docs warn that the shared snowflakecomputing.com allows cross-account reuse.
    • Microsoft Entra: the federated credential's single audience
    • Google: the provider's allowedAudiences. STS still exchanges at the provider resource name.
  • One shared mechanism in workload-identity/audiences.ts:
    • a submit schema: at most 255 characters (AWS's client ID cap), limited to URI/ID characters so every setup snippet pastes without escaping, and refusing another cloud's default audience;
    • a stored field schema;
    • storedAudienceField, which stores nothing for the default.
  • Same audience everywhere: every mint uses the stored audience, including the connect-time subject-pin probe, so the probe tests what runs will present.
  • Reconnect: reopens on the stored audience. Each provider now has one stored<X>ReconnectFields reader (one parse) instead of separate auth-type and audience readers.
  • Connect dialogs: an editable Audience field, defaulting to the current value. The trust snippets update to match: AWS trust policy, Databricks policy command, Snowflake CREATE USER, gcloud --allowed-audiences.
  • Docs, API and CLI: each provider page has a "use your own audience" section. The API and CLI document keylessConfig.audience.
  • Backward compatibility: credentials saved without an audience mint exactly the old default and keep the same stored shape, so the old strict schemas still read them. A custom-audience credential is refused by older pods during a mixed-version window; it is never sent with the wrong audience.

Type of Change

  • New feature

Testing

  • Each provider's server tests cover:
    • a custom audience in verification, the pin probe and runs;
    • default stored shape unchanged;
    • cross-cloud refusal before any network call;
    • the error copy naming the audience;
    • the Microsoft token cache, which never serves a token minted for an old audience.
  • prepare-workload-identity covers reconnect reopening on a custom audience for all five providers. audiences.test.ts covers the shared schema.
  • Revert proofs: each guard was reverted and its test went red.
  • 1,841 tests pass across lib/credentials, app/api/v2/credentials and lib/api/contracts, plus 554 sim-cli tests.
  • bun run lint and check-block-registry.ts origin/staging pass.
  • These audits pass: check:openapi, check:cli-api, check:cli-docs, check:mcp-operations, check:api-validation:strict, check:test-patterns, check:comment-hygiene, check:explicit-any, check:client-boundary, check:boundaries, check:utils, check:file-names and check:docs.
  • Type-check and the full suite run in CI.
  • I checked each provider's official docs for custom-audience support and syntax (IAM CreateOpenIDConnectProvider, Databricks federation policy API, Snowflake workload identity federation, Entra federated identity credentials, Google workload identity pool providers).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)