Skip to content

Conversation

@chernser
Copy link
Contributor

@chernser chernser commented Jun 24, 2025

Summary

This PR add configuration option to create mapping between host/ip and SNI. The last one will be set each time SSL socket is created to connect to it.

Closes #2434

Checklist

Delete items not relevant to your PR:

  • Closes #
  • Unit and integration tests covering the common scenarios were added
  • A human-readable description of the changes was provided to include in CHANGELOG
  • For significant changes, documentation in https://github.com/ClickHouse/clickhouse-docs was updated with further explanations or tutorials
@chernser chernser modified the milestone: 0.9.1 Jun 24, 2025
@chernser chernser requested a review from Copilot June 25, 2025 04:28
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces configurable SSL SNI mapping to the ClickHouse Java client, allowing users to specify host/IP-to-SNI mappings when creating HTTPS connections. It also adds accompanying integration tests, sample Nginx configurations, and new certificate assets to validate the feature.

  • Added ssl_sni_mapping property and parsing logic in ClientConfigProperties
  • Extended HTTP client factories (HttpAPIClientHelper and ApacheHttpConnectionImpl) to apply SNI based on mappings
  • Added integration tests using Testcontainers and sample Nginx configs/certs

Reviewed Changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
client-v2/src/test/resources/nginx.conf Sample Nginx config defining two SSL servers for SNI tests
client-v2/src/test/resources/certs/node2.key Private key for node2 test server
client-v2/src/test/resources/certs/node2.crt Certificate for node2 test server
client-v2/src/test/resources/certs/node1.key Private key for node1 test server
client-v2/src/test/resources/certs/node1.crt Certificate for node1 test server
client-v2/src/test/resources/certs/README.md Instructions for generating self-signed certs
client-v2/src/test/java/com/clickhouse/client/internal/SmallTests.java New test printing config properties (needs assertions)
client-v2/src/test/java/com/clickhouse/client/NetworkTests.java Integration test scaffolding for SNI (incomplete)
client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java Added CustomSSLConnectionFactory for SNI mapping
client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java Introduced SSL_SNI_MAPPING enum and toKeyValuePairs parser
client-v2/src/main/java/com/clickhouse/client/api/Client.java Added builder method appCompressedData(boolean)
client-v2/pom.xml Bumped in-test logging by adding slf4j-simple dependency
clickhouse-http-client/src/test/resources/nginx.conf Duplicate sample Nginx config for HTTP client module
clickhouse-http-client/src/test/resources/certs/node2.key Duplicate node2 private key in HTTP client module
clickhouse-http-client/src/test/resources/certs/node2.crt Duplicate node2 certificate in HTTP client module
clickhouse-http-client/src/test/resources/certs/node1.key Duplicate node1 private key in HTTP client module
clickhouse-http-client/src/test/resources/certs/node1.crt Duplicate node1 certificate in HTTP client module
clickhouse-http-client/src/test/java/com/clickhouse/client/http/NetworkTests.java HTTP client integration tests for SNI
clickhouse-http-client/src/main/java/com/clickhouse/client/http/ApacheHttpConnectionImpl.java Extended SSLSocketFactory to apply SNI mapping
clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java Added SSL_SNI_MAPPING enum option
Comments suppressed due to low confidence (6)

client-v2/src/test/java/com/clickhouse/client/internal/SmallTests.java:52

  • This test method prints values but has no assertions. Consider adding assertions to verify the output or remove the test if it is only for manual inspection.
 System.out.println("<br/> <br/> Default: `none` <br/> Enum: `none` <br/> Key: `none` " 

client-v2/src/test/java/com/clickhouse/client/NetworkTests.java:67

  • The testSNI method currently only prints the container address and lacks assertions. It should include assertions to validate actual SNI behavior or be removed.
 public void testSNI() { 

client-v2/src/main/java/com/clickhouse/client/api/Client.java:600

  • The Javadoc for appCompressedData has an empty @return tag. Please provide a description, e.g., @return this builder instance.
 * @return 

clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java:460

  • The key ssl_sni_map here is inconsistent with ssl_sni_mapping in ClientConfigProperties. Consider unifying the property name across modules.
 SSL_SNI_MAPPING("ssl_sni_map", "", "Comma separated key-value pairs of IP address/host to SNI mapping. Special mapping _default_ - for default SNI when no match found. Without default mapping only matched targets will have SNI parameter.") 

client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java:227

  • Add unit tests for toKeyValuePairs to verify parsing of edge cases (escaped commas, missing values, whitespace handling).
 public static Map<String, String> toKeyValuePairs(String str) { 

clickhouse-http-client/src/test/java/com/clickhouse/client/http/NetworkTests.java:1

  • [nitpick] There is duplicated NetworkTests logic in both client-v2 and clickhouse-http-client modules. Consider consolidating shared test helpers to avoid repetition.
package com.clickhouse.client.http; 
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
Copy link

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The slf4j-simple dependency is added without a <scope>test</scope>. If it's only needed for tests, scope it to test to avoid polluting production classpaths.

Suggested change
<version>2.0.16</version>
<version>2.0.16</version>
<scope>test</scope>
Copilot uses AI. Check for mistakes.
@chernser chernser marked this pull request as ready for review July 8, 2025 21:21
Copy link

@windsurf-bot windsurf-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other comments (3)
  • client-v2/src/test/java/com/clickhouse/client/internal/SmallTests.java (50-63) This test method appears to be generating documentation or debug output rather than validating functionality. Consider either:
    1. Adding assertions to make this a proper test
    2. Moving this to a separate utility class if it's meant for documentation generation
    3. Adding a comment explaining the purpose of this test method
  • client-v2/src/test/java/com/clickhouse/client/ClientTests.java (209-209) The test assertions have been updated to account for the new SNI configuration property, but there's no test case that actually verifies the SNI mapping functionality. Consider adding a test that demonstrates how to configure the SNI mapping and validates that it works correctly when connecting to a server.
  • client-v2/src/test/java/com/clickhouse/client/internal/SmallTests.java (52-62) Consider removing the unnecessary blank lines in the println statements to improve code readability.
     System.out.println("<br/> <br/> Default: `none` <br/> Enum: `none` <br/> Key: `none` "); for (ClientConfigProperties p : ClientConfigProperties.values()) { String defaultValue = p.getDefaultValue() == null ? "-" : "`" + p.getDefaultValue() + "`"; System.out.println("<br/> <br/> Default: " +defaultValue + " <br/> Enum: `ClientConfigProperties." + p.name() + "` <br/> Key: `" + p.getKey() +"` "); } 

💡 To request another review, post a new comment with "/windsurf-review".

if (sslContext != null) {
String socketSNI = (String)configuration.get(ClientConfigProperties.SSL_SOCKET_SNI.getKey());
if (socketSNI != null && !socketSNI.trim().isEmpty()) {
sslConnectionSocketFactory = new CustomSSLConnectionFactory(socketSNI, sslContext, (hostname, session) -> true);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is using a hostname verifier that always returns true ((hostname, session) -> true), which bypasses hostname verification entirely. This is a security risk as it makes the connection vulnerable to man-in-the-middle attacks. Consider using a proper hostname verifier or making this configurable.

@chernser chernser merged commit d4792b7 into main Jul 8, 2025
16 of 23 checks passed
@chernser chernser deleted the impl_SNI_config branch July 8, 2025 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants