Skip to content

[JDBC] Add a hostnameOverride connection property to verify TLS against a hostname different from the connection host #1319

Description

@fredjoonpark

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions