-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
In Netty 4.2 we changed the default endpoint identification algorithm to “HTTPS”, thereby enabling hostname verification by default.
This has no effect on gRPC-Java, because it was already always enabling hostname verification:
grpc-java/netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java
Lines 651 to 661 in 7322c07
@Override | |
@IgnoreJRERequirement | |
protected void handlerAdded0(ChannelHandlerContext ctx) { | |
sslEngine = sslContext.newEngine(ctx.alloc(), host, port); | |
SSLParameters sslParams = sslEngine.getSSLParameters(); | |
sslParams.setEndpointIdentificationAlgorithm("HTTPS"); | |
sslEngine.setSSLParameters(sslParams); | |
ctx.pipeline().addBefore(ctx.name(), /* name= */ null, this.executor != null | |
? new SslHandler(sslEngine, false, this.executor) | |
: new SslHandler(sslEngine, false)); | |
} |
Unfortunately, the above means gRPC-Java doesn’t offer any nice way to disable hostname verification in situations where the client expects a non-DNS identity from the server, such as a SPIFFE in a URI SAN.
A client that wishes to authenticate non-DNS identities needs to implement a custom TrustManager
that nerfs out the endpoint identification algorithm in the provided SSLEngine
, before proceeding with the authentication procedure. When we use the OPENSSL provider, this adds an extra JNI call per handshake that could otherwise be avoided.
A better approach would be to configure the endpoint identification algorithm in the SslContextBuilder
. Since Netty 4.1.112, we’ve been exposing this as a configuration method:
https://netty.io/4.1/api/io/netty/handler/ssl/SslContextBuilder.html#endpointIdentificationAlgorithm-java.lang.String-
The GrpcSslContexts
class in gRPC-Java already provides ssl context builder objects with sane defaults that people are encouraged to use. It makes sense that it would provide instances to clients that have the “HTTPS” endpoint identification algorithm pre-configured. Clients could then choose to opt out of hostname verification if they need to.
Now, with the above proposed change, if people don’t use the GrpcSslContexts
class but instead create their own SslContextBuilder
, then it’s possible that they were previously protected by hostname verification but now no longer are.
It is possible to issue or log a warning, in that case. There are two ways to disable hostname verification: 1) the endpoint identification algorithm can be null
(the default in 4.1), or 2) the algorithm can be the empty string. In gRPC-Java, we can use these to distinguish between a poor default, null
, and intentionally opting out of hostname verification with the empty string.
Alternatively, gRPC-Java can overwrite the null
values to preserve the default safety it currently enjoy, and then accept the empty string as an intentional choice to opt out.
By removing the code in the ClientTlsHandler
and instead relying on the setter in the SslContextBuilder
, we can get the authentication flexibility that certain clients need for dealing with non-DNS identities, while preserving the safe defaults we currently have.