2424import static org .apache .hadoop .hbase .security .HBaseKerberosUtils .loginKerberosPrincipal ;
2525import static org .apache .hadoop .hbase .security .HBaseKerberosUtils .setSecuredConfiguration ;
2626import static org .apache .hadoop .hbase .security .provider .SaslClientAuthenticationProviders .SELECTOR_KEY ;
27+ import static org .hamcrest .MatcherAssert .assertThat ;
28+ import static org .hamcrest .Matchers .either ;
29+ import static org .hamcrest .Matchers .instanceOf ;
2730import static org .junit .Assert .assertEquals ;
2831import static org .junit .Assert .assertNotSame ;
2932import static org .junit .Assert .assertSame ;
3033import static org .junit .Assert .assertThrows ;
3134import static org .junit .Assert .fail ;
3235
36+ import java .io .EOFException ;
3337import java .io .File ;
3438import java .io .IOException ;
3539import java .lang .reflect .Field ;
3640import java .net .InetAddress ;
3741import java .net .InetSocketAddress ;
42+ import java .security .PrivilegedExceptionAction ;
3843import java .util .ArrayList ;
3944import java .util .Collections ;
4045import java .util .Map ;
4449import org .apache .hadoop .conf .Configuration ;
4550import org .apache .hadoop .hbase .HBaseTestingUtil ;
4651import org .apache .hadoop .hbase .HConstants ;
52+ import org .apache .hadoop .hbase .exceptions .ConnectionClosedException ;
53+ import org .apache .hadoop .hbase .ipc .FallbackDisallowedException ;
4754import org .apache .hadoop .hbase .ipc .FifoRpcScheduler ;
4855import org .apache .hadoop .hbase .ipc .RpcClient ;
4956import org .apache .hadoop .hbase .ipc .RpcClientFactory ;
5057import org .apache .hadoop .hbase .ipc .RpcServer ;
5158import org .apache .hadoop .hbase .ipc .RpcServerFactory ;
52- import org .apache .hadoop .hbase .ipc .RpcServerInterface ;
5359import org .apache .hadoop .hbase .security .provider .AuthenticationProviderSelector ;
5460import org .apache .hadoop .hbase .security .provider .BuiltInProviderSelector ;
5561import org .apache .hadoop .hbase .security .provider .SaslAuthMethod ;
@@ -95,6 +101,7 @@ protected static void initKDCAndConf() throws Exception {
95101 // set a smaller timeout and retry to speed up tests
96102 TEST_UTIL .getConfiguration ().setInt (RpcClient .SOCKET_TIMEOUT_READ , 2000 );
97103 TEST_UTIL .getConfiguration ().setInt ("hbase.security.relogin.maxretries" , 1 );
104+ TEST_UTIL .getConfiguration ().setInt ("hbase.security.relogin.maxbackoff" , 100 );
98105 }
99106
100107 protected static void stopKDC () throws InterruptedException {
@@ -237,7 +244,7 @@ public String getTokenKind() {
237244 }
238245
239246 @ Test
240- public void testRpcFallbackToSimpleAuth () throws Exception {
247+ public void testRpcServerFallbackToSimpleAuth () throws Exception {
241248 String clientUsername = "testuser" ;
242249 UserGroupInformation clientUgi =
243250 UserGroupInformation .createUserForTesting (clientUsername , new String [] { clientUsername });
@@ -252,6 +259,59 @@ public void testRpcFallbackToSimpleAuth() throws Exception {
252259 callRpcService (User .create (clientUgi ));
253260 }
254261
262+ @ Test
263+ public void testRpcServerDisallowFallbackToSimpleAuth () throws Exception {
264+ String clientUsername = "testuser" ;
265+ UserGroupInformation clientUgi =
266+ UserGroupInformation .createUserForTesting (clientUsername , new String [] { clientUsername });
267+
268+ // check that the client user is insecure
269+ assertNotSame (ugi , clientUgi );
270+ assertEquals (AuthenticationMethod .SIMPLE , clientUgi .getAuthenticationMethod ());
271+ assertEquals (clientUsername , clientUgi .getUserName ());
272+
273+ clientConf .set (User .HBASE_SECURITY_CONF_KEY , "simple" );
274+ serverConf .setBoolean (RpcServer .FALLBACK_TO_INSECURE_CLIENT_AUTH , false );
275+ IOException error =
276+ assertThrows (IOException .class , () -> callRpcService (User .create (clientUgi )));
277+ // server just closes the connection, so we could get broken pipe, or EOF, or connection closed
278+ if (error .getMessage () == null || !error .getMessage ().contains ("Broken pipe" )) {
279+ assertThat (error ,
280+ either (instanceOf (EOFException .class )).or (instanceOf (ConnectionClosedException .class )));
281+ }
282+ }
283+
284+ @ Test
285+ public void testRpcClientFallbackToSimpleAuth () throws Exception {
286+ String serverUsername = "testuser" ;
287+ UserGroupInformation serverUgi =
288+ UserGroupInformation .createUserForTesting (serverUsername , new String [] { serverUsername });
289+ // check that the server user is insecure
290+ assertNotSame (ugi , serverUgi );
291+ assertEquals (AuthenticationMethod .SIMPLE , serverUgi .getAuthenticationMethod ());
292+ assertEquals (serverUsername , serverUgi .getUserName ());
293+
294+ serverConf .set (User .HBASE_SECURITY_CONF_KEY , "simple" );
295+ clientConf .setBoolean (RpcClient .IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_KEY , true );
296+ callRpcService (User .create (serverUgi ), User .create (ugi ));
297+ }
298+
299+ @ Test
300+ public void testRpcClientDisallowFallbackToSimpleAuth () throws Exception {
301+ String serverUsername = "testuser" ;
302+ UserGroupInformation serverUgi =
303+ UserGroupInformation .createUserForTesting (serverUsername , new String [] { serverUsername });
304+ // check that the server user is insecure
305+ assertNotSame (ugi , serverUgi );
306+ assertEquals (AuthenticationMethod .SIMPLE , serverUgi .getAuthenticationMethod ());
307+ assertEquals (serverUsername , serverUgi .getUserName ());
308+
309+ serverConf .set (User .HBASE_SECURITY_CONF_KEY , "simple" );
310+ clientConf .setBoolean (RpcClient .IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_KEY , false );
311+ assertThrows (FallbackDisallowedException .class ,
312+ () -> callRpcService (User .create (serverUgi ), User .create (ugi )));
313+ }
314+
255315 private void setRpcProtection (String clientProtection , String serverProtection ) {
256316 clientConf .set ("hbase.rpc.protection" , clientProtection );
257317 serverConf .set ("hbase.rpc.protection" , serverProtection );
@@ -263,25 +323,25 @@ private void setRpcProtection(String clientProtection, String serverProtection)
263323 @ Test
264324 public void testSaslWithCommonQop () throws Exception {
265325 setRpcProtection ("privacy,authentication" , "authentication" );
266- callRpcService (User . create ( ugi ) );
326+ callRpcService ();
267327
268328 setRpcProtection ("authentication" , "privacy,authentication" );
269- callRpcService (User . create ( ugi ) );
329+ callRpcService ();
270330
271331 setRpcProtection ("integrity,authentication" , "privacy,authentication" );
272- callRpcService (User . create ( ugi ) );
332+ callRpcService ();
273333
274334 setRpcProtection ("integrity,authentication" , "integrity,authentication" );
275- callRpcService (User . create ( ugi ) );
335+ callRpcService ();
276336
277337 setRpcProtection ("privacy,authentication" , "privacy,authentication" );
278- callRpcService (User . create ( ugi ) );
338+ callRpcService ();
279339 }
280340
281341 @ Test
282342 public void testSaslNoCommonQop () throws Exception {
283343 setRpcProtection ("integrity" , "privacy" );
284- SaslException se = assertThrows (SaslException .class , () -> callRpcService (User . create ( ugi ) ));
344+ SaslException se = assertThrows (SaslException .class , () -> callRpcService ());
285345 assertEquals ("No common protection layer between client and server" , se .getMessage ());
286346 }
287347
@@ -292,7 +352,7 @@ public void testSaslNoCommonQop() throws Exception {
292352 public void testSaslWithCryptoAES () throws Exception {
293353 setRpcProtection ("privacy" , "privacy" );
294354 setCryptoAES ("true" , "true" );
295- callRpcService (User . create ( ugi ) );
355+ callRpcService ();
296356 }
297357
298358 /**
@@ -303,11 +363,11 @@ public void testDifferentConfWithCryptoAES() throws Exception {
303363 setRpcProtection ("privacy" , "privacy" );
304364
305365 setCryptoAES ("false" , "true" );
306- callRpcService (User . create ( ugi ) );
366+ callRpcService ();
307367
308368 setCryptoAES ("true" , "false" );
309369 try {
310- callRpcService (User . create ( ugi ) );
370+ callRpcService ();
311371 fail ("The exception should be thrown out for the rpc timeout." );
312372 } catch (Exception e ) {
313373 // ignore the expected exception
@@ -323,18 +383,20 @@ private void setCryptoAES(String clientCryptoAES, String serverCryptoAES) {
323383 * Sets up a RPC Server and a Client. Does a RPC checks the result. If an exception is thrown from
324384 * the stub, this function will throw root cause of that exception.
325385 */
326- private void callRpcService (User clientUser ) throws Exception {
386+ private void callRpcService (User serverUser , User clientUser ) throws Exception {
327387 SecurityInfo securityInfoMock = Mockito .mock (SecurityInfo .class );
328388 Mockito .when (securityInfoMock .getServerPrincipal ())
329389 .thenReturn (HBaseKerberosUtils .KRB_PRINCIPAL );
330390 SecurityInfo .addInfo ("TestProtobufRpcProto" , securityInfoMock );
331391
332392 InetSocketAddress isa = new InetSocketAddress (HOST , 0 );
333393
334- RpcServerInterface rpcServer = RpcServerFactory .createRpcServer (null , "AbstractTestSecureIPC" ,
335- Lists
336- .newArrayList (new RpcServer .BlockingServiceAndInterface ((BlockingService ) SERVICE , null )),
337- isa , serverConf , new FifoRpcScheduler (serverConf , 1 ));
394+ RpcServer rpcServer = serverUser .getUGI ()
395+ .doAs ((PrivilegedExceptionAction <
396+ RpcServer >) () -> RpcServerFactory .createRpcServer (null , "AbstractTestSecureIPC" ,
397+ Lists .newArrayList (
398+ new RpcServer .BlockingServiceAndInterface ((BlockingService ) SERVICE , null )),
399+ isa , serverConf , new FifoRpcScheduler (serverConf , 1 )));
338400 rpcServer .start ();
339401 try (RpcClient rpcClient =
340402 RpcClientFactory .createClient (clientConf , HConstants .DEFAULT_CLUSTER_ID .toString ())) {
@@ -364,6 +426,14 @@ public void uncaughtException(Thread th, Throwable ex) {
364426 }
365427 }
366428
429+ private void callRpcService (User clientUser ) throws Exception {
430+ callRpcService (User .create (ugi ), clientUser );
431+ }
432+
433+ private void callRpcService () throws Exception {
434+ callRpcService (User .create (ugi ));
435+ }
436+
367437 public static class TestThread extends Thread {
368438 private final BlockingInterface stub ;
369439
0 commit comments