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

anmolnar pushed a commit to branch branch-3.9
in repository https://gitbox.apache.org/repos/asf/zookeeper.git


The following commit(s) were added to refs/heads/branch-3.9 by this push:
     new f6fb66846 ZOOKEEPER-5045: Fall back to TLSv1.2 default in FIPS mode
f6fb66846 is described below

commit f6fb6684665758bf79913c325400e2f9fe6c840f
Author: Dávid Paksy <[email protected]>
AuthorDate: Mon Jun 22 18:22:17 2026 +0200

    ZOOKEEPER-5045: Fall back to TLSv1.2 default in FIPS mode
    
    Reviewers: meszibalu
    Author: PDavid
    Closes #2383 from PDavid/ZOOKEEPER-5045-branch-3.9
---
 .../java/org/apache/zookeeper/common/X509Util.java | 36 ++++++++++++++--------
 .../org/apache/zookeeper/common/X509UtilTest.java  | 33 +++++++++++++++-----
 .../zookeeper/server/admin/CommandAuthTest.java    |  5 ++-
 3 files changed, 54 insertions(+), 20 deletions(-)

diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
index 9620dfbd4..a89d57821 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
@@ -35,7 +35,6 @@
 import java.security.cert.PKIXBuilderParameters;
 import java.security.cert.PKIXRevocationChecker;
 import java.security.cert.X509CertSelector;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
@@ -87,27 +86,40 @@ public abstract class X509Util implements Closeable, 
AutoCloseable {
         }
     }
 
-    public static final String DEFAULT_PROTOCOL = defaultTlsProtocol();
+    private static final AtomicReference<String> defaultProtocol = new 
AtomicReference<>();
 
     /**
-     * Return TLSv1.3 or TLSv1.2 depending on Java runtime version being used.
+     * Return TLSv1.2 when FIPS mode is enabled.
+     * Otherwise, returns TLSv1.3 or TLSv1.2 depending on Java runtime version 
being used.
      * TLSv1.3 was first introduced in JDK11 and back-ported to OpenJDK 8u272.
      */
-    private static String defaultTlsProtocol() {
-        String defaultProtocol = TLS_1_2;
-        List<String> supported = new ArrayList<>();
+    public static String defaultTlsProtocol(ZKConfig config) {
+        if (getFipsMode(config)) {
+            return TLS_1_2;
+        }
+
+        String proto = defaultProtocol.get();
+        if (proto != null) {
+            return proto;
+        }
+
+        proto = TLS_1_2;
         try {
-            supported = 
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
+            List<String> supported = 
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
             // We cannot use the default protocols directly, because the 
SSLContext factory methods
             // only accept a single protocol
             if (supported.contains(TLS_1_3)) {
-                defaultProtocol = TLS_1_3;
+                proto = TLS_1_3;
+            }
+            if (defaultProtocol.compareAndSet(null, proto)) {
+                LOG.info("Supported TLS protocols are {}, default TLS protocol 
is {}", supported, proto);
+            } else {
+                proto = defaultProtocol.get();
             }
         } catch (NoSuchAlgorithmException e) {
             // Ignore.
         }
-        LOG.info("Default TLS protocol is {}, supported TLS protocols are {}", 
defaultProtocol, supported);
-        return defaultProtocol;
+        return proto;
     }
 
     public static final int DEFAULT_HANDSHAKE_DETECTION_TIMEOUT_MILLIS = 5000;
@@ -431,8 +443,8 @@ public SSLContextAndOptions 
createSSLContextAndOptionsFromConfig(ZKConfig config
                                               + trustStoreTypeProp, e);
             }
         }
