This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch 1.3.x
in repository https://gitbox.apache.org/repos/asf/pekko-grpc.git
The following commit(s) were added to refs/heads/1.3.x by this push:
new 953719f5 add verify-hostname support (#820) (#845)
953719f5 is described below
commit 953719f545cbf09c01b9f211dc23008d6ed1e458
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Aug 19 23:20:55 2026 +0100
add verify-hostname support (#820) (#845)
* add verify-hostname support (#820)
* upgrade setup-sbt due to build issues
* Update PekkoHttpClientUtils.scala
---
.github/workflows/build-test.yml | 14 ++++----
.github/workflows/headers.yml | 2 +-
.github/workflows/link-validator.yml | 2 +-
.../workflows/nightly-snapshot-dependency-test.yml | 2 +-
.github/workflows/publish-1.0-docs.yml | 2 +-
.github/workflows/publish-1.0-snapshots.yml | 2 +-
.github/workflows/publish-1.1-docs.yml | 2 +-
.github/workflows/publish-1.1-snapshots.yml | 2 +-
.github/workflows/publish-1.2-docs.yml | 2 +-
.github/workflows/publish-1.2-snapshots.yml | 2 +-
.github/workflows/publish-nightly.yml | 2 +-
runtime/src/main/resources/reference.conf | 6 ++++
.../org/apache/pekko/grpc/GrpcClientSettings.scala | 22 +++++++++---
.../pekko/grpc/internal/PekkoHttpClientUtils.scala | 41 +++++++++++++++-------
14 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 98456b38..0f5ffa2f 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -37,7 +37,7 @@ jobs:
java-version: 11
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
@@ -64,7 +64,7 @@ jobs:
java-version: 11
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
@@ -95,7 +95,7 @@ jobs:
java-version: ${{ matrix.JAVA_VERSION }}
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
@@ -130,7 +130,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Install go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 #
v5.5.0
@@ -162,7 +162,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
@@ -221,7 +221,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
@@ -270,7 +270,7 @@ jobs:
java-version: 11
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
diff --git a/.github/workflows/headers.yml b/.github/workflows/headers.yml
index e0c25374..f1f9128b 100644
--- a/.github/workflows/headers.yml
+++ b/.github/workflows/headers.yml
@@ -37,7 +37,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
diff --git a/.github/workflows/link-validator.yml
b/.github/workflows/link-validator.yml
index 48dba86f..845d2991 100644
--- a/.github/workflows/link-validator.yml
+++ b/.github/workflows/link-validator.yml
@@ -33,7 +33,7 @@ jobs:
java-version: 11
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Cache Coursier cache
uses: coursier/cache-action@95e5b1029b6b86e7bac033ee44a0697d8a527d2d #
v8.1.1
diff --git a/.github/workflows/nightly-snapshot-dependency-test.yml
b/.github/workflows/nightly-snapshot-dependency-test.yml
index 37bed5f3..e5401ad8 100644
--- a/.github/workflows/nightly-snapshot-dependency-test.yml
+++ b/.github/workflows/nightly-snapshot-dependency-test.yml
@@ -32,7 +32,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Test
run: |-
diff --git a/.github/workflows/publish-1.0-docs.yml
b/.github/workflows/publish-1.0-docs.yml
index e41aa9c3..bab24838 100644
--- a/.github/workflows/publish-1.0-docs.yml
+++ b/.github/workflows/publish-1.0-docs.yml
@@ -40,7 +40,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Build Documentation
run: |-
diff --git a/.github/workflows/publish-1.0-snapshots.yml
b/.github/workflows/publish-1.0-snapshots.yml
index 27470842..72c32401 100644
--- a/.github/workflows/publish-1.0-snapshots.yml
+++ b/.github/workflows/publish-1.0-snapshots.yml
@@ -31,7 +31,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Publish
run: |-
diff --git a/.github/workflows/publish-1.1-docs.yml
b/.github/workflows/publish-1.1-docs.yml
index 6cf3df6f..e2c40657 100644
--- a/.github/workflows/publish-1.1-docs.yml
+++ b/.github/workflows/publish-1.1-docs.yml
@@ -40,7 +40,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Build Documentation
run: |-
diff --git a/.github/workflows/publish-1.1-snapshots.yml
b/.github/workflows/publish-1.1-snapshots.yml
index 79531426..ee2f38c6 100644
--- a/.github/workflows/publish-1.1-snapshots.yml
+++ b/.github/workflows/publish-1.1-snapshots.yml
@@ -33,7 +33,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Publish
run: |-
diff --git a/.github/workflows/publish-1.2-docs.yml
b/.github/workflows/publish-1.2-docs.yml
index b5481c5e..475ff900 100644
--- a/.github/workflows/publish-1.2-docs.yml
+++ b/.github/workflows/publish-1.2-docs.yml
@@ -40,7 +40,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Build Documentation
run: |-
diff --git a/.github/workflows/publish-1.2-snapshots.yml
b/.github/workflows/publish-1.2-snapshots.yml
index dd775dc1..19a66976 100644
--- a/.github/workflows/publish-1.2-snapshots.yml
+++ b/.github/workflows/publish-1.2-snapshots.yml
@@ -33,7 +33,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Publish
run: |-
diff --git a/.github/workflows/publish-nightly.yml
b/.github/workflows/publish-nightly.yml
index c62a241d..a0aebfe8 100644
--- a/.github/workflows/publish-nightly.yml
+++ b/.github/workflows/publish-nightly.yml
@@ -32,7 +32,7 @@ jobs:
java-version: 8
- name: Install sbt
- uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2
+ uses: sbt/setup-sbt@8feba82adc7f01ddcf8165b86f778bdb5b82cebc # v1.5.7
- name: Publish
run: |-
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 11c6eef1..116b3188 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")
@@ -294,6 +296,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,
@@ -311,7 +323,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,
@@ -331,5 +344,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 3567bf1e..efd16b53 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
@@ -16,7 +16,7 @@ package org.apache.pekko.grpc.internal
import java.net.InetSocketAddress
import java.security.SecureRandom
import java.util.concurrent.CompletionStage
-import scala.concurrent.duration._
+
import org.apache.pekko
import pekko.{ Done, NotUsed }
import pekko.actor.ClassicActorSystemProvider
@@ -27,6 +27,7 @@ import pekko.grpc.{ GrpcClientSettings, GrpcResponseMetadata,
GrpcSingleResponse
import pekko.http.scaladsl.model.HttpEntity.{ Chunk, Chunked, LastChunk,
Strict }
import pekko.http.scaladsl.{ ClientTransport, ConnectionContext, Http }
import pekko.http.scaladsl.model._
+import pekko.http.scaladsl.model.StatusCodes
import pekko.http.scaladsl.model.headers.RawHeader
import pekko.http.scaladsl.settings.ClientConnectionSettings
import pekko.stream.{ Materializer, OverflowStrategy }
@@ -38,8 +39,8 @@ import io.grpc.{ CallOptions, MethodDescriptor, Status,
StatusRuntimeException }
import javax.net.ssl.{ KeyManager, SSLContext, TrustManager }
import scala.collection.immutable
import scala.concurrent.{ ExecutionContext, Future, Promise }
+import scala.concurrent.duration._
import scala.util.{ Failure, Success }
-import pekko.http.scaladsl.model.StatusCodes
/**
* INTERNAL API
@@ -94,18 +95,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]