This is an automated email from the ASF dual-hosted git repository.

xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new d4dec25b886 Add runtime TLS diagnostics for gRPC and HTTPS (#17559)
d4dec25b886 is described below

commit d4dec25b88652fe73a32a846b283030445963dc0
Author: Xiang Fu <[email protected]>
AuthorDate: Tue Jan 27 22:28:19 2026 -0800

    Add runtime TLS diagnostics for gRPC and HTTPS (#17559)
---
 .../apache/pinot/broker/grpc/BrokerGrpcServer.java |  6 +-
 .../common/utils/grpc/BaseGrpcQueryClient.java     |  4 +
 .../apache/pinot/common/utils/tls/TlsUtils.java    | 97 ++++++++++++++++++++++
 .../pinot/core/transport/grpc/GrpcQueryServer.java |  4 +
 4 files changed, 108 insertions(+), 3 deletions(-)

diff --git 
a/pinot-broker/src/main/java/org/apache/pinot/broker/grpc/BrokerGrpcServer.java 
b/pinot-broker/src/main/java/org/apache/pinot/broker/grpc/BrokerGrpcServer.java
index 0ff44a18280..ed8db8261bf 100644
--- 
a/pinot-broker/src/main/java/org/apache/pinot/broker/grpc/BrokerGrpcServer.java
+++ 
b/pinot-broker/src/main/java/org/apache/pinot/broker/grpc/BrokerGrpcServer.java
@@ -363,9 +363,9 @@ public class BrokerGrpcServer extends 
PinotQueryBrokerGrpc.PinotQueryBrokerImplB
           
RenewableTlsUtils.createSSLFactoryAndEnableAutoRenewalWhenUsingFileStores(tlsConfig);
       // since tlsConfig.getKeyStorePath() is not null, 
sslFactory.getKeyManagerFactory().get() should not be null
       SslProvider sslProvider = 
SslProvider.valueOf(tlsConfig.getSslProvider());
-      if (sslProvider != SslProvider.JDK) {
-        LOGGER.warn("Configured SSL provider is {}. For FIPS/BCJSSE 
environments use JDK provider.", sslProvider);
-      }
+      // Runtime visibility for Platform-FIPS-JDK deployments: warn & log the 
actual JSSE provider/protocol once.
+      TlsUtils.warnIfNonJdkProviderConfigured("grpc.broker.server", tlsConfig);
+      TlsUtils.logJsseDiagnosticsOnce("grpc.broker.server", sslFactory, 
tlsConfig);
       SslContextBuilder sslContextBuilder =
           
SslContextBuilder.forServer(sslFactory.getKeyManagerFactory().get()).sslProvider(sslProvider);
       
sslFactory.getTrustManagerFactory().ifPresent(sslContextBuilder::trustManager);
diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/grpc/BaseGrpcQueryClient.java
 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/grpc/BaseGrpcQueryClient.java
index e1d92ded2e9..7aba0456b48 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/grpc/BaseGrpcQueryClient.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/grpc/BaseGrpcQueryClient.java
@@ -38,6 +38,7 @@ import org.apache.pinot.common.config.GrpcConfig;
 import org.apache.pinot.common.config.TlsConfig;
 import org.apache.pinot.common.utils.tls.PinotInsecureMode;
 import org.apache.pinot.common.utils.tls.RenewableTlsUtils;
+import org.apache.pinot.common.utils.tls.TlsUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -98,6 +99,9 @@ public abstract class BaseGrpcQueryClient<REQUEST, RESPONSE> 
implements Closeabl
       try {
         SSLFactory sslFactory = 
RenewableTlsUtils.createSSLFactoryAndEnableAutoRenewalWhenUsingFileStores(tlsConfig,
             PinotInsecureMode::isPinotInInsecureMode);
+        // Runtime visibility for Platform-FIPS-JDK deployments: warn & log 
the actual JSSE provider/protocol once.
+        TlsUtils.warnIfNonJdkProviderConfigured("grpc.query.client", 
tlsConfig);
+        TlsUtils.logJsseDiagnosticsOnce("grpc.query.client", sslFactory, 
tlsConfig);
         SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
         
sslFactory.getKeyManagerFactory().ifPresent(sslContextBuilder::keyManager);
         
sslFactory.getTrustManagerFactory().ifPresent(sslContextBuilder::trustManager);
diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/tls/TlsUtils.java 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/tls/TlsUtils.java
index 966393d823c..f8d00ccf70c 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/utils/tls/TlsUtils.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/utils/tls/TlsUtils.java
@@ -32,10 +32,14 @@ import java.net.URL;
 import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
 import javax.net.ssl.TrustManagerFactory;
 import nl.altindag.ssl.SSLFactory;
 import nl.altindag.ssl.exception.GenericSSLContextException;
@@ -70,6 +74,7 @@ public final class TlsUtils {
   private static final String INSECURE = "insecure";
 
   private static final AtomicReference<SSLContext> SSL_CONTEXT_REF = new 
AtomicReference<>();
+  private static final Set<String> LOGGED_TLS_DIAGNOSTICS_KEYS = 
ConcurrentHashMap.newKeySet();
 
   private TlsUtils() {
     // left blank
@@ -251,6 +256,7 @@ public final class TlsUtils {
       // HttpsURLConnection
       HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
       setSslContext(sc);
+      logTlsDiagnosticsOnce("https.default", sc, null, false);
     } catch (GenericSSLContextException | GeneralSecurityException e) {
       throw new IllegalStateException("Could not initialize SSL support", e);
     }
@@ -321,6 +327,7 @@ public final class TlsUtils {
     sslFactory.getKeyManagerFactory().ifPresent(sslContextBuilder::keyManager);
     
sslFactory.getTrustManagerFactory().ifPresent(sslContextBuilder::trustManager);
     try {
+      warnIfNonJdkProviderConfiguredInternal("netty.client", tlsConfig);
       return sslContextBuilder.build();
     } catch (Exception e) {
       throw new RuntimeException(e);
@@ -346,6 +353,7 @@ public final class TlsUtils {
       sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
     }
     try {
+      warnIfNonJdkProviderConfiguredInternal("netty.server", tlsConfig);
       return sslContextBuilder.build();
     } catch (Exception e) {
       throw new RuntimeException(e);
@@ -369,4 +377,93 @@ public final class TlsUtils {
       throw new RuntimeException(e);
     }
   }
+
+  private static void warnIfNonJdkProviderConfiguredInternal(String 
contextName, TlsConfig tlsConfig) {
+    // In Platform-FIPS-JDK deployments, you typically want to stay on the JDK 
TLS stack
+    // (JSSE provider selection happens via java.security / JVM configuration).
+    String configured = tlsConfig != null ? tlsConfig.getSslProvider() : null;
+    if (configured != null) {
+      try {
+        SslProvider sslProvider = SslProvider.valueOf(configured);
+        if (sslProvider != SslProvider.JDK) {
+          LOGGER.warn("TLS config for '{}' sets sslProvider='{}'. 
Platform-FIPS-JDK deployments typically require "
+              + "sslProvider='JDK' (avoid OpenSSL).", contextName, configured);
+        }
+      } catch (Exception e) {
+        // If config is invalid, let existing code fail where it parses/builds 
the context.
+      }
+    }
+  }
+
+  /**
+   * Log (once) the JSSE provider/protocol actually used at runtime for the 
given TLS config.
+   * <p>
+   * This is intended as a lightweight runtime self-check for 
Platform-FIPS-JDK deployments: Pinot generally uses the
+   * JDK TLS stack (JSSE), and the platform/JDK decides which provider is 
active via {@code java.security} and other JVM
+   * settings. This method helps surface misconfiguration early without 
enforcing behavior.
+   */
+  public static void logJsseDiagnosticsOnce(String contextName, SSLFactory 
sslFactory, TlsConfig tlsConfig) {
+    if (sslFactory == null) {
+      return;
+    }
+    try {
+      SSLContext sslContext = sslFactory.getSslContext();
+      String configuredSslProvider = tlsConfig != null ? 
tlsConfig.getSslProvider() : null;
+      boolean insecure = tlsConfig != null && tlsConfig.isInsecure();
+      logTlsDiagnosticsOnce(contextName, sslContext, configuredSslProvider, 
insecure);
+    } catch (Exception e) {
+      LOGGER.warn("TLS diagnostics ({}): failed to obtain SSLContext for 
diagnostics", contextName, e);
+    }
+  }
+
+  /**
+   * Emit a warning when a non-JDK TLS stack is configured.
+   */
+  public static void warnIfNonJdkProviderConfigured(String contextName, 
TlsConfig tlsConfig) {
+    warnIfNonJdkProviderConfiguredInternal(contextName, tlsConfig);
+  }
+
+  private static void logTlsDiagnosticsOnce(String contextName, SSLContext 
sslContext, String configuredSslProvider,
+      boolean insecure) {
+    if (sslContext == null) {
+      return;
+    }
+    String providerName = sslContext.getProvider() != null ? 
sslContext.getProvider().getName() : "null";
+    String protocol = sslContext.getProtocol();
+    String key = contextName + "|" + providerName + "|" + protocol + "|" + 
configuredSslProvider + "|" + insecure;
+    if (!LOGGED_TLS_DIAGNOSTICS_KEYS.add(key)) {
+      return;
+    }
+
+    // Basic “what are we actually using at runtime?” visibility.
+    LOGGER.info(
+        "TLS diagnostics ({}): SSLContext protocol='{}', provider='{}', 
configuredSslProvider='{}', insecure={}",
+        contextName, protocol, providerName, configuredSslProvider, insecure);
+
+    // Heuristic warnings that are helpful for FIPS hardening (without 
enforcing behavior here).
+    if ("SSL".equalsIgnoreCase(protocol)) {
+      LOGGER.warn("TLS diagnostics ({}): SSLContext protocol is '{}'. Consider 
using 'TLS' and enforcing TLSv1.2+ via "
+          + "protocol/cipher allowlists for compliance hardening.", 
contextName, protocol);
+    }
+
+    try {
+      SSLEngine engine = sslContext.createSSLEngine();
+      String[] enabledProtocols = engine.getEnabledProtocols();
+      String[] enabledCiphers = engine.getEnabledCipherSuites();
+      LOGGER.info("TLS diagnostics ({}): enabledProtocols={}, 
enabledCipherSuites(count)={}", contextName,
+          Arrays.toString(enabledProtocols), enabledCiphers != null ? 
enabledCiphers.length : 0);
+
+      if (enabledProtocols != null) {
+        for (String p : enabledProtocols) {
+          if ("TLSv1".equalsIgnoreCase(p) || "TLSv1.1".equalsIgnoreCase(p) || 
"SSLv3".equalsIgnoreCase(p)
+              || "SSLv2Hello".equalsIgnoreCase(p)) {
+            LOGGER.warn("TLS diagnostics ({}): enabled protocol '{}' is 
typically disallowed in modern/FIPS-hardened "
+                + "deployments. Consider enforcing TLSv1.2+.", contextName, p);
+          }
+        }
+      }
+    } catch (Exception e) {
+      LOGGER.warn("TLS diagnostics ({}): failed to create SSLEngine for 
diagnostics", contextName, e);
+    }
+  }
 }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/transport/grpc/GrpcQueryServer.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/transport/grpc/GrpcQueryServer.java
index 5f0cf528aa6..f8b9013e520 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/transport/grpc/GrpcQueryServer.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/transport/grpc/GrpcQueryServer.java
@@ -53,6 +53,7 @@ import org.apache.pinot.common.proto.Server.ServerRequest;
 import org.apache.pinot.common.proto.Server.ServerResponse;
 import org.apache.pinot.common.utils.tls.PinotInsecureMode;
 import org.apache.pinot.common.utils.tls.RenewableTlsUtils;
+import org.apache.pinot.common.utils.tls.TlsUtils;
 import org.apache.pinot.core.operator.blocks.InstanceResponseBlock;
 import org.apache.pinot.core.operator.streaming.StreamingResponseUtils;
 import org.apache.pinot.core.query.executor.QueryExecutor;
@@ -185,6 +186,9 @@ public class GrpcQueryServer extends 
PinotQueryServerGrpc.PinotQueryServerImplBa
         SSLFactory sslFactory =
             
RenewableTlsUtils.createSSLFactoryAndEnableAutoRenewalWhenUsingFileStores(
                 tlsConfig, PinotInsecureMode::isPinotInInsecureMode);
+        // Runtime visibility for Platform-FIPS-JDK deployments: log the 
actual JSSE provider/protocol once.
+        TlsUtils.warnIfNonJdkProviderConfigured("grpc.query.server", 
tlsConfig);
+        TlsUtils.logJsseDiagnosticsOnce("grpc.query.server", sslFactory, 
tlsConfig);
         SslContextBuilder sslContextBuilder = 
SslContextBuilder.forServer(sslFactory.getKeyManagerFactory().get())
             .sslProvider(SslProvider.valueOf(tlsConfig.getSslProvider()));
         
sslFactory.getTrustManagerFactory().ifPresent(sslContextBuilder::trustManager);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to