This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-grpc.git
The following commit(s) were added to refs/heads/main by this push:
new af8aa19e add verify-hostname support (#820)
af8aa19e is described below
commit af8aa19e73ca07995b6b06dce2c85895dff6f726
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Aug 5 11:04:51 2026 +0100
add verify-hostname support (#820)
---
runtime/src/main/resources/reference.conf | 6 ++++
.../org/apache/pekko/grpc/GrpcClientSettings.scala | 22 ++++++++++---
.../pekko/grpc/internal/PekkoHttpClientUtils.scala | 36 ++++++++++++++++------
3 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/runtime/src/main/resources/reference.conf
b/runtime/src/main/resources/reference.conf
index 99fcc62a..89a84f85 100644
--- a/runtime/src/main/resources/reference.conf
+++ b/runtime/src/main/resources/reference.conf
@@ -38,6 +38,12 @@ pekko.grpc.client."*" {
# leave empty to auto-detect, or configure 'jdk' or 'openssl'.
ssl-provider = ""
+ # Whether to verify the server's hostname against its TLS certificate (RFC
2818).
+ # When false (the default), the client accepts any valid certificate
regardless
+ # of hostname. This is insecure for production and should only be used for
testing.
+ # Only effective for the pekko-http backend; the netty backend always
verifies.
+ verify-hostname = false
+
# TODO: Enforce HTTP/2 TLS restrictions:
https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-9.2
# The number of times to try connecting before giving up.
diff --git
a/runtime/src/main/scala/org/apache/pekko/grpc/GrpcClientSettings.scala
b/runtime/src/main/scala/org/apache/pekko/grpc/GrpcClientSettings.scala
index 8b933314..16eb934b 100644
--- a/runtime/src/main/scala/org/apache/pekko/grpc/GrpcClientSettings.scala
+++ b/runtime/src/main/scala/org/apache/pekko/grpc/GrpcClientSettings.scala
@@ -158,7 +158,8 @@ object GrpcClientSettings {
getOptionalString(clientConfiguration, "user-agent"),
clientConfiguration.getBoolean("use-tls"),
getOptionalString(clientConfiguration, "load-balancing-policy"),
- clientConfiguration.getString("backend"))
+ clientConfiguration.getString("backend"),
+ verifyHostname = clientConfiguration.getBoolean("verify-hostname"))
private def getOptionalString(config: Config, path: String): Option[String] =
config.getString(path) match {
@@ -206,7 +207,8 @@ final class GrpcClientSettings private (
val useTls: Boolean,
val loadBalancingPolicy: Option[String],
val backend: String,
- val channelBuilderOverrides: NettyChannelBuilder => NettyChannelBuilder =
identity) {
+ val channelBuilderOverrides: NettyChannelBuilder => NettyChannelBuilder =
identity,
+ val verifyHostname: Boolean) {
require(
sslContext.isEmpty || trustManager.isEmpty,
"Configuring the sslContext or the trustManager is mutually exclusive")
@@ -289,6 +291,16 @@ final class GrpcClientSettings private (
def withBackend(value: String): GrpcClientSettings =
copy(backend = value)
+ /**
+ * Whether to verify the server's hostname against its TLS certificate (RFC
2818).
+ * When false (the default), the client accepts any valid certificate
regardless
+ * of hostname. This is insecure for production and should only be used for
testing.
+ * Only effective for the pekko-http backend; the netty backend always
verifies.
+ * @since 2.0.0
+ */
+ def withVerifyHostname(value: Boolean): GrpcClientSettings =
+ copy(verifyHostname = value)
+
private def copy(
serviceName: String = serviceName,
servicePortName: Option[String] = servicePortName,
@@ -306,7 +318,8 @@ final class GrpcClientSettings private (
connectionAttempts: Option[Int] = connectionAttempts,
loadBalancingPolicy: Option[String] = loadBalancingPolicy,
backend: String = backend,
- channelBuilderOverrides: NettyChannelBuilder => NettyChannelBuilder =
channelBuilderOverrides)
+ channelBuilderOverrides: NettyChannelBuilder => NettyChannelBuilder =
channelBuilderOverrides,
+ verifyHostname: Boolean = verifyHostname)
: GrpcClientSettings =
new GrpcClientSettings(
callCredentials = callCredentials,
@@ -326,5 +339,6 @@ final class GrpcClientSettings private (
connectionAttempts = connectionAttempts,
loadBalancingPolicy = loadBalancingPolicy,
backend = backend,
- channelBuilderOverrides = channelBuilderOverrides)
+ channelBuilderOverrides = channelBuilderOverrides,
+ verifyHostname = verifyHostname)
}
diff --git
a/runtime/src/main/scala/org/apache/pekko/grpc/internal/PekkoHttpClientUtils.scala
b/runtime/src/main/scala/org/apache/pekko/grpc/internal/PekkoHttpClientUtils.scala
index c9797961..f4fe196e 100644
---
a/runtime/src/main/scala/org/apache/pekko/grpc/internal/PekkoHttpClientUtils.scala
+++
b/runtime/src/main/scala/org/apache/pekko/grpc/internal/PekkoHttpClientUtils.scala
@@ -96,18 +96,34 @@ object PekkoHttpClientUtils {
val http2client =
if (settings.useTls) {
- val connectionContext =
- ConnectionContext.httpsClient {
- settings.sslContext.getOrElse {
- settings.trustManager match {
- case None => SSLContext.getDefault
- case Some(trustManager) =>
- val sslContext: SSLContext = SSLContext.getInstance("TLS")
- sslContext.init(Array[KeyManager](),
Array[TrustManager](trustManager), new SecureRandom)
- sslContext
- }
+ if (!settings.verifyHostname) {
+ log.warning(
+ "TLS hostname verification is disabled for pekko-http client '{}'.
" +
+ "This is insecure and should only be used for testing. " +
+ "Enable it with verify-hostname = true in your configuration. " +
+ "Note: the netty backend always verifies hostnames.",
+ settings.serviceName)
+ }
+ val sslContext =
+ settings.sslContext.getOrElse {
+ settings.trustManager match {
+ case None => SSLContext.getDefault
+ case Some(trustManager) =>
+ val ctx: SSLContext = SSLContext.getInstance("TLS")
+ ctx.init(Array[KeyManager](),
Array[TrustManager](trustManager), new SecureRandom)
+ ctx
}
}
+ val connectionContext =
+ ConnectionContext.httpsClient((hostname, port) => {
+ val engine = sslContext.createSSLEngine(hostname, port)
+ if (settings.verifyHostname) {
+ val sslParams = engine.getSSLParameters
+ sslParams.setEndpointIdentificationAlgorithm("HTTPS")
+ engine.setSSLParameters(sslParams)
+ }
+ engine
+ })
builder.withCustomHttpsConnectionContext(connectionContext).managedPersistentHttp2()
} else {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]