This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 4256d38070d Add keystore truststore expire check and avoid unnecessary
error log printed (#16552)
4256d38070d is described below
commit 4256d38070d0773b68a761a06836ad3f8b1d6793
Author: Haonan <[email protected]>
AuthorDate: Sat Oct 11 18:47:53 2025 +0800
Add keystore truststore expire check and avoid unnecessary error log
printed (#16552)
* Add keystore truststore expire check
* Avoid unnecessary error log printed
* Avoid print file name when access denied
* avoid file name printed
---
.../apache/iotdb/rpc/BaseRpcTransportFactory.java | 12 +++++-
.../iotdb/rpc/NettyTNonblockingTransport.java | 23 ++++++++---
.../apache/iotdb/rpc/TElasticFramedTransport.java | 10 +++++
.../org/apache/iotdb/db/service/RestService.java | 2 +-
.../service/AbstractThriftServiceThread.java | 45 +++++++++++++++++++++-
5 files changed, 83 insertions(+), 9 deletions(-)
diff --git
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
index 1175b16a935..eccebe2eafe 100644
---
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
+++
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
@@ -26,6 +26,10 @@ import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.TTransportFactory;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
@SuppressWarnings("java:S1135") // ignore todos
public class BaseRpcTransportFactory extends TTransportFactory {
@@ -95,8 +99,12 @@ public class BaseRpcTransportFactory extends
TTransportFactory {
throws TTransportException {
TSSLTransportFactory.TSSLTransportParameters params =
new TSSLTransportFactory.TSSLTransportParameters();
- params.setTrustStore(trustStore, trustStorePwd);
- params.setKeyStore(keyStore, keyStorePwd);
+ if (Files.exists(Paths.get(trustStore)) &&
Files.exists(Paths.get(keyStore))) {
+ params.setTrustStore(trustStore, trustStorePwd);
+ params.setKeyStore(keyStore, keyStorePwd);
+ } else {
+ throw new TTransportException(new IOException("Could not load keystore
or truststore file"));
+ }
TTransport transport = TSSLTransportFactory.getClientSocket(ip, port,
timeout, params);
return inner.getTransport(transport);
}
diff --git
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/NettyTNonblockingTransport.java
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/NettyTNonblockingTransport.java
index 8cf6c51a95c..b42b901cc18 100644
---
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/NettyTNonblockingTransport.java
+++
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/NettyTNonblockingTransport.java
@@ -47,6 +47,7 @@ import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
@@ -54,6 +55,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
+import java.nio.file.AccessDeniedException;
import java.security.KeyStore;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
@@ -166,12 +168,15 @@ public class NettyTNonblockingTransport extends
TNonblockingTransport {
"SSL handshake completed successfully for
{}:{}", host, port);
}
} else {
- if (logger.isDebugEnabled()) {
+ if (!future
+ .cause()
+ .getMessage()
+ .contains("SslHandler removed before handshake
completed")) {
+ logger.warn(
+ "SSL handshake failed for {}:{}", host,
port, future.cause());
+ } else if (logger.isDebugEnabled()) {
logger.debug(
- "SSL handshake failed for {}:{}: {}",
- host,
- port,
- future.cause().getMessage());
+ "SSL handshake failed for {}:{}", host,
port, future.cause());
}
}
});
@@ -187,6 +192,10 @@ public class NettyTNonblockingTransport extends
TNonblockingTransport {
KeyStore keyStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream(keystorePath)) {
keyStore.load(fis, keystorePassword.toCharArray());
+ } catch (AccessDeniedException e) {
+ throw new AccessDeniedException("Failed to load keystore file");
+ } catch (FileNotFoundException e) {
+ throw new FileNotFoundException("keystore file not found");
}
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
@@ -198,6 +207,10 @@ public class NettyTNonblockingTransport extends
TNonblockingTransport {
KeyStore trustStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream(truststorePath)) {
trustStore.load(fis, truststorePassword.toCharArray());
+ } catch (AccessDeniedException e) {
+ throw new AccessDeniedException("Failed to load truststore file");
+ } catch (FileNotFoundException e) {
+ throw new FileNotFoundException("truststore file not found");
}
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
diff --git
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
index 05a6a83117d..0ff58f71e12 100644
---
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
+++
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
@@ -25,6 +25,9 @@ import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.TTransportFactory;
import org.apache.thrift.transport.layered.TFramedTransport;
+import javax.net.ssl.SSLHandshakeException;
+
+import java.io.EOFException;
import java.net.SocketTimeoutException;
// https://github.com/apache/thrift/blob/master/doc/specs/thrift-rpc.md
@@ -126,6 +129,13 @@ public class TElasticFramedTransport extends TTransport {
if (e.getCause() instanceof SocketTimeoutException) {
throw new TTransportException(TTransportException.TIMED_OUT,
e.getCause());
}
+ // When client with SSL shut down due to time out. Some unnecessary
error logs may be printed.
+ // Adding this workaround to avoid the problem.
+ if (e.getCause() instanceof SSLHandshakeException
+ && e.getCause().getCause() != null
+ && e.getCause().getCause() instanceof EOFException) {
+ throw new TTransportException(TTransportException.END_OF_FILE,
e.getCause());
+ }
throw e;
}
return readBuffer.read(buf, off, len);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RestService.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RestService.java
index fa8df0c9a69..7fc4d788380 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RestService.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RestService.java
@@ -67,7 +67,7 @@ public class RestService implements IService {
if (clientAuth) {
sslContextFactory.setTrustStorePath(trustStorePath);
sslContextFactory.setTrustStorePassword(trustStorePwd);
- sslContextFactory.setNeedClientAuth(clientAuth);
+ sslContextFactory.setNeedClientAuth(true);
}
ServerConnector httpsConnector =
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
index 7537308d6cd..39b11ba677a 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
@@ -44,7 +44,13 @@ import org.apache.thrift.transport.TTransportFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.net.InetSocketAddress;
+import java.nio.file.AccessDeniedException;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@@ -177,13 +183,15 @@ public abstract class AbstractThriftServiceThread extends
Thread {
this.serviceName = serviceName;
try {
+ validateCertificate(keyStorePath, keyStorePwd);
TSSLTransportFactory.TSSLTransportParameters params =
new TSSLTransportFactory.TSSLTransportParameters();
params.setKeyStore(keyStorePath, keyStorePwd);
if (trustStorePath != null && !trustStorePath.isEmpty()) {
+ validateCertificate(trustStorePath, trustStorePwd);
params.setTrustStore(trustStorePath, trustStorePwd);
+ params.requireClientAuth(true);
}
- params.requireClientAuth(false);
InetSocketAddress socketAddress = new InetSocketAddress(bindAddress,
port);
serverTransport =
TSSLTransportFactory.getServerSocket(
@@ -197,6 +205,41 @@ public abstract class AbstractThriftServiceThread extends
Thread {
}
}
+ private static void validateCertificate(String keyStorePath, String
keystorePassword)
+ throws TTransportException {
+ try {
+ KeyStore keystore = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(keyStorePath)) {
+ keystore.load(fis, keystorePassword.toCharArray());
+ }
+
+ Enumeration<String> aliases = keystore.aliases();
+ while (aliases.hasMoreElements()) {
+ String currentAlias = aliases.nextElement();
+ checkCertificate(keystore, currentAlias);
+ }
+ } catch (AccessDeniedException e) {
+ throw new TTransportException("Failed to load keystore or truststore
file");
+ } catch (FileNotFoundException e) {
+ throw new TTransportException("keystore or truststore file not found");
+ } catch (Exception e) {
+ throw new TTransportException(e);
+ }
+ }
+
+ private static void checkCertificate(KeyStore keystore, String alias) throws
Exception {
+ if (!keystore.containsAlias(alias)) {
+ return;
+ }
+
+ X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
+ if (cert == null) {
+ return;
+ }
+
+ cert.checkValidity();
+ }
+
@SuppressWarnings("squid:S107")
protected AbstractThriftServiceThread(
TProcessor processor,