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.apache.hadoop.hbase.ipc.TestProtobufRpcServiceImpl.SERVICE; 021import static org.apache.hadoop.hbase.ipc.TestProtobufRpcServiceImpl.newBlockingStub; 022import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getKeytabFileForTesting; 023import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getPrincipalForTesting; 024import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.loginKerberosPrincipal; 025import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.setSecuredConfiguration; 026import static org.junit.Assert.assertFalse; 027import static org.junit.Assert.assertTrue; 028 029import java.io.File; 030import java.net.InetSocketAddress; 031import java.util.Collections; 032import java.util.concurrent.atomic.AtomicReference; 033import org.apache.hadoop.conf.Configuration; 034import org.apache.hadoop.hbase.HBaseClassTestRule; 035import org.apache.hadoop.hbase.HBaseTestingUtil; 036import org.apache.hadoop.hbase.HConstants; 037import org.apache.hadoop.hbase.security.HBaseKerberosUtils; 038import org.apache.hadoop.hbase.security.SecurityInfo; 039import org.apache.hadoop.hbase.security.User; 040import org.apache.hadoop.hbase.testclassification.MediumTests; 041import org.apache.hadoop.hbase.testclassification.RPCTests; 042import org.apache.hadoop.minikdc.MiniKdc; 043import org.apache.hadoop.security.UserGroupInformation; 044import org.junit.AfterClass; 045import org.junit.Before; 046import org.junit.BeforeClass; 047import org.junit.ClassRule; 048import org.junit.Test; 049import org.junit.experimental.categories.Category; 050import org.mockito.Mockito; 051 052import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 053import org.apache.hbase.thirdparty.io.netty.channel.Channel; 054 055import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProtos; 056import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface; 057 058@Category({ RPCTests.class, MediumTests.class }) 059public class TestRpcSkipInitialSaslHandshake { 060 061 @ClassRule 062 public static final HBaseClassTestRule CLASS_RULE = 063 HBaseClassTestRule.forClass(TestRpcSkipInitialSaslHandshake.class); 064 065 protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 066 067 protected static final File KEYTAB_FILE = 068 new File(TEST_UTIL.getDataTestDir("keytab").toUri().getPath()); 069 070 protected static MiniKdc KDC; 071 protected static String HOST = "localhost"; 072 protected static String PRINCIPAL; 073 074 protected String krbKeytab; 075 protected String krbPrincipal; 076 protected UserGroupInformation ugi; 077 protected Configuration clientConf; 078 protected Configuration serverConf; 079 080 protected static void initKDCAndConf() throws Exception { 081 KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE); 082 PRINCIPAL = "hbase/" + HOST; 083 KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL); 084 HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm()); 085 // set a smaller timeout and retry to speed up tests 086 TEST_UTIL.getConfiguration().setInt(RpcClient.SOCKET_TIMEOUT_READ, 2000000000); 087 TEST_UTIL.getConfiguration().setInt("hbase.security.relogin.maxretries", 1); 088 } 089 090 protected static void stopKDC() throws InterruptedException { 091 if (KDC != null) { 092 KDC.stop(); 093 } 094 } 095 096 protected final void setUpPrincipalAndConf() throws Exception { 097 krbKeytab = getKeytabFileForTesting(); 098 krbPrincipal = getPrincipalForTesting(); 099 ugi = loginKerberosPrincipal(krbKeytab, krbPrincipal); 100 clientConf = new Configuration(TEST_UTIL.getConfiguration()); 101 setSecuredConfiguration(clientConf); 102 clientConf.setBoolean(RpcClient.IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_KEY, true); 103 serverConf = new Configuration(TEST_UTIL.getConfiguration()); 104 } 105 106 @BeforeClass 107 public static void setUp() throws Exception { 108 initKDCAndConf(); 109 } 110 111 @AfterClass 112 public static void tearDown() throws Exception { 113 stopKDC(); 114 TEST_UTIL.cleanupTestDir(); 115 } 116 117 @Before 118 public void setUpTest() throws Exception { 119 setUpPrincipalAndConf(); 120 } 121 122 /** 123 * This test is for HBASE-27923,which NettyRpcServer may hange if it should skip initial sasl 124 * handshake. 125 */ 126 @Test 127 public void test() throws Exception { 128 SecurityInfo securityInfoMock = Mockito.mock(SecurityInfo.class); 129 Mockito.when(securityInfoMock.getServerPrincipals()) 130 .thenReturn(Collections.singletonList(HBaseKerberosUtils.KRB_PRINCIPAL)); 131 SecurityInfo.addInfo("TestProtobufRpcProto", securityInfoMock); 132 133 final AtomicReference<NettyServerRpcConnection> conn = new AtomicReference<>(null); 134 NettyRpcServer rpcServer = new NettyRpcServer(null, getClass().getSimpleName(), 135 Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(SERVICE, null)), 136 new InetSocketAddress(HOST, 0), serverConf, new FifoRpcScheduler(serverConf, 1), true) { 137 138 @Override 139 protected NettyServerRpcConnection createNettyServerRpcConnection(Channel channel) { 140 conn.set(super.createNettyServerRpcConnection(channel)); 141 return conn.get(); 142 } 143 }; 144 145 rpcServer.start(); 146 try (NettyRpcClient rpcClient = 147 new NettyRpcClient(clientConf, HConstants.DEFAULT_CLUSTER_ID.toString(), null, null)) { 148 BlockingInterface stub = newBlockingStub(rpcClient, rpcServer.getListenerAddress(), 149 User.create(UserGroupInformation.getCurrentUser())); 150 151 String response = 152 stub.echo(null, TestProtos.EchoRequestProto.newBuilder().setMessage("test").build()) 153 .getMessage(); 154 assertTrue("test".equals(response)); 155 assertFalse(conn.get().useSasl); 156 } finally { 157 rpcServer.stop(); 158 } 159 } 160}