Skip to content

Persist resolved CIMD clients so Redis session rehydration finds them - #6284

Draft
alex-feel wants to merge 1 commit into
stacklok:mainfrom
alex-feel:cimd-client-persistence
Draft

Persist resolved CIMD clients so Redis session rehydration finds them#6284
alex-feel wants to merge 1 commit into
stacklok:mainfrom
alex-feel:cimd-client-persistence

Conversation

@alex-feel

Copy link
Copy Markdown

Closes #6187

Problem

RedisStorage's session rehydration (unmarshalRequester) resolves the session's client through the bare storage's own GetClient row lookup — never through the CIMDStorageDecorator. A CIMD client is resolved dynamically at authorize time and never persisted, so at the token endpoint the lookup fails and every exchange for a CIMD client ends in a bare invalid_grant, with no server-side log line. Memory storage keeps the live client object, so only the CIMD × Redis combination breaks (see #6187 for the analysis and repro).

Change

Of the two directions proposed in the issue, this implements the persistence one, as laid out in #6187 (comment):

  • On every successful CIMD document fetch, the decorator best-effort persists the resolved client into the underlying storage via RegisterClient (write-through; a persistence failure WARN-logs and does not fail the resolution).
  • The persisted client is marked DCR-issued (registration.MarkDCRIssued gains a *LoopbackClient arm for the loopback-wrapped CIMD shape), so the row carries the same anti-bloat TTL as DCR registrations and RenewClientTTL keeps actively-used rows alive — unauthenticated /oauth/authorize traffic can mint these rows, so they must never be permanent.
  • Rehydration reads the persisted snapshot without a document re-fetch, so established sessions also survive pod restarts (the decorator's LRU is per-instance memory) and document rotation mid-session.
  • Diagnosability: unmarshalRequester now WARN-logs the client id and the wrapped error when the client lookup fails, so this failure mode is no longer silent server-side.

Tests

Note: #6283 touches other parts of the same decorator file; the two PRs are independent and either can land first.

Redis session rehydration resolves the session's client through the bare
RedisStorage row lookup, never through the CIMD storage decorator, so a
CIMD client that was resolved dynamically at authorize time was not found
at the token endpoint and every exchange failed with a bare
invalid_grant.

Persist the resolved client into the underlying storage on every
successful document fetch (best-effort write-through), marked DCR-issued
so the row carries the same anti-bloat TTL as DCR registrations.
Rehydration then finds the persisted snapshot without a document
re-fetch, so established sessions also survive pod restarts and document
rotation. The rehydration client lookup now also logs the client id and
the wrapped error, which previously left no server-side trace.

Closes stacklok#6187

Signed-off-by: Aleksandr Filippov <71711753+alex-feel@users.noreply.github.com>
@alex-feel
alex-feel force-pushed the cimd-client-persistence branch from e17c040 to de0cb7c Compare August 16, 2026 01:55
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.

Redis storage rehydrates sessions past the CIMDStorageDecorator, so CIMD clients fail every token exchange with invalid_grant

1 participant