Skip to content

[BUG] API-exposed authentication modes fail with gateway credential injection #2873

Open

Description

@EItanya

After #2868 switched runtime credentials to Substrate v0.2.0-beta4 gateway injection, several authentication modes exposed by the public API can no longer be compiled. Gateway bindings support static HTTP headers; the affected modes need credentials inside the runtime for signing or token exchange.

Affected components: harness compilation, ModelConfig/Harness APIs, model-provider discovery, and UI configuration.

Authentication modes broken by the merge

All resource field paths below refer to kagent.dev/v1alpha3.

Authentication mode API fields that enable it Current failure / affected harnesses
AWS Bedrock IAM / SigV4 ModelConfig.spec.provider: Bedrock, spec.bedrock.region, and spec.apiKeySecret referencing AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, optionally AWS_SESSION_TOKEN kagent, BYO, Claude, and Codex generate secret-backed signing environment variables that the shared credential compiler rejects. There is no separate authentication-mode field; the Secret contents select this path. Bedrock bearer-token authentication through AWS_BEARER_TOKEN_BEDROCK remains supported.
Google service-account authentication for Claude on Vertex AI ModelConfig.spec.provider: AnthropicVertexAI, spec.anthropicVertexAI, spec.apiKeySecret, and spec.apiKeySecretKey referencing service-account JSON Claude generates KAGENT_CLAUDE_GOOGLE_CREDENTIALS_JSON for its GOOGLE_APPLICATION_CREDENTIALS flow; the shared credential compiler rejects this secret-backed environment variable.
SAP AI Core OAuth client credentials ModelConfig.spec.provider: SAPAICore, spec.sapAICore.{baseUrl,resourceGroup,authUrl}, and spec.apiKeySecret containing client_id and client_secret kagent/BYO generate SAP_AI_CORE_CLIENT_ID and SAP_AI_CORE_CLIENT_SECRET; the shared credential compiler rejects them. apiKeySecretKey is not used for this provider. SAP caller-token passthrough remains implemented, so this is specifically the client-credentials path.
Arbitrary runtime secret environment variables Harness.spec.env[].credentialRef.{name,key,optional} The shared compiler rejects every credentialRef, across all harness compilers, regardless of the variable name. The field is still accepted by the CRD schema.

The shared compiler reports errors such as:

environment credential "AWS_SECRET_ACCESS_KEY" cannot use gateway header injection; local signing and arbitrary secret environment variables are unsupported

For Harness credential references:

Harness environment "<name>": arbitrary credentialRef values cannot be injected into HTTP headers; configure credentials on ModelConfig or RemoteMCPServer

Related API paths already unsupported before this merge

These are current failures, but were not introduced by #2868:

  • Google service-account authentication in kagent/BYO: ModelConfig.spec.provider: GeminiVertexAI or AnthropicVertexAI, the corresponding spec.geminiVertexAI / spec.anthropicVertexAI block, and spec.apiKeySecret / spec.apiKeySecretKey. These paths construct a Secret volume and set GOOGLE_APPLICATION_CREDENTIALS to a file under /creds. Compilation already rejected the required volume mounts. The forms without a Secret can compile and rely on ambient Google credentials; that does not establish that authentication works in the provisioned runtime.
  • GDCH service-account token exchange: ModelConfig.spec.provider: OpenAI, spec.openAI.tokenExchange.type: GDCHServiceAccount, spec.openAI.tokenExchange.gdchServiceAccount.audience, and spec.apiKeySecret / spec.apiKeySecretKey. This also requires a credential-file mount already rejected by kagent/BYO compilation.
  • Custom upstream CA Secret mounts: ModelConfig.spec.tls.caCertSecretRef/caCertSecretKey and RemoteMCPServer.spec.tls.caCertSecretRef/caCertSecretKey. kagent/BYO reject the volume requirements. Native model compilers reject TLS configuration; native MCP compilers ignore it with a compatibility warning. This is not a claim that every TLS field is rejected in every harness.

API surfaces still exposing these modes

  • Kubernetes ModelConfig provider enum, provider-specific configuration blocks, and credential fields.
  • Kubernetes Harness.spec.env[].credentialRef.
  • ModelService.ListSupportedModelProviders and ListSupportedModels still list the Vertex and SAP providers without describing these runtime authentication restrictions.
  • ModelService.CreateModelConfig and UpdateModelConfig expose a generic resource plus api_key / secrets inputs through which these configurations can be submitted. The restrictions are encountered during compilation rather than expressed in those request schemas.
  • The UI still exposes these provider choices, Secret references, and custom CA fields.

Scope and evidence

This report is based on a source and pre-merge history audit at 850c4647, not live cloud-provider authentication tests.

Ordinary OpenAI, Anthropic, Azure OpenAI, Foundry, and Gemini API-key bindings, Bedrock bearer tokens, and Secret-backed MCP headers remain implemented. The failures above do not imply that every authentication mode of each named provider is broken.

Relevant source:

Activity

  1. yashrajshuklaaa commented on Sep 20, 2026

    @yashrajshuklaaa
    Contributor

    @EItanya I'd like to work on this if it's still free.

    I've read through the code and this is what I'd propose for a first PR. ResolveModelConfig already feeds SemanticFailures into the Accepted condition on ModelConfig, so I could report the unsupported modes there (Bedrock IAM keys, SAP client credentials, Vertex with an apiKeySecret, GDCH) as Accepted=False with reason UnsupportedCredentialMode. Right now users only see a generic error on the AgentTemplate that names an env var, not the ModelConfig.

    I haven't written any code yet. Before I start, three questions:

    1. Is a status condition OK, or would you rather use CEL rules on the CRD?
    2. Is a Substrate-side fix planned? If so, this would just be a temporary guard.
    3. Is it OK to leave Harness credentialRef, custom CA Secrets, and the discovery/UI warnings for later PRs?

    If that works, could you assign it to me?

  2. QuentinBisson commented on Sep 22, 2026

    @QuentinBisson
    Contributor

    One more mode belongs in the table, though #2868 did not break it, since it never existed upstream: a skill or plugin source on a private git repository. The materialiser clones with the process environment and no helper, so spec.skills[].source.git and spec.plugins[].source.git cannot point at a private repository. It needs the same decision as the rows above: a credential inside the runtime (a git credential helper reading a Secret-backed variable, which the shared compiler now rejects), or a gateway binding for the source host. #2899 is a draft of the second shape, credentialRef per source compiled to Authorization: Basic for the host. A Harness-level list of host bindings would cover it as well, together with any other static header an admitted agent needs, if that is the direction you take for this issue.

  3. QuentinBisson commented on Oct 15, 2026

    @QuentinBisson
    Contributor

    For the Bedrock IAM and Vertex rows: we route both through the egress-side gateway rather than carrying signing credentials into the runtime. Vertex works for us with a credential provider that mints a Google access token from the service-account key at fetch time (the shape of #2888 and kagent-dev/substrate#47, carried in our fork), so the compiler binds authorization: Bearer on the Vertex hostname to that provider's authority and Claude Code runs with CLAUDE_CODE_SKIP_VERTEX_AUTH=1. Bedrock with IAM keys we do not bind per ModelConfig at all: the LLM gateway (agentgateway's Bedrock provider with an assumed role) takes Anthropic-format requests, so agents keep an Anthropic ModelConfig. If a maintainer wants the Vertex binding upstream, the provider side belongs in a plugin provider rather than the reference Kubernetes provider; happy to file it that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions