This is an automated email from the ASF dual-hosted git repository.
roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 1fbd8f010f [#12298] feat(design-docs): Design doc pinning the exact
TLS API for the Java client (#12370)
1fbd8f010f is described below
commit 1fbd8f010fed9f3cbb583e1671f9bc87c8cc88c0
Author: Octavio Herrera Contreras <[email protected]>
AuthorDate: Wed Aug 5 19:47:44 2026 -0700
[#12298] feat(design-docs): Design doc pinning the exact TLS API for the
Java client (#12370)
[Subtask] M0: Design doc pinning the exact TLS API for the Java client
#12298
### What changes were proposed in this pull request?
This document outlines the design considerations, implementation
details, and potential challenges associated with integrating TLS into
the Gravitino client.
### Why are the changes needed?
Documentation was requested prior to beginning work on TLS subtasks to
ensure a clear vision and hard boundary for expectations of
implementation.
Fix: #12298
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
NA
---
design-docs/gravitino-client-tls.md | 284 ++++++++++++++++++++++++++++++++++++
1 file changed, 284 insertions(+)
diff --git a/design-docs/gravitino-client-tls.md
b/design-docs/gravitino-client-tls.md
new file mode 100644
index 0000000000..e7ba2b708c
--- /dev/null
+++ b/design-docs/gravitino-client-tls.md
@@ -0,0 +1,284 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+# Gravitino Java Client TLS Configuration
+
+## Summary
+
+This document defines the public API for configuring TLS connections made by
the Gravitino Java client.
+
+The design supports the following client use cases:
+
+* Connecting to a server whose certificate is signed by a private certificate
authority.
+* Connecting to a server that requires mutual TLS.
+* Presenting a client certificate while continuing to use the JVM's default
trust configuration.
+* Restricting the enabled TLS protocols and cipher suites.
+
+The TLS configuration is supplied through a narrow, typed client-builder
method:
+
+```java
+withTlsConfigurer(TLSConfigurer tlsConfigurer)
+```
+
+The underlying HTTP client builder is not exposed.
+
+## What does a user write?
+
+### Private-CA server
+
+A user connects to a Gravitino server whose certificate is signed by a private
CA by supplying a custom truststore.
+
+```java
+TLSConfigurer tlsConfigurer =
+ TLSConfigurers.builder()
+ .trustStore(
+ Paths.get("/etc/gravitino/client-truststore.p12"),
+ "truststore-password")
+ .build();
+
+GravitinoClient client =
+ GravitinoClient.builder("https://gravitino.example.com")
+ .withTlsConfigurer(tlsConfigurer)
+ .build();
+```
+
+The truststore is used instead of the JVM's default trust configuration for
this client.
+
+### Mutual TLS
+
+A user supplies both a truststore for validating the server and a keystore
containing the client's certificate and private key.
+
+```java
+TLSConfigurer tlsConfigurer =
+ TLSConfigurers.builder()
+ .trustStore(
+ Paths.get("/etc/gravitino/client-truststore.p12"),
+ "truststore-password")
+ .keyStore(
+ Paths.get("/etc/gravitino/client-keystore.p12"),
+ "keystore-password")
+ .build();
+
+GravitinoClient client =
+ GravitinoClient.builder("https://gravitino.example.com")
+ .withTlsConfigurer(tlsConfigurer)
+ .build();
+```
+
+### Client certificate with the system truststore
+
+A user supplies a client certificate without supplying a custom truststore.
+
+```java
+TLSConfigurer tlsConfigurer =
+ TLSConfigurers.builder()
+ .keyStore(
+ Paths.get("/etc/gravitino/client-keystore.p12"),
+ "keystore-password")
+ .build();
+
+GravitinoClient client =
+ GravitinoClient.builder("https://gravitino.example.com")
+ .withTlsConfigurer(tlsConfigurer)
+ .build();
+```
+
+Because no custom truststore is configured, the client uses the JVM's default
trust configuration to validate the server certificate.
+
+### Restricting protocols and cipher suites
+
+A user may restrict the protocols and cipher suites enabled for the connection.
+
+```java
+TLSConfigurer tlsConfigurer =
+ TLSConfigurers.builder()
+ .protocols("TLSv1.3")
+ .cipherSuites("TLS_AES_256_GCM_SHA384")
+ .build();
+
+GravitinoClient client =
+ GravitinoClient.builder("https://gravitino.example.com")
+ .withTlsConfigurer(tlsConfigurer)
+ .build();
+```
+
+When protocols or cipher suites are not specified, the HTTP and TLS
implementation defaults are used.
+
+Unsupported protocols or cipher suites cause client construction or connection
establishment to fail rather than silently falling back to weaker settings.
+
+## What are we promising?
+
+### Public API
+
+The following types and methods are part of the public client API.
+
+```java
+public interface TLSConfigurer
+```
+
+`TLSConfigurer` represents a complete optional TLS configuration that can be
applied to the Gravitino HTTP client.
+
+```java
+public final class TLSConfigurers
+```
+
+`TLSConfigurers` is the entry point for constructing a `TLSConfigurer`.
+
+```java
+public static TLSConfigurers.Builder builder()
+```
+
+Creates a new TLS configuration builder.
+
+```java
+public static final class TLSConfigurers.Builder
+```
+
+The builder exposes the following methods:
+
+```java
+public Builder trustStore(Path path, String password)
+```
+
+Configures the truststore used to validate the server certificate.
+
+```java
+public Builder keyStore(Path path, String password)
+```
+
+Configures the keystore containing the client certificate and private key.
+
+```java
+public Builder protocols(String... protocols)
+```
+
+Restricts the enabled TLS protocols.
+
+```java
+public Builder cipherSuites(String... cipherSuites)
+```
+
+Restricts the enabled TLS cipher suites.
+
+```java
+public TLSConfigurer build()
+```
+
+Creates the TLS configuration.
+
+The Gravitino client builders expose:
+
+```java
+public GravitinoClient.Builder withTlsConfigurer(
+ TLSConfigurer tlsConfigurer)
+```
+
+```java
+public GravitinoAdminClient.Builder withTlsConfigurer(
+ TLSConfigurer tlsConfigurer)
+```
+
+These methods apply the supplied TLS configuration to HTTP connections created
by the corresponding client.
+
+The exact return types above should match the existing nested builder types
used by `GravitinoClient` and `GravitinoAdminClient`.
+
+### Default behavior
+
+The following defaults are part of the API behavior:
+
+* When no `TLSConfigurer` is supplied, existing client behavior remains
unchanged.
+* When no truststore is supplied, the JVM's default trust configuration is
used.
+* When no keystore is supplied, the client does not present a client
certificate.
+* When protocols are not supplied, the TLS implementation's enabled protocol
defaults are used.
+* When cipher suites are not supplied, the TLS implementation's enabled
cipher-suite defaults are used.
+* TLS configuration applies only to HTTPS connections.
+* Configuring TLS does not implicitly disable hostname verification.
+
+### Error handling
+
+Invalid TLS configuration must fail with an actionable exception.
+
+Examples include:
+
+* The configured store does not exist or cannot be read.
+* The store password is incorrect.
+* The store cannot be parsed as the supported store type.
+* The keystore contains no usable client key.
+* A configured protocol or cipher suite is unsupported.
+* The server certificate cannot be validated.
+* The server rejects the client's certificate.
+
+Sensitive values, including store passwords and private-key material, must not
be included in exception messages or logs.
+
+### Builder-method decision
+
+The public client API will expose the narrow, typed method:
+
+```java
+withTlsConfigurer(TLSConfigurer tlsConfigurer)
+```
+
+It will not expose a general callback or hook for modifying the underlying
HTTP client builder.
+
+A typed TLS configuration API is preferred because:
+
+* It limits the public contract to the capabilities required by the TLS epic.
+* It prevents the underlying HTTP client implementation from becoming part of
Gravitino's public API.
+* It allows the HTTP implementation to be replaced without breaking client
code.
+* It gives Gravitino control over validation, defaults, compatibility, and
error reporting.
+* It is easier to widen the typed API in a later release than to narrow a
general-purpose HTTP-builder hook after users depend on it.
+
+This decision intentionally favors a narrow API. Additional TLS configuration
capabilities can be added to `TLSConfigurer` later when concrete use cases
require them.
+
+## What stays internal?
+
+The following implementation details are not public API:
+
+* Loading `KeyStore` instances from configured paths.
+* Creating and initializing `KeyManagerFactory`.
+* Creating and initializing `TrustManagerFactory`.
+* Creating the Java `SSLContext`.
+* Creating the Apache HttpComponents TLS strategy.
+* Applying protocols and cipher suites to the underlying HTTP transport.
+* Translating `TLSConfigurer` into HTTP client configuration.
+* The concrete implementation class of `TLSConfigurer`.
+* Any wrapper, adapter, or helper classes used by `HTTPClient`.
+* The choice of Apache HttpComponents classes used internally.
+* Test certificates, test keystores, and test truststores.
+
+Users interact only with `TLSConfigurer`, `TLSConfigurers.Builder`, and the
typed `withTlsConfigurer` client-builder method.
+
+## What are we not doing?
+
+This design does not include:
+
+* Server-side TLS configuration.
+* Certificate enrollment, renewal, rotation, revocation, or certificate
pinning.
+* Automatically detecting or reloading keystore or truststore changes after
the client has been built. Users must rebuild the client to apply updated
stores.
+* Configuring TLS globally for the JVM.
+* Providing an option to disable or bypass hostname verification.
+* Trusting all certificates or providing an insecure trust manager.
+* Exposing the underlying Apache HttpComponents client builder.
+* Providing a general-purpose HTTP-client customization callback.
+* Directly accepting PEM-encoded CA certificates, client certificates,
certificate chains, or private keys. These materials must be supplied through
PKCS12 keystores or truststores.
+* Allowing users to explicitly select which private-key entry or certificate
alias is presented when a keystore contains multiple eligible entries.
Selection is delegated to the standard Java key manager.
+* Supplying keystore or truststore contents through an `InputStream`.
+* Guaranteeing that every configured protocol or cipher suite is supported by
every JVM or security provider.
+
+Initial file-based keystore and truststore support uses PKCS12 stores.
Supporting additional store formats may be considered separately without
changing the client-builder integration point.