Add cluster interserver-secret authentication#1
Open
BorisTyshkevich wants to merge 2 commits intomainfrom
Open
Add cluster interserver-secret authentication#1BorisTyshkevich wants to merge 2 commits intomainfrom
BorisTyshkevich wants to merge 2 commits intomainfrom
Conversation
Allows a client to authenticate as a trusted ClickHouse cluster peer by
sharing the cluster secret instead of a user password, and to execute each
query as an arbitrary `initial_user` which the server accepts via
`AlwaysAllowCredentials`. This mirrors the existing distributed-query
protocol documented in `src/Server/TCPHandler.cpp`.
- `Options.Cluster{Name, Secret}` configures interserver mode.
- `WithInitialUser` sets the impersonated user per query (falls back to
`Auth.Username`).
- Hello sends `" INTERSERVER SECRET "`, empty password, cluster name, and
a 32-byte random salt when `Cluster.Secret` is set.
- Each query encodes `SHA256(salt + secret + body + id + initial_user)`
into the interserver-secret slot and flips `ClientQueryInitial` to
`ClientQuerySecondary`. When `Cluster.Secret` is empty the slot stays
the legacy empty string, so existing callers are unaffected.
- Driver advertises protocol 54460, so nonce and externally-granted-roles
wire additions from `DBMS_MIN_REVISION_WITH_INTERSERVER_SECRET_V2`
(54462) and later are intentionally omitted.
Unit tests in `lib/proto/query_interserver_test.go` cover the hash layout
and verify the empty-secret branch preserves the legacy empty slot.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
BorisTyshkevich
added a commit
to Altinity/altinity-mcp
that referenced
this pull request
Apr 20, 2026
Stops requiring a shared ClickHouse username/password for altinity-mcp's gated deployments. When `clickhouse-cluster-secret` is set, altinity-mcp handshakes with ClickHouse as a trusted cluster peer using the shared secret and executes each query as the MCP-authenticated user (taken from OAuth claims or the configured `clickhouse-username`). - Add `ClusterName`/`ClusterSecret` to `ClickHouseConfig` with matching CLI flags (`--clickhouse-cluster-name`, `--clickhouse-cluster-secret`) and `CLICKHOUSE_CLUSTER_*` env vars. - Reject invalid combinations early: interserver auth is TCP-only and requires a non-empty cluster name. - Wire `ClusterCredentials` through `clickhouse.Open` and drop the static password when the secret is set, so only the secret reaches the wire. - In OAuth gating mode, override `chConfig.Username` with the OAuth `Subject` when the cluster secret is active so `system.query_log` attributes the query to the end user. Requires the Altinity/clickhouse-go fork which implements the protocol extension (see Altinity/clickhouse-go#1). The `go.mod` uses a local-path replace during development — see the in-file comment for the follow-up resolution path. Adds `pkg/clickhouse/cluster_secret_test.go` which spins up `clickhouse/clickhouse-server` with a `<remote_servers>` cluster and passwordless users (`alice`, `bob`), then verifies `SELECT currentUser()` returns the impersonated user, that switching Username switches the effective user, and that a wrong secret is rejected. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
5 tasks
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.
Summary
Teaches the driver how to authenticate as a trusted cluster peer using ClickHouse's shared interserver secret, so callers can execute queries as an arbitrary
initial_userwithout a per-user password. This is the same protocol ClickHouse servers use between cluster nodes for distributed queries.Options.Cluster{Name, Secret}turns interserver mode onWithInitialUser(user)sets the impersonated user per query (falls back toAuth.Username)" INTERSERVER SECRET "+ empty password + cluster name + 32-byte random saltSHA256(salt + secret + body + id + initial_user)andClientQueryInitialis flipped toClientQuerySecondaryDriver advertises protocol 54460, so nonce + external-roles additions from
DBMS_MIN_REVISION_WITH_INTERSERVER_SECRET_V2(54462) are intentionally omitted. Matchessrc/Server/TCPHandler.cpp::processQueryinterserver branch.Test plan
go test -count=1 ./lib/proto/ -run Interserver— newquery_interserver_test.gocovers empty-secret → empty slot, hash layout matches ClickHouse, hash differs per userclickhouse/clickhouse-serverwith a cluster secret, connects withCluster.Secretset, and verifiesSELECT currentUser()returns the impersonated user and that a wrong secret is rejectedNotes for reviewers
Cluster.Secret == ""is a short-circuit everywherestring(h.Sum(nil))(raw 32 bytes) to match ClickHouse'sencodeSHA256which returns binary, not hexClickHouse/clickhouse-go(main HEADd280a2aat branch time); upstream PR is a follow-up if desired🤖 Generated with Claude Code