-
-        String protocol = config.getProperty(sslProtocolProperty, 
DEFAULT_PROTOCOL);
+        String defaultTlsProtocol = defaultTlsProtocol(config);
+        String protocol = config.getProperty(sslProtocolProperty, 
defaultTlsProtocol);
         try {
             SSLContext sslContext = SSLContext.getInstance(protocol);
             sslContext.init(keyManagers, trustManagers, null);
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
index 1c5104e78..660ca64bf 100644
--- 
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
@@ -18,6 +18,9 @@
 
 package org.apache.zookeeper.common;
 
+import static org.apache.zookeeper.common.X509Util.FIPS_MODE_PROPERTY;
+import static org.apache.zookeeper.common.X509Util.TLS_1_2;
+import static org.apache.zookeeper.common.X509Util.TLS_1_3;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -90,6 +93,7 @@ public void cleanUp() {
         
System.clearProperty(x509Util.getSslHandshakeDetectionTimeoutMillisProperty());
         System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
         System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
+        System.clearProperty(FIPS_MODE_PROPERTY);
         x509Util.close();
     }
 
@@ -100,24 +104,39 @@ public void testCreateSSLContextWithoutCustomProtocol(
             X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
             throws Exception {
         init(caKeyType, certKeyType, keyPassword, paramIndex);
+        System.setProperty(FIPS_MODE_PROPERTY, Boolean.FALSE.toString());
         SSLContext sslContext = x509Util.getDefaultSSLContext();
-        assertEquals(X509Util.DEFAULT_PROTOCOL, sslContext.getProtocol());
+        String defaultTlsProtocol = X509Util.defaultTlsProtocol(new 
ZKConfig());
+        assertEquals(defaultTlsProtocol, sslContext.getProtocol());
 
         // Check that TLSv1.3 is selected in JDKs that support it (OpenJDK 
8u272 and later).
         List<String> supported = 
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
-        if (supported.contains(X509Util.TLS_1_3)) {
+        if (supported.contains(TLS_1_3)) {
             // SSLContext protocol.
-            assertEquals(X509Util.TLS_1_3, sslContext.getProtocol());
+            assertEquals(TLS_1_3, sslContext.getProtocol());
             // Enabled protocols.
             List<String> protos = 
Arrays.asList(sslContext.getDefaultSSLParameters().getProtocols());
-            assertTrue(protos.contains(X509Util.TLS_1_2));
-            assertTrue(protos.contains(X509Util.TLS_1_3));
+            assertTrue(protos.contains(TLS_1_2));
+            assertTrue(protos.contains(TLS_1_3));
         } else {
-            assertEquals(X509Util.TLS_1_2, sslContext.getProtocol());
-            assertArrayEquals(new String[]{X509Util.TLS_1_2}, 
sslContext.getDefaultSSLParameters().getProtocols());
+            assertEquals(TLS_1_2, sslContext.getProtocol());
+            assertArrayEquals(new String[]{TLS_1_2}, 
sslContext.getDefaultSSLParameters().getProtocols());
         }
     }
 
+    @ParameterizedTest
+    @MethodSource("data")
+    @Timeout(value = 5)
+    public void testCreateSSLContextFIPSModeEnabled(
+            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
+            throws Exception {
+        init(caKeyType, certKeyType, keyPassword, paramIndex);
+        System.setProperty(FIPS_MODE_PROPERTY, Boolean.TRUE.toString());
+        SSLContext sslContext = x509Util.getDefaultSSLContext();
+        assertEquals(TLS_1_2, sslContext.getProtocol());
+        assertArrayEquals(new String[]{TLS_1_2}, 
sslContext.getDefaultSSLParameters().getProtocols());
+    }
+
     @ParameterizedTest
     @MethodSource("data")
     @Timeout(value = 5)
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/admin/CommandAuthTest.java
 
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/admin/CommandAuthTest.java
index ed5dea56c..f576ad81b 100644
--- 
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/admin/CommandAuthTest.java
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/admin/CommandAuthTest.java
@@ -48,6 +48,8 @@
 import org.apache.zookeeper.common.ClientX509Util;
 import org.apache.zookeeper.common.QuorumX509Util;
 import org.apache.zookeeper.common.X509Exception;
+import org.apache.zookeeper.common.X509Util;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Id;
 import org.apache.zookeeper.server.NettyServerCnxnFactory;
@@ -281,7 +283,8 @@ private void setupTLS() throws Exception {
         System.setProperty("zookeeper.admin.needClientAuth", "true");
 
         // create SSLContext
-        final SSLContext sslContext = 
SSLContext.getInstance(ClientX509Util.DEFAULT_PROTOCOL);
+        String defaultTlsProtocol = X509Util.defaultTlsProtocol(new 
ZKConfig());
+        final SSLContext sslContext = 
SSLContext.getInstance(defaultTlsProtocol);
         final X509AuthenticationProvider authProvider = 
(X509AuthenticationProvider) ProviderRegistry.getProvider("x509");
         if (authProvider == null) {
             throw new X509Exception.SSLContextException("Could not create 
SSLContext with x509 auth provider");

Reply via email to