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