Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/source/flight_sql_jdbc_driver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ public List<CloseableEndpointStreamPair> 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);

Expand Down Expand Up @@ -677,6 +684,8 @@ public static final class Builder {

@VisibleForTesting boolean disableCertificateVerification;

@VisibleForTesting @Nullable String hostnameOverride;

@VisibleForTesting boolean useSystemTrustStore = true;

@VisibleForTesting String tlsRootCertificatesPath;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -106,6 +107,12 @@ public static Stream<Arguments> provideParameters() {
useEncryption,
(Function<ArrowFlightConnectionConfigImpl, ?>)
ArrowFlightConnectionConfigImpl::useEncryption),
Arguments.of(
HOSTNAME_OVERRIDE,
"flight.example.com",
"flight.example.com",
(Function<ArrowFlightConnectionConfigImpl, ?>)
ArrowFlightConnectionConfigImpl::getHostnameOverride),
Arguments.of(
THREAD_POOL_SIZE,
threadPoolSize,
Expand Down
Loading