Skip to content

Commit

Permalink
HBASE-28336 Correctly cast array of Certificates to array of X509Cert…
Browse files Browse the repository at this point in the history
…ificates (#5658)

Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
  • Loading branch information
charlesconnell authored and bbeaudreault committed Jan 30, 2024
1 parent 66d27a3 commit fdd8d56
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -416,33 +416,41 @@ private void initSSL(ChannelPipeline p, NettyServerRpcConnection conn, boolean s
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);
}
});
sslHandler.handshakeFuture()
.addListener(future -> sslHandshakeCompleteHandler(conn, sslHandler, remoteAddress));

p.addLast("ssl", sslHandler);
LOG.debug("SSL handler added for channel: {}", p.channel());
}
}

static void sslHandshakeCompleteHandler(NettyServerRpcConnection conn, SslHandler sslHandler,
SocketAddress remoteAddress) {
try {
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates();
if (certificates != null && certificates.length > 0) {
X509Certificate[] x509Certificates = new X509Certificate[certificates.length];
for (int i = 0; i < x509Certificates.length; i++) {
x509Certificates[i] = (X509Certificate) certificates[i];
}
conn.clientCertificateChain = x509Certificates;
} else if (sslHandler.engine().getNeedClientAuth()) {
LOG.debug(
"Could not get peer certificate on TLS connection from {}, although one is required",
remoteAddress);
}
} catch (SSLPeerUnverifiedException e) {
if (sslHandler.engine().getNeedClientAuth()) {
LOG.debug(
"Could not get peer certificate on TLS connection from {}, although one is required",
remoteAddress, e);
}
} catch (Exception e) {
LOG.debug("Unexpected error getting peer certificate for TLS connection from {}",
remoteAddress, e);
}
}

SslContext getSslContext() throws X509Exception, IOException {
SslContext result = sslContextForServer.get();
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,25 @@
*/
package org.apache.hadoop.hbase.ipc;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.ByteArrayInputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtil;
import org.apache.hadoop.hbase.TableName;
Expand All @@ -47,6 +61,8 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslHandler;

@Category({ RPCTests.class, MediumTests.class })
@RunWith(Parameterized.class)
public class TestNettyRpcServer {
Expand Down Expand Up @@ -122,4 +138,51 @@ protected void doTest(TableName tableName) throws Exception {
}
}

private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
+ "MIIEITCCAwmgAwIBAgIUaLL8vLOhWLCLXVHEJqXJhfmsTB8wDQYJKoZIhvcNAQEL\n"
+ "BQAwgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYD\n"
+ "VQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRlc3QgY2FzZTEYMBYGA1UE\n"
+ "CwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0eSB0ZXN0IGNhc2UxIzAh\n"
+ "BgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29tMB4XDTI0MDEyMTE5MzMy\n"
+ "MFoXDTI1MDEyMDE5MzMyMFowgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNz\n"
+ "YWNodXNldHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRl\n"
+ "c3QgY2FzZTEYMBYGA1UECwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0\n"
+ "eSB0ZXN0IGNhc2UxIzAhBgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29t\n"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+qzEZpQMjVdLj0siUcG\n"
+ "y8LIHOW4S+tgHIKFkF865qWq6FVGbROe2Z0f5W6yIamZkdxzptT0iv+8S5okNNeW\n"
+ "2NbsN/HNJIRtWfxku1Jh1gBqSkAYIjXyq7+20hIaJTzzxqike9M/Lc14EGb33Ja/\n"
+ "kDPRV3UtiM3Ntf3eALXKbrWptkbgQngCaTgtfg8IkMAEpP270wZ9fW0lDHv3NPPt\n"
+ "Zt0QSJzWSqWfu+l4ayvcUQYyNJesx9YmTHSJu69lvT4QApoX8FEiHfNCJ28R50CS\n"
+ "aIgOpCWUvkH7rqx0p9q393uJRS/S6RlLbU30xUN1fNrVmP/XAapfy+R0PSgiUi8o\n"
+ "EQIDAQABozkwNzAWBgNVHRIEDzANggt3d3cuZm9vLmNvbTAdBgNVHQ4EFgQUl4FD\n"
+ "Y8jJ/JHJR68YqPsGUjUJuwgwDQYJKoZIhvcNAQELBQADggEBADVzivYz2M0qsWUc\n"
+ "jXjCHymwTIr+7ud10um53FbYEAfKWsIY8Pp35fKpFzUwc5wVdCnLU86K/YMKRzNB\n"
+ "zL2Auow3PJFRvXecOv7dWxNlNneLDcwbVrdNRu6nQXmZUgyz0oUKuJbF+JGtI+7W\n"
+ "kRw7yhBfki+UCSQWeDqvaWzgmA4Us0N8NFq3euAs4xFbMMPMQWrT9Z7DGchCeRiB\n"
+ "dkQBvh88vbR3v2Saq14W4Wt5rj2++vXWGQSeAQL6nGbOwc3ohW6isNNV0eGQQTmS\n"
+ "khS2d/JDZq2XL5RGexf3CA6YYzWiTr9YZHNjuobvLH7mVnA2c8n6Zty/UhfnuK1x\n" + "JbkleFk=\n"
+ "-----END CERTIFICATE-----";

@Test
public void testHandshakeCompleteHandler()
throws SSLPeerUnverifiedException, CertificateException {
NettyServerRpcConnection conn = mock(NettyServerRpcConnection.class);
SslHandler sslHandler = mock(SslHandler.class);
SocketAddress remoteAddress = new InetSocketAddress("localhost", 5555);
SSLEngine engine = mock(SSLEngine.class);
SSLSession session = mock(SSLSession.class);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate x509Certificate = (X509Certificate) certificateFactory
.generateCertificate(new ByteArrayInputStream(CERTIFICATE.getBytes(StandardCharsets.UTF_8)));
Certificate[] certificates = new Certificate[] { x509Certificate };

when(sslHandler.engine()).thenReturn(engine);
when(engine.getSession()).thenReturn(session);
when(session.getPeerCertificates()).thenReturn(certificates);

NettyRpcServer.sslHandshakeCompleteHandler(conn, sslHandler, remoteAddress);

assertArrayEquals(certificates, conn.clientCertificateChain);
}

}

0 comments on commit fdd8d56

Please sign in to comment.