Support application-supplied SSLContext in client-v2 and jdbc-v2#2918
Conversation
Adds a way to inject a fully pre-built javax.net.ssl.SSLContext so trust/key material can be assembled in memory and never written to disk - the use-case from #2909 (diskless TLS behind connection pools such as HikariCP). client-v2: - New ClientConfigProperties.SSL_CONTEXT ("ssl_context"). It holds a live object, so it is never parsed from or represented as a string. - Client.Builder.setSSLContext(SSLContext) stores the context and it is injected into the parsed (object) configuration in the Client constructor. - HttpAPIClientHelper.createSSLContext returns the supplied context as is, bypassing the trust/key material builder. ssl_mode still governs server hostname verification at the socket-factory layer. jdbc-v2: - JdbcConfiguration accepts a live SSLContext under the ssl_context key in the connection Properties (scoped relaxation of the string-only validation; any other non-string value still throws) and forwards it to the client builder. Tests: client-v2 ClientBuilderTest (builder plumbing + createSSLContext short-circuit) and jdbc-v2 JdbcConfigurationTest (Properties capture, forwarding to the builder, and that other non-string values are still rejected). Examples (client-v2 and jdbc SSLExamples) and docs/features.md updated. Fixes: #2909 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Repository collaborators can run the JMH benchmark suite against this PR by commenting: Optional regression threshold override (Δ% on Time or Alloc/op; defaults to 10%): Only one benchmark run per PR is active at a time — issuing a new |
Client V2 CoverageCoverage Report
Class Coverage
|
JDBC V2 CoverageCoverage Report
Class Coverage
|
JDBC V1 CoverageCoverage Report
Class Coverage
|
Client V1 CoverageCoverage Report
Class Coverage
|
…erial Addresses review feedback on custom SSLContext support (#2918): - client-v2 and jdbc-v2 now reject a string `ssl_context` value (ClientMisconfigurationException / SQLException) instead of silently ignoring it. The property carries a live object only; a textual value parsed to null and either dropped or caused a ConcurrentHashMap NPE. - Skip the trust-store/client-certificate conflict check in Client.Builder.build() when a custom SSLContext is supplied, because that trust/key material is ignored in that case (per the documented contract and createSSLContext's short-circuit). - Update docs/features.md to document both refinements.
TriageCategory: Summary What this impacts
Concerns
Required reviewer action
|
|
@chernser addressed the review feedback in 73ff7da:
Added 5 regression tests (verified failing before / passing after the fix) and updated |
|
@chernser — ready for another look. The one remaining Cursor Bugbot comment (textual I left that thread open because it raises one genuine design question I'd like your call on: when a user supplies both a live |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
1 issue from previous review remains unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 73ff7da. Configure here.
- Reject trust/key material options when a custom SSLContext is supplied (except ssl_mode) instead of silently ignoring them - Move the custom-vs-built context selection from createSSLContext into createHttpClient; createSSLContext now purely builds from material - Reject a textual ssl_context in Builder.setOption as well as build() - Trim obvious comments, shorten setSSLContext javadoc, drop the duplicate enum-constant javadoc - Update tests (per-property rejection via DataProvider, ssl_mode-allowed case, jdbc material-rejection), docs/features.md, examples, and CHANGELOG Implements: #2909
|
@chernser thanks for the review — all 7 comments are addressed in a1f8b04:
Verified locally: client-v2 |
chernser
left a comment
There was a problem hiding this comment.
see the comment. Apply please
…Client Per @chernser review: when the 'ssl_context' configuration value is present but not a javax.net.ssl.SSLContext instance, HttpAPIClientHelper.createHttpClient now throws ClientMisconfigurationException instead of silently falling back to building a context from trust/key material. A null value still builds from material and a real SSLContext is still used as-is. Implements: #2909
|
@chernser addressed your latest review in 7409993.
Added |
|
Resolve conflicts with #2918 (application-supplied SSLContext), which merged to main and touched the same client-v2 SSL surface. Union both SSL features (no behavior change to either): - Client.java: keep both Builder.setSSLCipherSuites(...) and setSSLContext(...) - ClientBuilderTest / JdbcConfigurationTest: keep both sides' test methods - docs/features.md: keep both the cipher-suite and custom-SSLContext bullets - examples client-v2 + jdbc SSLExamples: keep both example methods + call sites - CHANGELOG.md: keep both New Features entries (auto-merged, distinct releases) ClientConfigProperties (SSL_CIPHER_SUITES stays the last enum constant) and HttpAPIClientHelper.createHttpClient (custom-context selection + cipher-suite socket factory) auto-merged cleanly and now integrate both features.




Description
Fixes #2909.
Some deployments assemble their TLS material (certificates + private keys) entirely in memory — fetched and decrypted from a secret store — and are prohibited from writing it to disk, even as temporary files.
client-v2can already build anSSLContextfrom files/PEM, but there was no way to hand it a fully pre-builtjavax.net.ssl.SSLContext, and the JDBC layer rejected any non-StringPropertiesvalue (IllegalArgumentException: Property key and value should be a string), which blocked passing a live context through connection pools such as HikariCP that only exposejava.util.Properties.This PR adds that injection point for client-v2 and jdbc-v2. When a context is supplied it is used as is (the application is responsible for configuring it), and
ssl_modethen only controls server hostname verification — matching the requested behavior.Changes
client-v2
ClientConfigProperties.SSL_CONTEXT("ssl_context"). It carries a live object, so it is never parsed from or represented as a string; it is injected into the parsed (object) configuration directly.Client.Builder.setSSLContext(SSLContext)stores the context; theClientconstructor injects it into the resolved configuration map.HttpAPIClientHelper.createSSLContext(...)returns the supplied context as is and skips building one from trust/key material. Hostname verification is unchanged — still derived fromssl_modeat the connection-socket-factory layer (TRUST/VERIFY_CAskip it,STRICTenforces it).jdbc-v2
JdbcConfigurationcaptures a liveSSLContextsupplied under thessl_contextkey in the connectionProperties(a scoped relaxation of the string-only check — any other non-string value still throws) and forwards it to the underlyingClient.BuilderviasetSSLContext(...).Examples & docs
SSLExamples(both client-v2 and jdbc) gain aconnectWithCustomSSLContextexample that builds the trust material in memory and injects the context (the jdbc one passes it viaProperties.put, since it is not a string).docs/features.mdupdated (client-v2 feature + compatibility notes, jdbc feature + the scopedPropertiesexception).Test
ClientBuilderTest(unit):setSSLContextstores the exact instance in the resolved configuration (and it is absent when not set);createSSLContextreturns the supplied context as is, and still builds its own when none is supplied.JdbcConfigurationTest(unit): a liveSSLContextinPropertiesis accepted (previously threw) and does not leak into the string client properties; it is forwarded to the client builder; and a non-string value under any other key is still rejected.Focused runs:
ClientBuilderTest13/13,JdbcConfigurationTest94/94. Both example projects compile.Pre-PR validation gate
ClientBuilderTest/JdbcConfigurationTeststill passAGENTS.md/docs/changes_checklist.md/docs/features.mddocs/changes_checklist.mdwalkthroughClientConfigProperties.SSL_CONTEXT): keyssl_contextis unique; value typeSSLContext.classis correct; the default isnullandparseValue(null)returnsnull, so it parses to the declared type. It never participates in string config parsing/serialization (injected as an object and skipped byparseConfigMap), so there is no round-trip or older-reader concern. Placed next to the other SSL keys for readability; order is irrelevant for this enum (keyed lookups, no ordinal persistence).Client.Builder.setSSLContext): name/params/return match the siblingsetSSLMode(...); public because it is a user-facing builder option; behavior-focused tests added; reflected indocs/features.md.Client(...)constructor gained a parameter — no public API/binary-compatibility impact.JdbcConfiguration.getSslContext()is new but lives in the internalcom.clickhouse.jdbc.internalpackage.client-v2/jdbc-v2and public API surface →docs/features.mdupdated accordingly. Change is purely additive; default behavior (no context supplied) is unchanged.Notes