From cd1765ea0d3d8a9af82b10af80e68ca8f8397fd8 Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:23:44 +0530 Subject: [PATCH 1/6] GH-1319: Add hostnameOverride JDBC property --- .../jdbc/utils/ArrowFlightConnectionConfigImpl.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java index d0ba74dbcc..a79e4e838e 100644 --- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java +++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java @@ -112,6 +112,15 @@ public String getTlsRootCertificatesPath() { return ArrowFlightConnectionProperty.TLS_ROOT_CERTS.getString(properties); } + /** + * Gets the hostname used for TLS certificate verification and SNI, if configured. + * + * @return the hostname override, or null when not configured. + */ + public String getHostnameOverride() { + return ArrowFlightConnectionProperty.HOSTNAME_OVERRIDE.getString(properties); + } + public String getClientCertificatePath() { return ArrowFlightConnectionProperty.CLIENT_CERTIFICATE.getString(properties); } @@ -254,6 +263,7 @@ public enum ArrowFlightConnectionProperty implements ConnectionProperty { PASSWORD("password", null, Type.STRING, false), USE_ENCRYPTION("useEncryption", true, Type.BOOLEAN, false), CERTIFICATE_VERIFICATION("disableCertificateVerification", false, Type.BOOLEAN, false), + HOSTNAME_OVERRIDE("hostnameOverride", null, Type.STRING, false), TRUST_STORE("trustStore", null, Type.STRING, false), TRUST_STORE_PASSWORD("trustStorePassword", null, Type.STRING, false), USE_SYSTEM_TRUST_STORE("useSystemTrustStore", true, Type.BOOLEAN, false), From 798418a8bcb2c108caeef3ca27877abcbc575e3d Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:23:48 +0530 Subject: [PATCH 2/6] GH-1319: Test hostnameOverride JDBC property --- .../jdbc/utils/ArrowFlightConnectionConfigImplTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImplTest.java b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImplTest.java index ecce7708c0..909e7cd39a 100644 --- a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImplTest.java +++ b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImplTest.java @@ -20,6 +20,7 @@ import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.CATALOG; import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.CONNECT_TIMEOUT_MILLIS; import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.HOST; +import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.HOSTNAME_OVERRIDE; import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.PASSWORD; import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.PORT; import static org.apache.arrow.driver.jdbc.utils.ArrowFlightConnectionConfigImpl.ArrowFlightConnectionProperty.THREAD_POOL_SIZE; @@ -106,6 +107,12 @@ public static Stream provideParameters() { useEncryption, (Function) ArrowFlightConnectionConfigImpl::useEncryption), + Arguments.of( + HOSTNAME_OVERRIDE, + "flight.example.com", + "flight.example.com", + (Function) + ArrowFlightConnectionConfigImpl::getHostnameOverride), Arguments.of( THREAD_POOL_SIZE, threadPoolSize, From 4d817001f25c903fd3f081fbd3c5fe2a5c317672 Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:23:51 +0530 Subject: [PATCH 3/6] GH-1319: Wire hostnameOverride into JDBC client --- .../java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java | 1 + 1 file changed, 1 insertion(+) diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java index 623c2b81be..d5fb2105e5 100644 --- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java +++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java @@ -118,6 +118,7 @@ private static ArrowFlightSqlClientHandler createNewClientHandler( .withClientKey(config.getClientKeyPath()) .withBufferAllocator(allocator) .withEncryption(config.useEncryption()) + .withHostnameOverride(config.getHostnameOverride()) .withDisableCertificateVerification(config.getDisableCertificateVerification()) .withToken(config.getToken()) .withCallOptions(config.toCallOption()) From 080f00db41f78a8f3c7b8471f29bf9a53dba93ae Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:23:57 +0530 Subject: [PATCH 4/6] GH-1319: Apply TLS hostname override safely --- .../client/ArrowFlightSqlClientHandler.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java index 719cc38a2b..66239dfc31 100644 --- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java +++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java @@ -188,6 +188,13 @@ public List getStreams(final FlightInfo flightInfo) .withHost(endpointUri.getHost()) .withPort(endpointUri.getPort()) .withEncryption(endpointUri.getScheme().equals(LocationSchemes.GRPC_TLS)) + // An override belongs to the original connection host, not arbitrary endpoints. + .withHostnameOverride( + endpointUri.getHost() != null + && this.builder.host != null + && endpointUri.getHost().equalsIgnoreCase(this.builder.host) + ? this.builder.hostnameOverride + : null) .withClientCache(flightClientCache) .withConnectTimeout(builder.connectTimeout); @@ -677,6 +684,8 @@ public static final class Builder { @VisibleForTesting boolean disableCertificateVerification; + @VisibleForTesting @Nullable String hostnameOverride; + @VisibleForTesting boolean useSystemTrustStore = true; @VisibleForTesting String tlsRootCertificatesPath; @@ -732,6 +741,7 @@ public Builder() {} this.token = original.token; this.useEncryption = original.useEncryption; this.disableCertificateVerification = original.disableCertificateVerification; + this.hostnameOverride = original.hostnameOverride; this.useSystemTrustStore = original.useSystemTrustStore; this.tlsRootCertificatesPath = original.tlsRootCertificatesPath; this.clientCertificatePath = original.clientCertificatePath; @@ -840,6 +850,17 @@ public Builder withDisableCertificateVerification( return this; } + /** + * Sets the hostname used for TLS certificate verification and SNI. + * + * @param hostnameOverride the hostname override, or null to use the connection host. + * @return this instance. + */ + public Builder withHostnameOverride(@Nullable final String hostnameOverride) { + this.hostnameOverride = hostnameOverride; + return this; + } + /** * Sets whether to use the certificates from the operating system. * @@ -1065,6 +1086,9 @@ public ArrowFlightSqlClientHandler build() throws SQLException { buildTimeMiddlewareFactories.forEach(clientBuilder::intercept); if (useEncryption) { clientBuilder.useTls(); + if (hostnameOverride != null) { + clientBuilder.overrideHostname(hostnameOverride); + } } Location location = getLocation(); clientBuilder.location(location); From a9a36e0e6b870e697ab996ce1bf733ece4a68fa0 Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:24:19 +0530 Subject: [PATCH 5/6] GH-1319: Document hostnameOverride JDBC property --- docs/source/flight_sql_jdbc_driver.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/flight_sql_jdbc_driver.rst b/docs/source/flight_sql_jdbc_driver.rst index 6d40434a22..ca52d0a157 100644 --- a/docs/source/flight_sql_jdbc_driver.rst +++ b/docs/source/flight_sql_jdbc_driver.rst @@ -93,6 +93,10 @@ case-sensitive. The supported parameters are: - false - When TLS is enabled, whether to verify the server certificate + * - hostnameOverride + - null + - When TLS is enabled, the hostname used for server certificate verification and SNI instead of the host in the JDBC URL + * - password - null - The password for user/password authentication From 7340765a6800e9ecd6fd9cde2b6346d89ec92bc6 Mon Sep 17 00:00:00 2001 From: Swati Kumari Date: Tue, 13 Oct 2026 22:24:22 +0530 Subject: [PATCH 6/6] GH-1319: Test hostname override builder configuration --- .../ArrowFlightSqlClientHandlerBuilderTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java index a60a71f23d..37c2229c0d 100644 --- a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java +++ b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java @@ -137,6 +137,7 @@ public void testDefaults() { assertNull(builder.password); assertTrue(builder.useEncryption); assertFalse(builder.disableCertificateVerification); + assertNull(builder.hostnameOverride); assertNull(builder.trustStorePath); assertNull(builder.trustStorePassword); assertTrue(builder.useSystemTrustStore); @@ -152,6 +153,18 @@ public void testDefaults() { assertNull(builder.driverVersion); } + @Test + public void testHostnameOverrideIsCopied() { + final String hostnameOverride = "flight.example.com"; + final ArrowFlightSqlClientHandler.Builder rootBuilder = + new ArrowFlightSqlClientHandler.Builder().withHostnameOverride(hostnameOverride); + + final ArrowFlightSqlClientHandler.Builder copiedBuilder = + new ArrowFlightSqlClientHandler.Builder(rootBuilder); + + assertEquals(hostnameOverride, copiedBuilder.hostnameOverride); + } + @Test public void testCatalog() { ArrowFlightSqlClientHandler.Builder rootBuilder = new ArrowFlightSqlClientHandler.Builder();