[SPARK-58658][CONNECT] Do not return redacted configurations from the Config RPC - #57892
Open
alexandrefimov wants to merge 1 commit into
Open
[SPARK-58658][CONNECT] Do not return redacted configurations from the Config RPC#57892alexandrefimov wants to merge 1 commit into
alexandrefimov wants to merge 1 commit into
Conversation
… Config RPC The Config RPC read paths return any configuration that reached SparkConf, including entries the connecting client never held. Withhold entries matching spark.redaction.regex, reporting them the way each operation reports an unset key: Get fails, GetWithDefault returns the caller's default, GetOption returns no value and GetAll omits the entry. Matching follows Utils.redact and covers the key or the value, so a secret carried by an innocuous key, such as a password inside a JDBC URL, is withheld as well. SET already masks that case through SQLConf.redactOptions. The pattern is read from the SparkConf rather than from the session config, which the client can write. GetAll filters on the full key, before the requested prefix is stripped.
Contributor
Author
|
cc @viirya One deviation from the JIRA text: matching follows The description lists three open questions. The one I would most like your call on: should an entry the client wrote into its own session stay readable? |
uros-b
approved these changes
Aug 10, 2026
Member
|
Thank you @alexandrefimov! |
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.
What changes were proposed in this pull request?
The four read paths of the Config RPC —
Get,GetWithDefault,GetOptionandGetAll— stop returning configuration entries that matchspark.redaction.regex. A withheld entry is reported the way that same operation already reports an unset key:Getfails withSQL_CONF_NOT_FOUND,GetWithDefaultreturns the caller's default,GetOptionreturns no value andGetAllomits the entry.Three details are worth pointing at.
The pattern is read from the
SparkConf, not from the session config. The session config is client-writable.requireNonStaticConfdoes guardspark.redaction.regex, but that guard is itself controlled byspark.sql.legacy.setCommandRejectsSparkCoreConfs, an ordinary non-static SQL conf, so twoSetcalls would otherwise be enough to clear the filter before reading.Matching covers the key or the value, following
Utils.redact.SetCommandalready redacts throughSQLConf.redactOptions, so a key-only match would leave the Config RPC laxer thanSETover the same configuration — a password inside a JDBC URL is the obvious case. Onlyspark.redaction.regexis applied;spark.sql.redaction.options.regexis deliberately left out, since it exists for SQL command output and its default would withhold every key withurlin its name.GetAllfilters before the requested prefix is stripped. Filtering afterwards would returnspark.my.secret.valueasvaluefor prefixspark.my.secret., walking straight past the pattern.IsModifiableis left as it is: whether a key is modifiable is a property of the name and discloses no value.Why are the changes needed?
The Config RPC discloses anything sensitive that reached
SparkConf, whatever put it there.spark.connect.authenticate.tokenis the one key Spark itself puts there, and it looks benign only because it happens to be the client's own credential.Apache Kyuubi makes the general shape visible. Kyuubi passes its own configuration to the Spark engine through
--confand prefixes every non-spark.key withspark., so the whole engine configuration ends up in the driver'sSparkConf, andSQLConf.mergeSparkConfcopies all of it into the session config. Some of those entries are secrets shared across the deployment rather than owned by the connecting user — a ZooKeeper digest, an internal pre-shared secret. That is a plain client-to-server deployment with no proxy anywhere, and a client reads back secrets it never held.Does this PR introduce any user-facing change?
Yes. A configuration entry whose key or value matches
spark.redaction.regexis no longer returned by the Config RPC, and each read operation reports it as if it were unset.Three consequences I would like reviewers to look at explicitly.
A client can no longer read back an entry it set itself in its own session: after
spark.conf.set("spark.sql.catalog.mycat.password", …), reading that key back now fails. Classic Spark still returns it. The filter could be narrowed to keys present insparkContext.conf, which would keep session-local entries readable; I did not do that, because it would let a secret written into the session config server-side — by a plugin or an extension rather than throughSparkConf— stay readable. That trade is a judgement call and I am happy to switch.A batched
Getfails as a whole if any key in the batch is withheld, since that is how a single unset key in a batch already behaves. With the default pattern none of the keys the clients batch internally match, but an operator who widensspark.redaction.regexfar enough could turncreateDataFrameinto an error rather than a hidden value.An empty
spark.redaction.regexmatches every key, so setting it to an empty string — a plausible attempt to turn redaction off — now withholds the entire configuration.Utils.redactdegrades the same way, so I did not special-case it here, but it is worth a decision.How was this patch tested?
New
SparkConnectConfigHandlerSuitecovers the five read operations, the prefix-stripping order, the value match, and that the pattern is not taken from the session config.SparkConnectAuthSuitegains an end-to-end assertion that the authentication token is not readable while a non-sensitive server-side configuration still is.10 tests, all passing. With the handler reverted to master, 8 of the 10 fail; the two that still pass are the
IsModifiablecase, whose behaviour is deliberately unchanged, and the pre-existing authentication test.Was this patch authored or co-authored using generative AI tooling?
Yes — Claude Code (Opus 5) was used for code reading, drafting and review. Every line was reviewed by the author, who takes responsibility for the patch.