Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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 @@ -443,20 +444,30 @@ private void initSSL(ChannelPipeline p, NettyServerRpcConnection conn, boolean s
sslHandler.handshakeFuture().addListener(future -> {
try {
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates();
if (certificates.length > 0) {
X509Certificate certificate = (X509Certificate) certificates[0];
if (certificates != null && certificates.length > 0) {
// Hack to work around https://github.com/netty/netty/issues/13796, remove once HBase uses Netty 4.1.107.Final or later
if (certificate instanceof LazyX509Certificate) {
Method method = certificate.getClass().getDeclaredMethod("unwrap");
method.setAccessible(true);
certificate = (X509Certificate) method.invoke(certificate);
for (int i=0; i < certificates.length; i++) {
if (certificates[i] instanceof LazyX509Certificate) {
Method method = LazyX509Certificate.class.getDeclaredMethod("unwrap");
method.setAccessible(true);
certificates[i] = (X509Certificate) method.invoke(certificates[i]);
}
}
conn.clientCertificate = certificate;
} else {
LOG.debug("No client certificate found for peer {}", remoteAddress);
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.debug("Failure getting peer certificate for {}", remoteAddress, e);
LOG.error("Unexpected error getting peer certificate for TLS connection from {}",
remoteAddress, e);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ default Optional<String> getRequestUserName() {
}

/**
* Returns the TLS certificate that the client presented to this HBase server when making its
* 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 this#getRequestUser()}. Both, one, or neither, may be present.
* {@link RpcCallContext#getRequestUser()}. Both, one, or neither may be present.
*/
Optional<X509Certificate> getClientCertificate();
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 @@ -97,7 +97,7 @@ public abstract class ServerCall<T extends ServerRpcConnection> implements RpcCa

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

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

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

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ abstract class ServerRpcConnection implements Closeable {
protected User user = null;
protected UserGroupInformation ugi = null;
protected SaslServerAuthenticationProviders saslProviders = null;
// volatile because this gets set after this object is constructed, when TLS handshake finishes
protected volatile X509Certificate clientCertificate = 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 @@ -816,7 +816,7 @@ public Optional<User> getRequestUser() {
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public Optional<User> getRequestUser() {
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public Optional<User> getRequestUser() {
}

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

Expand Down