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();
+ }
}