-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HBASE-28317: Expose client TLS certificate on RpcCallContext #5644
HBASE-28317: Expose client TLS certificate on RpcCallContext #5644
Conversation
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
@@ -413,6 +415,19 @@ private void initSSL(ChannelPipeline p, boolean supportPlaintext) | |||
sslHandler.setWrapDataSize( | |||
conf.getInt(HBASE_SERVER_NETTY_TLS_WRAP_SIZE, DEFAULT_HBASE_SERVER_NETTY_TLS_WRAP_SIZE)); | |||
|
|||
sslHandler.handshakeFuture().addListener(future -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Apache9 do you think a listener is the right approach here? I'm wondering if we should instead pass the SSLHandler into NettyServerRpcConnection, and directly call handler.handshakeFuture().get()
in setupHandlers()
. That way it's more explicit that we have the certificate on the connection prior to handling any requests. With the listener approach, I'm not 100% sure we can guarantee that the listener is executed in the eventLoop prior to the channelRead0 in NettyRpcServerPreambleHandler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should never do future.get in event loop thread, as it has serious performance impact, or even dead lock...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Do you think we should leave it as is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://stackoverflow.com/questions/70654915/order-of-invocation-of-listeners
Norman Maurer answered that the invocation order of listeners is the same with adding order. And I checked the code, if there are multiple listeners netty will call them sequentially, with the adding order. So here, since we are the first listener(at least first in the listeners added by our code), so I think we can guarantee that NettyRpcServerPreambleHandler.channelRead can see the certificates.
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates(); | ||
if (certificates.length > 0) { | ||
conn.clientCertificate = (X509Certificate) certificates[0]; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should inspect the sslHandler.engine().getNeedClientAuth()
and throw an exception if no certificate is found here and/or in the exception below. See https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java#L418-L463 for how zookeeper handles hits.
Another thing I notice in zookeeper is that they set the entire Certificate[] onto the connection, so that someone can inspect the whole certificate chain if they want. I think we should probably do that in order to avoid having to break this interface in the future if someone wants more than the head of the chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed the interface to use the certificate chain. I'm also logging when getNeedClientAuth()
is true but no certificate is found. I don't think throwing an exception in this listener is any more useful than logging, it wouldn't block a connection from forming. I also don't necessarily think that it's the job of this code to verify that connections that require mutual auth are doing it. Netty is already enforcing that.
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
Test failures appear unrelated to this PR |
hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcCallContext.java
Outdated
Show resolved
Hide resolved
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
) (#69) Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
At my employer we plan on using a coprocessor to log information about some requests to HBase. For this to be useful to us, we need to know who each request is coming from. We use HBase's TLS support with mutual authentication to authenticate clients. I'd like a way to expose the client certificate used on a request to coprocessors. For setups using Kerberos authentication, RpcCall exposes the Kerberos principal shortname via
getRequestUser()
, so this would be the TLS equivalent to that. I've tested this patch applied to 2.5.x in my company's infrastructure.I found that in order for this patch to be useful to me, I also need netty to fix a related bug which I reported as netty/netty#13796. This doesn't need to block this PR.