001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.ipc; 019 020import static org.junit.Assert.assertArrayEquals; 021import static org.junit.Assert.assertNotNull; 022import static org.junit.Assert.assertTrue; 023import static org.mockito.Mockito.mock; 024import static org.mockito.Mockito.when; 025 026import java.io.ByteArrayInputStream; 027import java.net.InetSocketAddress; 028import java.net.SocketAddress; 029import java.nio.charset.StandardCharsets; 030import java.security.cert.Certificate; 031import java.security.cert.CertificateException; 032import java.security.cert.CertificateFactory; 033import java.security.cert.X509Certificate; 034import java.util.Arrays; 035import java.util.Collection; 036import javax.net.ssl.SSLEngine; 037import javax.net.ssl.SSLPeerUnverifiedException; 038import javax.net.ssl.SSLSession; 039import org.apache.hadoop.hbase.HBaseClassTestRule; 040import org.apache.hadoop.hbase.HBaseTestingUtil; 041import org.apache.hadoop.hbase.TableName; 042import org.apache.hadoop.hbase.TableNameTestRule; 043import org.apache.hadoop.hbase.client.Get; 044import org.apache.hadoop.hbase.client.Put; 045import org.apache.hadoop.hbase.client.Result; 046import org.apache.hadoop.hbase.client.Table; 047import org.apache.hadoop.hbase.client.TableDescriptor; 048import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 049import org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy; 050import org.apache.hadoop.hbase.testclassification.MediumTests; 051import org.apache.hadoop.hbase.testclassification.RPCTests; 052import org.apache.hadoop.hbase.util.Bytes; 053import org.apache.hadoop.hbase.util.LoadTestKVGenerator; 054import org.junit.After; 055import org.junit.Before; 056import org.junit.ClassRule; 057import org.junit.Rule; 058import org.junit.Test; 059import org.junit.experimental.categories.Category; 060import org.junit.runner.RunWith; 061import org.junit.runners.Parameterized; 062import org.junit.runners.Parameterized.Parameters; 063 064import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslHandler; 065 066@Category({ RPCTests.class, MediumTests.class }) 067@RunWith(Parameterized.class) 068public class TestNettyRpcServer { 069 070 @ClassRule 071 public static final HBaseClassTestRule CLASS_RULE = 072 HBaseClassTestRule.forClass(TestNettyRpcServer.class); 073 074 private static final byte[] FAMILY = Bytes.toBytes("f"); 075 private static final byte[] QUALIFIER = Bytes.toBytes("q"); 076 private static final int NUM_ROWS = 100; 077 private static final int MIN_LEN = 1000; 078 private static final int MAX_LEN = 1000000; 079 protected static final LoadTestKVGenerator GENERATOR = new LoadTestKVGenerator(MIN_LEN, MAX_LEN); 080 protected static HBaseTestingUtil TEST_UTIL; 081 082 @Rule 083 public TableNameTestRule name = new TableNameTestRule(); 084 085 @Parameterized.Parameter 086 public String allocatorType; 087 088 @Parameters 089 public static Collection<Object[]> parameters() { 090 return Arrays.asList(new Object[][] { { NettyRpcServer.POOLED_ALLOCATOR_TYPE }, 091 { NettyRpcServer.UNPOOLED_ALLOCATOR_TYPE }, { NettyRpcServer.HEAP_ALLOCATOR_TYPE }, 092 { SimpleByteBufAllocator.class.getName() } }); 093 } 094 095 @Before 096 public void setup() throws Exception { 097 // A subclass may have already created TEST_UTIL and is now upcalling to us 098 if (TEST_UTIL == null) { 099 TEST_UTIL = new HBaseTestingUtil(); 100 } 101 TEST_UTIL.getConfiguration().set(RpcServerFactory.CUSTOM_RPC_SERVER_IMPL_CONF_KEY, 102 NettyRpcServer.class.getName()); 103 TEST_UTIL.getConfiguration().set(NettyRpcServer.HBASE_NETTY_ALLOCATOR_KEY, allocatorType); 104 TEST_UTIL.startMiniCluster(); 105 } 106 107 @After 108 public void tearDown() throws Exception { 109 TEST_UTIL.shutdownMiniCluster(); 110 } 111 112 @Test 113 public void testNettyRpcServer() throws Exception { 114 doTest(name.getTableName()); 115 } 116 117 protected void doTest(TableName tableName) throws Exception { 118 // Splitting just complicates the test scenario, disable it 119 final TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName) 120 .setRegionSplitPolicyClassName(DisabledRegionSplitPolicy.class.getName()).build(); 121 try (Table table = 122 TEST_UTIL.createTable(desc, new byte[][] { FAMILY }, TEST_UTIL.getConfiguration())) { 123 // put some test data 124 for (int i = 0; i < NUM_ROWS; i++) { 125 final byte[] rowKey = Bytes.toBytes(LoadTestKVGenerator.md5PrefixedKey(i)); 126 final byte[] v = GENERATOR.generateRandomSizeValue(rowKey, QUALIFIER); 127 table.put(new Put(rowKey).addColumn(FAMILY, QUALIFIER, v)); 128 } 129 // read to verify it. 130 for (int i = 0; i < NUM_ROWS; i++) { 131 final byte[] rowKey = Bytes.toBytes(LoadTestKVGenerator.md5PrefixedKey(i)); 132 final Result r = table.get(new Get(rowKey).addColumn(FAMILY, QUALIFIER)); 133 assertNotNull("Result was empty", r); 134 final byte[] v = r.getValue(FAMILY, QUALIFIER); 135 assertNotNull("Result did not contain expected value", v); 136 assertTrue("Value was not verified", LoadTestKVGenerator.verify(v, rowKey, QUALIFIER)); 137 } 138 } 139 } 140 141 private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 142 + "MIIEITCCAwmgAwIBAgIUaLL8vLOhWLCLXVHEJqXJhfmsTB8wDQYJKoZIhvcNAQEL\n" 143 + "BQAwgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYD\n" 144 + "VQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRlc3QgY2FzZTEYMBYGA1UE\n" 145 + "CwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0eSB0ZXN0IGNhc2UxIzAh\n" 146 + "BgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29tMB4XDTI0MDEyMTE5MzMy\n" 147 + "MFoXDTI1MDEyMDE5MzMyMFowgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNz\n" 148 + "YWNodXNldHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRl\n" 149 + "c3QgY2FzZTEYMBYGA1UECwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0\n" 150 + "eSB0ZXN0IGNhc2UxIzAhBgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29t\n" 151 + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+qzEZpQMjVdLj0siUcG\n" 152 + "y8LIHOW4S+tgHIKFkF865qWq6FVGbROe2Z0f5W6yIamZkdxzptT0iv+8S5okNNeW\n" 153 + "2NbsN/HNJIRtWfxku1Jh1gBqSkAYIjXyq7+20hIaJTzzxqike9M/Lc14EGb33Ja/\n" 154 + "kDPRV3UtiM3Ntf3eALXKbrWptkbgQngCaTgtfg8IkMAEpP270wZ9fW0lDHv3NPPt\n" 155 + "Zt0QSJzWSqWfu+l4ayvcUQYyNJesx9YmTHSJu69lvT4QApoX8FEiHfNCJ28R50CS\n" 156 + "aIgOpCWUvkH7rqx0p9q393uJRS/S6RlLbU30xUN1fNrVmP/XAapfy+R0PSgiUi8o\n" 157 + "EQIDAQABozkwNzAWBgNVHRIEDzANggt3d3cuZm9vLmNvbTAdBgNVHQ4EFgQUl4FD\n" 158 + "Y8jJ/JHJR68YqPsGUjUJuwgwDQYJKoZIhvcNAQELBQADggEBADVzivYz2M0qsWUc\n" 159 + "jXjCHymwTIr+7ud10um53FbYEAfKWsIY8Pp35fKpFzUwc5wVdCnLU86K/YMKRzNB\n" 160 + "zL2Auow3PJFRvXecOv7dWxNlNneLDcwbVrdNRu6nQXmZUgyz0oUKuJbF+JGtI+7W\n" 161 + "kRw7yhBfki+UCSQWeDqvaWzgmA4Us0N8NFq3euAs4xFbMMPMQWrT9Z7DGchCeRiB\n" 162 + "dkQBvh88vbR3v2Saq14W4Wt5rj2++vXWGQSeAQL6nGbOwc3ohW6isNNV0eGQQTmS\n" 163 + "khS2d/JDZq2XL5RGexf3CA6YYzWiTr9YZHNjuobvLH7mVnA2c8n6Zty/UhfnuK1x\n" + "JbkleFk=\n" 164 + "-----END CERTIFICATE-----"; 165 166 @Test 167 public void testHandshakeCompleteHandler() 168 throws SSLPeerUnverifiedException, CertificateException { 169 NettyServerRpcConnection conn = mock(NettyServerRpcConnection.class); 170 SslHandler sslHandler = mock(SslHandler.class); 171 SocketAddress remoteAddress = new InetSocketAddress("localhost", 5555); 172 SSLEngine engine = mock(SSLEngine.class); 173 SSLSession session = mock(SSLSession.class); 174 CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); 175 X509Certificate x509Certificate = (X509Certificate) certificateFactory 176 .generateCertificate(new ByteArrayInputStream(CERTIFICATE.getBytes(StandardCharsets.UTF_8))); 177 Certificate[] certificates = new Certificate[] { x509Certificate }; 178 179 when(sslHandler.engine()).thenReturn(engine); 180 when(engine.getSession()).thenReturn(session); 181 when(session.getPeerCertificates()).thenReturn(certificates); 182 183 NettyRpcServer.sslHandshakeCompleteHandler(conn, sslHandler, remoteAddress); 184 185 assertArrayEquals(certificates, conn.clientCertificateChain); 186 } 187 188}