fredjoonpark opened a new issue, #1319: URL: https://github.com/apache/arrow-java/issues/1319
### Describe the enhancement requested The Flight SQL JDBC driver has no way to set the hostname used for TLS certificate verification (and SNI) separately from the host it connects to. The driver always verifies the server certificate against the `host` in the JDBC URL. This breaks TLS whenever the client connects through an address or hostname that doesn't match the server's certificate, for example: - **Tunnels and port-forwarding:** reaching a private server through SSH (`ssh -L`), AWS Systems Manager Session Manager port forwarding, or `kubectl port-forward`. The client connects to `localhost`, but the certificate is issued for the server's real hostname. - **Private endpoints and aliases:** connecting through a hostname other than the one on the certificate, for example an AWS PrivateLink interface endpoint DNS name (`vpce-...amazonaws.com`) when private DNS isn't enabled, or an internal alias that points at a load balancer. - **Connecting by IP address:** service discovery or client-side load balancing that returns IP addresses (for example Kubernetes endpoints or AWS Cloud Map), when the certificate only contains DNS names in its SAN. - **Private network gateways** that require the client to dial a specific address (IPv4 or IPv6) instead of the server's own hostname. The available workarounds all have significant drawbacks: - `disableCertificateVerification=true` removes server authentication entirely. - Making the certificate's hostname resolve to the target address (`/etc/hosts`, custom DNS, or a JDK `InetAddressResolverProvider`) applies to the whole OS or JVM. It requires control over that environment, and it can't send the same hostname to different addresses for different connections in one process. - Adding the connection address (`localhost`, an IP address or an endpoint hostname) to the server certificate's SAN requires control over the server certificate. Managed services usually don't allow that, and the address may change. - Using `FlightClient` directly with `overrideHostname` works, but doesn't help JDBC-based tools. **Example** ``` jdbc:arrow-flight-sql://192.0.2.10:443?useEncryption=true&tlsRootCerts=/path/ca.pem ``` fails with: ``` No subject alternative names matching IP address 192.0.2.10 found ``` even though the server presents a valid certificate for `flight.example.com`. Observed with `flight-sql-jdbc-driver` 19.0.0. The code path is unchanged on `main`. **Flight client already supports this** `FlightClient.Builder.overrideHostname(String)` and `NettyClientBuilder.overrideHostname(String)` already exist and map to gRPC's `overrideAuthority`. This was confirmed as the supported way to set SNI for the Java Flight client in apache/arrow#26155 (ARROW-10144). The JDBC driver builds its client with `NettyClientBuilder` in `ArrowFlightSqlClientHandler.Builder.build()`, but never calls `overrideHostname`, and there is no connection property to set it. **Proposal** - Add an optional connection property, `hostnameOverride` (string, default unset), to `ArrowFlightConnectionProperty`. - When set and `useEncryption=true`, call `clientBuilder.overrideHostname(value)` in `ArrowFlightSqlClientHandler.Builder.build()`. - Handle the clients the driver creates for additional endpoint locations in `getStreams()`. These are built from a copy of the original builder (`new Builder(original).withHost(endpointUri.getHost())...`), so a plain copied field would wrongly verify a different endpoint host against the override. Apply the override only when the endpoint host matches the original connection host, and otherwise clear it so those locations keep the current behavior. - Ignore the property when encryption is disabled, and document it next to `disableCertificateVerification` and `tlsRootCerts`. **Prior art in other JDBC drivers** - Trino JDBC: `hostnameInCertificate` - Microsoft SQL Server JDBC: `hostNameInCertificate` **Tests** Connect over TLS to an IP literal (for example `127.0.0.1` or `[::1]`) using a test certificate whose SAN only contains a DNS name: - Without the property: verification fails. - With `hostnameOverride=<dns-name>`: the connection succeeds with full verification. I'm happy to submit a PR for this. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
