Skip to content

Commit

Permalink
HBASE-28317 Expose client TLS certificate on RpcCallContext (#5644)
Browse files Browse the repository at this point in the history
Signed-off-by: Duo Zhang <zhangduo@apache.org>
Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
  • Loading branch information
charlesconnell authored and bbeaudreault committed Jan 29, 2024
1 parent 223c990 commit 28e482c
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
import java.io.InterruptedIOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLPeerUnverifiedException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
Expand Down Expand Up @@ -172,10 +175,10 @@ protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
FixedLengthFrameDecoder preambleDecoder = new FixedLengthFrameDecoder(6);
preambleDecoder.setSingleDecode(true);
NettyServerRpcConnection conn = createNettyServerRpcConnection(ch);
if (conf.getBoolean(HBASE_SERVER_NETTY_TLS_ENABLED, false)) {
initSSL(pipeline, conf.getBoolean(HBASE_SERVER_NETTY_TLS_SUPPORTPLAINTEXT, true));
initSSL(pipeline, conn, conf.getBoolean(HBASE_SERVER_NETTY_TLS_SUPPORTPLAINTEXT, true));
}
NettyServerRpcConnection conn = createNettyServerRpcConnection(ch);
pipeline.addLast(NettyRpcServerPreambleHandler.DECODER_NAME, preambleDecoder)
.addLast(new NettyRpcServerPreambleHandler(NettyRpcServer.this, conn))
// We need NettyRpcServerResponseEncoder here because NettyRpcServerPreambleHandler may
Expand Down Expand Up @@ -401,7 +404,7 @@ public Pair<Message, CellScanner> call(BlockingService service, MethodDescriptor
return call(fakeCall, status);
}

private void initSSL(ChannelPipeline p, boolean supportPlaintext)
private void initSSL(ChannelPipeline p, NettyServerRpcConnection conn, boolean supportPlaintext)
throws X509Exception, IOException {
SslContext nettySslContext = getSslContext();

Expand Down Expand Up @@ -436,6 +439,28 @@ 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 -> {
try {
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates();
if (certificates != null && certificates.length > 0) {
conn.clientCertificateChain = (X509Certificate[]) certificates;
} else if (sslHandler.engine().getNeedClientAuth()) {
LOG.error(
"Could not get peer certificate on TLS connection from {}, although one is required",
remoteAddress);
}
} catch (SSLPeerUnverifiedException e) {
if (sslHandler.engine().getNeedClientAuth()) {
LOG.error(
"Could not get peer certificate on TLS connection from {}, although one is required",
remoteAddress, e);
}
} catch (Exception e) {
LOG.error("Unexpected error getting peer certificate for TLS connection from {}",
remoteAddress, e);
}
});

p.addLast("ssl", sslHandler);
LOG.debug("SSL handler added for channel: {}", p.channel());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.ipc;

import java.net.InetAddress;
import java.security.cert.X509Certificate;
import java.util.Optional;
import org.apache.hadoop.hbase.security.User;
import org.apache.yetus.audience.InterfaceAudience;
Expand Down Expand Up @@ -60,6 +61,13 @@ default Optional<String> getRequestUserName() {
return getRequestUser().map(User::getShortName);
}

/**
* Returns the TLS certificate(s) that the client presented to this HBase server when making its
* connection. TLS is orthogonal to Kerberos, so this is unrelated to
* {@link RpcCallContext#getRequestUser()}. Both, one, or neither may be present.
*/
Optional<X509Certificate[]> getClientCertificateChain();

/** Returns Address of remote client in this call */
InetAddress getRemoteAddress();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -96,6 +97,7 @@ public abstract class ServerCall<T extends ServerRpcConnection> implements RpcCa

protected final User user;
protected final InetAddress remoteAddress;
protected final X509Certificate[] clientCertificateChain;
protected RpcCallback rpcCallback;

private long responseCellSize = 0;
Expand Down Expand Up @@ -136,9 +138,11 @@ public abstract class ServerCall<T extends ServerRpcConnection> implements RpcCa
if (connection != null) {
this.user = connection.user;
this.retryImmediatelySupported = connection.retryImmediatelySupported;
this.clientCertificateChain = connection.clientCertificateChain;
} else {
this.user = null;
this.retryImmediatelySupported = false;
this.clientCertificateChain = null;
}
this.remoteAddress = remoteAddress;
this.timeout = timeout;
Expand Down Expand Up @@ -499,6 +503,11 @@ public Optional<User> getRequestUser() {
return Optional.ofNullable(user);
}

@Override
public Optional<X509Certificate[]> getClientCertificateChain() {
return Optional.ofNullable(clientCertificateChain);
}

@Override
public InetAddress getRemoteAddress() {
return remoteAddress;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -133,6 +134,7 @@ abstract class ServerRpcConnection implements Closeable {
protected User user = null;
protected UserGroupInformation ugi = null;
protected SaslServerAuthenticationProviders saslProviders = null;
protected X509Certificate[] clientCertificateChain = null;

public ServerRpcConnection(RpcServer rpcServer) {
this.rpcServer = rpcServer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.net.InetAddress;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -814,6 +815,11 @@ public Optional<User> getRequestUser() {
return getUser(userName);
}

@Override
public Optional<X509Certificate[]> getClientCertificateChain() {
return Optional.empty();
}

@Override
public InetAddress getRemoteAddress() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
Expand Down Expand Up @@ -213,6 +214,11 @@ public Optional<User> getRequestUser() {
return null;
}

@Override
public Optional<X509Certificate[]> getClientCertificateChain() {
return Optional.empty();
}

@Override
public InetAddress getRemoteAddress() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.io.IOException;
import java.net.InetAddress;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -275,6 +276,11 @@ public Optional<User> getRequestUser() {
return Optional.empty();
}

@Override
public Optional<X509Certificate[]> getClientCertificateChain() {
return Optional.empty();
}

@Override
public InetAddress getRemoteAddress() {
return null;
Expand Down

0 comments on commit 28e482c

Please sign in to comment.