This is an automated email from the ASF dual-hosted git repository. He-Pin pushed a commit to branch fix/tls-observability-3162 in repository https://gitbox.apache.org/repos/asf/pekko.git
commit 34a891115fa04e705f6121d61460eaea65a82024 Author: 虎鸣 <[email protected]> AuthorDate: Wed Jun 24 04:04:31 2026 +0800 fix: improve TLS observability - handshake failure logging and fail-fast SSL init Motivation: Classic remoting TLS handshake failures were silently swallowed: the NettySSLSupport handshake listener closed the channel without logging the failure reason or peer address. Additionally, SSLContext was lazily initialized, meaning keystore/truststore errors were only discovered on the first connection attempt rather than at startup. Modification: - NettySSLSupport: add MarkerLoggingAdapter parameter, log TLS handshake failures with peer address and cause - NettyTransport: pass log to NettySSLSupport - ConfigSSLEngineProvider: change sslContext from lazy val to val for eager initialization (fail-fast at provider construction time) Result: TLS handshake failures now produce actionable warning logs with peer address and error cause. Keystore/truststore configuration errors are detected at startup rather than on first connection. Tests: - remote / Test / testOnly org.apache.pekko.remote.ConfigSSLEngineProviderSpec - remote / Test / testOnly org.apache.pekko.remote.Ticket1978ConfigSpec References: Fixes #3162 --- .../remote/transport/netty/NettySSLSupport.scala | 8 +++- .../remote/transport/netty/NettyTransport.scala | 2 +- .../remote/transport/netty/SSLEngineProvider.scala | 2 +- .../pekko/remote/ConfigSSLEngineProviderSpec.scala | 47 ++++++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettySSLSupport.scala b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettySSLSupport.scala index c127e4b0e8..fb71b826d8 100644 --- a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettySSLSupport.scala +++ b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettySSLSupport.scala @@ -21,6 +21,7 @@ import io.netty.handler.ssl.SslHandler import io.netty.util.concurrent.Future import com.typesafe.config.Config +import org.apache.pekko.event.MarkerLoggingAdapter /** * INTERNAL API @@ -60,13 +61,18 @@ private[pekko] object NettySSLSupport { /** * Construct a SSLHandler which can be inserted into a Netty server/client pipeline */ - def apply(sslEngineProvider: SSLEngineProvider, isClient: Boolean): SslHandler = { + def apply(sslEngineProvider: SSLEngineProvider, isClient: Boolean, log: MarkerLoggingAdapter): SslHandler = { val sslEngine = if (isClient) sslEngineProvider.createClientSSLEngine() else sslEngineProvider.createServerSSLEngine() val handler = new SslHandler(sslEngine) handler.handshakeFuture().addListener((future: Future[Channel]) => { if (!future.isSuccess) { + val cause = if (future.cause() != null) future.cause() else null + log.warning( + "TLS handshake failed for remote address [{}]. {}", + sslEngine.getPeerHost, + if (cause != null) cause.getMessage else "unknown cause") handler.closeOutbound().channel().close() } }) diff --git a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettyTransport.scala b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettyTransport.scala index f64a39ac02..bba302ce03 100644 --- a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettyTransport.scala +++ b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/NettyTransport.scala @@ -423,7 +423,7 @@ class NettyTransport(val settings: NettyTransportSettings, val system: ExtendedA private def sslHandler(isClient: Boolean): SslHandler = { sslEngineProvider match { case OptionVal.Some(sslProvider) => - NettySSLSupport(sslProvider, isClient) + NettySSLSupport(sslProvider, isClient, log) case _ => throw new IllegalStateException("Expected enable-ssl=on") } diff --git a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/SSLEngineProvider.scala b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/SSLEngineProvider.scala index ecab23e25a..88619cb8fa 100644 --- a/remote/src/main/scala/org/apache/pekko/remote/transport/netty/SSLEngineProvider.scala +++ b/remote/src/main/scala/org/apache/pekko/remote/transport/netty/SSLEngineProvider.scala @@ -62,7 +62,7 @@ class ConfigSSLEngineProvider(protected val log: MarkerLoggingAdapter, private v import settings._ - private lazy val sslContext: SSLContext = { + private val sslContext: SSLContext = { try { val rng = createSecureRandom() val ctx = SSLContext.getInstance(SSLProtocol) diff --git a/remote/src/test/scala/org/apache/pekko/remote/ConfigSSLEngineProviderSpec.scala b/remote/src/test/scala/org/apache/pekko/remote/ConfigSSLEngineProviderSpec.scala new file mode 100644 index 0000000000..08e21e5c75 --- /dev/null +++ b/remote/src/test/scala/org/apache/pekko/remote/ConfigSSLEngineProviderSpec.scala @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * license agreements; and to You under the Apache License, version 2.0: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * This file is part of the Apache Pekko project, which was derived from Akka. + */ + +package org.apache.pekko.remote + +import scala.annotation.nowarn + +import org.apache.pekko +import pekko.remote.transport.netty.ConfigSSLEngineProvider +import pekko.testkit.PekkoSpec + +import com.typesafe.config.ConfigFactory + +@nowarn("msg=deprecated") +class ConfigSSLEngineProviderSpec + extends PekkoSpec( + ConfigFactory.parseString(""" + pekko { + actor.provider = remote + remote.classic.netty.ssl.security { + key-store = "/nonexistent/keystore.jks" + key-store-password = "changeme" + key-password = "changeme" + trust-store = "/nonexistent/truststore.jks" + trust-store-password = "changeme" + protocol = "TLSv1.3" + enabled-algorithms = [TLS_AES_128_GCM_SHA256] + random-number-generator = "" + require-mutual-authentication = off + } + } + """)) { + + "ConfigSSLEngineProvider" must { + "fail fast when keystore cannot be loaded" in { + intercept[RemoteTransportException] { + new ConfigSSLEngineProvider(system) + }.getMessage should include("could not be established") + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
