Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/kubernetes-credential-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ directly over mTLS to inject credentials into HTTP and intercepted HTTPS request
entry in that Kubernetes Secret. The `default` locator and an explicit key are required.
The provider reads Kubernetes on every fetch and never persists or logs values.
AGW caches successful credentials per actor and URI for five minutes, so rotation
can take that long to reach injected requests.
can take that long to reach injected requests. A provider bounds that reuse with
`FetchSecretResponse.max_age`: zero fetches the credential again for every
request, and no answer is reused past the five minutes. This provider leaves it
unset.

A credential that is minted rather than read, such as the Google access token a
Vertex AI actor needs, is the business of a provider of its own under its own
Expand Down
4 changes: 4 additions & 0 deletions docs/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,10 @@ survive it.
- **During the roll:** an actor image only a pull secret can read is pulled
once its node's atelet runs 1.18; a 1.17 atelet still pulls it
anonymously or through the providers, as before.
- **Credential providers:** `FetchSecretResponse` gains `max_age`, how long
the injector may reuse an answer. A provider of 1.17 never sets it and
keeps the injector's default; atenet's injector caches nothing, so it
fetches every request whichever version answers.
- **Goldens:** kept.
- **Reset:** none. **Conversations lost:** none.

Expand Down
29 changes: 29 additions & 0 deletions fork/credential-provider-bounds-injector-reuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: credential-provider-bounds-injector-reuse
fork: substrate
theme: credential-injection
category: feature
status: carried
commits:
- 'feat(credprovider): a provider bounds how long the injector reuses its answer'
- "docs(credprovider): say how a provider bounds the gateway's credential cache"
upstream:
outcome: to-file
refs: []
exit: upstream PR merged or declined
depends_on: []
verified: 2026-10-24
---
# A credential provider bounds how long the injector reuses its answer

## Change

`FetchSecretResponse.max_age` in `pkg/proto/credproviderpb/credprovider.proto`: unset keeps the injector's default, zero fetches again for every request, and no injector reuses an answer past its own default. atenet's Go injector keeps no cache and already fetches every request. `docs/kubernetes-credential-provider.md` says how a provider shortens the gateway's credential cache.

## Reason

The egress gateway agentgateway runs caches a secret by actor and URI for a fixed 300 s, so a provider whose answer depends on who acts on the actor at the moment (kagent answering with the token of the person whose turn runs) had it injected after that turn, into another person's next turn on a shared instance included.

## History

`feat/credential-max-age`, [#110](https://github.com/giantswarm/substrate/pull/110) (draft). The gateway side, giantswarm/agentgateway-upstream#37, was closed unmerged on 2026-10-19, parked with the caller credential provider.
38 changes: 27 additions & 11 deletions pkg/proto/credproviderpb/credprovider.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pkg/proto/credproviderpb/credprovider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ syntax = "proto3";

package credprovider;

import "google/protobuf/duration.proto";

option go_package = "github.com/agent-substrate/substrate/pkg/proto/credproviderpb";

// CredentialProvider is the plugin API a secret backend implements so Substrate
Expand Down Expand Up @@ -66,4 +68,10 @@ message FetchSecretRequest {
message FetchSecretResponse {
// The raw bytes contains the secret.
bytes opaque_bytes = 1 [ debug_redact = true ];

// How long the injector may reuse the secret for the same actor and URI.
// Unset keeps the injector's default; zero makes it fetch the secret again
// for every request. An injector never reuses a secret longer than its own
// default, whatever the provider answers.
google.protobuf.Duration max_age = 2;
}
Loading