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

zhangduo pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 89ca879321d HBASE-29181 
TestNettyTLSIPCFileWatcher.testReplaceServerKeystore fails for some 
storeFileTypes (#6980)
89ca879321d is described below

commit 89ca879321df6ea0fafb18fcaf2aa5a4cc46b02e
Author: Andor Molnár <[email protected]>
AuthorDate: Fri May 16 09:00:30 2025 -0500

    HBASE-29181 TestNettyTLSIPCFileWatcher.testReplaceServerKeystore fails for 
some storeFileTypes (#6980)
    
    Signed-off-by: Duo Zhang <[email protected]>
    (cherry picked from commit c979be846f73d226c59fb37f186b916ccf9bc9bc)
---
 .../hadoop/hbase/io/crypto/tls/X509Util.java       | 17 +++++---
 .../hbase/security/TestNettyTLSIPCFileWatcher.java | 50 ++++++++++++++++++++--
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git 
a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java
 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java
index 4f9d2f5611b..37f6222844f 100644
--- 
a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java
+++ 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java
@@ -154,7 +154,10 @@ public final class X509Util {
 
   private static final String[] DEFAULT_CIPHERS_OPENSSL = 
getOpenSslFilteredDefaultCiphers();
 
-  private static final Duration FILE_POLL_INTERVAL = Duration.ofMinutes(1);
+  public static final String HBASE_TLS_FILEPOLL_INTERVAL_MILLIS =
+    CONFIG_PREFIX + "filepoll.interval.millis";
+  // 1 minute
+  private static final long DEFAULT_FILE_POLL_INTERVAL = 
Duration.ofSeconds(60).toMillis();
 
   /**
    * Not all of our default ciphers are available in OpenSSL. Takes our 
default cipher lists and
@@ -496,23 +499,25 @@ public final class X509Util {
     AtomicReference<FileChangeWatcher> trustStoreWatcher, Runnable 
resetContext)
     throws IOException {
     String keyStoreLocation = config.get(TLS_CONFIG_KEYSTORE_LOCATION, "");
-    keystoreWatcher.set(newFileChangeWatcher(keyStoreLocation, resetContext));
+    keystoreWatcher.set(newFileChangeWatcher(config, keyStoreLocation, 
resetContext));
     String trustStoreLocation = config.get(TLS_CONFIG_TRUSTSTORE_LOCATION, "");
     // we are using the same callback for both. there's no reason to kick off 
two
     // threads if keystore/truststore are both at the same location
     if (!keyStoreLocation.equals(trustStoreLocation)) {
-      trustStoreWatcher.set(newFileChangeWatcher(trustStoreLocation, 
resetContext));
+      trustStoreWatcher.set(newFileChangeWatcher(config, trustStoreLocation, 
resetContext));
     }
   }
 
-  private static FileChangeWatcher newFileChangeWatcher(String fileLocation, 
Runnable resetContext)
-    throws IOException {
+  private static FileChangeWatcher newFileChangeWatcher(Configuration config, 
String fileLocation,
+    Runnable resetContext) throws IOException {
     if (fileLocation == null || fileLocation.isEmpty() || resetContext == 
null) {
       return null;
     }
     final Path filePath = Paths.get(fileLocation).toAbsolutePath();
     FileChangeWatcher fileChangeWatcher =
-      new FileChangeWatcher(filePath, 
Objects.toString(filePath.getFileName()), FILE_POLL_INTERVAL,
+      new FileChangeWatcher(filePath, Objects.toString(filePath.getFileName()),
+        Duration
+          .ofMillis(config.getLong(HBASE_TLS_FILEPOLL_INTERVAL_MILLIS, 
DEFAULT_FILE_POLL_INTERVAL)),
         watchEventFilePath -> handleWatchEvent(watchEventFilePath, 
resetContext));
     fileChangeWatcher.start();
     return fileChangeWatcher;
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestNettyTLSIPCFileWatcher.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestNettyTLSIPCFileWatcher.java
index 403a538f024..1fdc44004bc 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestNettyTLSIPCFileWatcher.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestNettyTLSIPCFileWatcher.java
@@ -27,10 +27,16 @@ import static org.mockito.Mockito.when;
 import java.io.File;
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.GeneralSecurityException;
 import java.security.Security;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import org.apache.commons.io.FileUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseClassTestRule;
@@ -38,6 +44,7 @@ import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
 import org.apache.hadoop.hbase.HBaseConfiguration;
 import org.apache.hadoop.hbase.HBaseServerBase;
 import org.apache.hadoop.hbase.ServerName;
+import org.apache.hadoop.hbase.io.FileChangeWatcher;
 import org.apache.hadoop.hbase.io.crypto.tls.KeyStoreFileType;
 import org.apache.hadoop.hbase.io.crypto.tls.X509KeyType;
 import org.apache.hadoop.hbase.io.crypto.tls.X509TestContext;
@@ -66,6 +73,8 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
 import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
@@ -81,6 +90,8 @@ public class TestNettyTLSIPCFileWatcher {
   public static final HBaseClassTestRule CLASS_RULE =
     HBaseClassTestRule.forClass(TestNettyTLSIPCFileWatcher.class);
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(TestNettyTLSIPCFileWatcher.class);
+
   private static final Configuration CONF = HBaseConfiguration.create();
   private static final HBaseCommonTestingUtil UTIL = new 
HBaseCommonTestingUtil(CONF);
   private static HBaseServerBase<?> SERVER;
@@ -136,6 +147,7 @@ public class TestNettyTLSIPCFileWatcher {
     CONF.setBoolean(X509Util.HBASE_SERVER_NETTY_TLS_SUPPORTPLAINTEXT, false);
     CONF.setBoolean(X509Util.HBASE_CLIENT_NETTY_TLS_ENABLED, true);
     CONF.setBoolean(X509Util.TLS_CERT_RELOAD, true);
+    CONF.setLong(X509Util.HBASE_TLS_FILEPOLL_INTERVAL_MILLIS, 10);
   }
 
   @After
@@ -144,6 +156,7 @@ public class TestNettyTLSIPCFileWatcher {
     x509TestContext.getConf().unset(X509Util.TLS_CONFIG_OCSP);
     x509TestContext.getConf().unset(X509Util.TLS_CONFIG_CLR);
     x509TestContext.getConf().unset(X509Util.TLS_CONFIG_PROTOCOL);
+    
x509TestContext.getConf().unset(X509Util.HBASE_TLS_FILEPOLL_INTERVAL_MILLIS);
     System.clearProperty("com.sun.net.ssl.checkRevocation");
     System.clearProperty("com.sun.security.enableCRLDP");
     Security.setProperty("ocsp.enable", Boolean.FALSE.toString());
@@ -151,8 +164,8 @@ public class TestNettyTLSIPCFileWatcher {
   }
 
   @Test
-  public void testReplaceServerKeystore()
-    throws IOException, ServiceException, GeneralSecurityException, 
OperatorCreationException {
+  public void testReplaceServerKeystore() throws IOException, ServiceException,
+    GeneralSecurityException, OperatorCreationException, InterruptedException {
     Configuration clientConf = new Configuration(CONF);
     RpcServer rpcServer = createRpcServer("testRpcServer",
       Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(SERVICE, 
null)),
@@ -172,9 +185,18 @@ public class TestNettyTLSIPCFileWatcher {
         assertNull(pcrc.cellScanner());
       }
 
+      // truststore file change latch
+      final CountDownLatch latch = new CountDownLatch(1);
+      final Path trustStorePath = 
Paths.get(CONF.get(X509Util.TLS_CONFIG_TRUSTSTORE_LOCATION));
+      createAndStartFileWatcher(trustStorePath, latch, Duration.ofMillis(20));
+
       // Replace keystore
       x509TestContext.regenerateStores(keyType, keyType, storeFileType, 
storeFileType);
 
+      if (!latch.await(1, TimeUnit.SECONDS)) {
+        throw new AssertionError("Timed out waiting for truststore file to be 
changed");
+      }
+
       try (AbstractRpcClient<?> client = new NettyRpcClient(clientConf)) {
         TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface stub =
           newBlockingStub(client, rpcServer.getListenerAddress());
@@ -192,8 +214,8 @@ public class TestNettyTLSIPCFileWatcher {
   }
 
   @Test
-  public void testReplaceClientAndServerKeystore()
-    throws GeneralSecurityException, IOException, OperatorCreationException, 
ServiceException {
+  public void testReplaceClientAndServerKeystore() throws 
GeneralSecurityException, IOException,
+    OperatorCreationException, ServiceException, InterruptedException {
     Configuration clientConf = new Configuration(CONF);
     RpcServer rpcServer = createRpcServer("testRpcServer",
       Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(SERVICE, 
null)),
@@ -212,11 +234,21 @@ public class TestNettyTLSIPCFileWatcher {
             .getMessage());
         assertNull(pcrc.cellScanner());
 
+        // truststore file change latch
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        final Path trustStorePath = 
Paths.get(CONF.get(X509Util.TLS_CONFIG_TRUSTSTORE_LOCATION));
+        createAndStartFileWatcher(trustStorePath, latch, 
Duration.ofMillis(20));
+
         // Replace keystore and cancel client connections
         x509TestContext.regenerateStores(keyType, keyType, storeFileType, 
storeFileType);
         client.cancelConnections(
           
ServerName.valueOf(Address.fromSocketAddress(rpcServer.getListenerAddress()), 
0L));
 
+        if (!latch.await(1, TimeUnit.SECONDS)) {
+          throw new AssertionError("Timed out waiting for truststore file to 
be changed");
+        }
+
         assertEquals(message,
           stub.echo(pcrc, 
TestProtos.EchoRequestProto.newBuilder().setMessage(message).build())
             .getMessage());
@@ -232,4 +264,14 @@ public class TestNettyTLSIPCFileWatcher {
     Configuration conf, RpcScheduler scheduler) throws IOException {
     return new NettyRpcServer(SERVER, name, services, bindAddress, conf, 
scheduler, true);
   }
+
+  private void createAndStartFileWatcher(Path trustStorePath, CountDownLatch 
latch,
+    Duration duration) throws IOException {
+    FileChangeWatcher fileChangeWatcher = new FileChangeWatcher(trustStorePath,
+      Objects.toString(trustStorePath.getFileName()), duration, 
watchEventFilePath -> {
+        LOG.info("File " + watchEventFilePath.getFileName() + " has been 
changed.");
+        latch.countDown();
+      });
+    fileChangeWatcher.start();
+  }
 }

Reply via email to