Repository navigation
Conversation
Without P_CLUSTER_SECRET, create_intracluster_auth_headermap forwarded
the caller's browser cookie to peers when the request had no
Authorization header. Sessions exist only on the node that issued them,
so ingestors rejected every user and role sync made from the UI ("Your
session has expired..."), and the querier only logged it. Users created
in the UI could not ingest, roles created in the UI were missing, and
roles removed in the UI stayed in effect on ingestors until restart.
Fall back to the node token instead. The querier has already authorized
the caller, and the ingestor sync handlers reconcile from storage, so
authenticating as the node grants nothing beyond what storage says.
The Prism field-stats path called the helper with an empty node token;
it now forwards only the caller's Authorization header and otherwise
lets send_query_request use the querier's token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep main's Result-returning build_intracluster_auth_headermap and drop its cookie branch. Its cookie-copy test now asserts the cookie is replaced by the node token, and the unused-generated-text test copies an Authorization header instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sync_streams_with_ingestors copied every caller header, including the
session cookie, so a stream created or updated from the UI was rejected
by ingestors ("session ... no longer valid"). Drop the cookie and, when
no other credential (Authorization, X-API-KEY, cluster secret) is left,
authenticate with the ingestor's node token.
The Prism dataset-stats path no longer passes no auth to
send_query_request when there is no cluster secret and no Authorization
header. That fell back to the querier's root token, which skips the
per-dataset checks the querier runs for the caller. It now returns an
error asking for P_CLUSTER_SECRET instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The node token authenticates as root in the default tenant, so an ingestor given a tenant's stream sync with it would create or update the stream in the default tenant. Without a caller credential, a tenant's stream sync now fails (and is logged) and asks for P_CLUSTER_SECRET, as the other multi-tenant cluster paths do. A node token that can't be encoded now fails only that node's sync as a logged sync error. The stream already exists locally, so it is not returned as a header-build error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Without
P_CLUSTER_SECRET(never set in this fork), querier→ingestor syncs forwarded the caller's browserCookieheader whenever the request had noAuthorizationheader. Sessions exist only on the node that issued them, so every user, role, and stream sync made from the UI was rejected by the ingestor withYour session has expired or is no longer valid. The querier only logs that error, so the UI showed success.Two places did this:
create_intracluster_auth_headermap, used by the user and role syncs.sync_streams_with_ingestors, which copied every caller header.Reproduction (1 querier + 1 ingestor + MinIO, UI-style cookie login)
For E, ingest still worked before the fix, because ingestors load unknown streams from storage. But stream updates made in the UI never reached live ingestors.
Fix
src/utils/mod.rs): with no cluster secret, the caller'sAuthorizationheader is forwarded if present. Otherwise the request authenticates as the node withnode_token. Cookies are never forwarded. Authenticating as the node grants nothing extra: the querier has already authorized the caller, and every mounted ingestor sync handler reconciles from storage and ignores the request body (Ingestors install the stored role on role sync #78, Ingestors install the stored user on user sync, so role revocations take effect #80).src/handlers/http/cluster/mod.rs):sync_streams_with_ingestorsdropsCookie. If no other credential remains (Authorization,X-API-KEY, or the cluster secret), it uses the ingestor's node token, but only for default-tenant streams. The node token is root in the default tenant, and the ingestor's stream handler trusts the request's headers and body, so a tenant's stream would land in the default tenant. A tenant's stream sync without a credential now fails and is logged, asking forP_CLUSTER_SECRET. A node token that can't be encoded fails only that node's sync.src/storage/field_stats.rs): without a cluster secret, the dataset-stats path forwards only the caller'sAuthorizationheader and otherwise returns an error asking forP_CLUSTER_SECRET. Falling back to the querier's root token there would skip the querier's per-dataset checks for the caller. Prism mode is disabled at startup in this fork, so this path is unreachable today; it now fails closed if Prism is ever turned on.Known limitation
In multi-tenant mode without a cluster secret, the node-token fallback runs as root in the default tenant. Tenant-scoped syncs (user delete, role add/remove, password reset) then reconcile the same user ID in the default tenant, which is effectively a no-op. The tenant's change still doesn't reach ingestors, which is no worse than before, when the sync was rejected outright. This now applies to UI (cookie) callers too, not only callers with no credentials. Distributed multi-tenancy needs
P_CLUSTER_SECRETanyway (seeotel_generator.rsandtraces.rs).🤖 Generated with Claude Code