You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ps...@apache.org on 2022/01/20 14:49:31 UTC

[hbase] branch branch-2.5 updated: HBASE-26689 Backport HBASE-24443 Refactor TestCustomSaslAuthenticationProvider (#4049)

This is an automated email from the ASF dual-hosted git repository.

psomogyi pushed a commit to branch branch-2.5
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-2.5 by this push:
     new 2c82cf3  HBASE-26689 Backport HBASE-24443 Refactor TestCustomSaslAuthenticationProvider (#4049)
2c82cf3 is described below

commit 2c82cf3207231a4549b25904cac982411a3c4a66
Author: Peter Somogyi <ps...@apache.org>
AuthorDate: Thu Jan 20 15:04:31 2022 +0100

    HBASE-26689 Backport HBASE-24443 Refactor TestCustomSaslAuthenticationProvider (#4049)
    
    Duo Zhang <zh...@apache.org>
---
 ... CustomSaslAuthenticationProviderTestBase.java} | 240 +++++++++------------
 ...omSaslAuthenticationProviderNettyRpcServer.java |  43 ++++
 ...mSaslAuthenticationProviderSimpleRpcServer.java |  43 ++++
 3 files changed, 189 insertions(+), 137 deletions(-)

diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProvider.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/CustomSaslAuthenticationProviderTestBase.java
similarity index 73%
rename from hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProvider.java
rename to hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/CustomSaslAuthenticationProviderTestBase.java
index b8c7072..f8ce303 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProvider.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/CustomSaslAuthenticationProviderTestBase.java
@@ -31,7 +31,6 @@ import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
@@ -53,7 +52,6 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
-import org.apache.hadoop.hbase.HBaseClassTestRule;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.LocalHBaseCluster;
@@ -72,10 +70,8 @@ import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
 import org.apache.hadoop.hbase.ipc.BlockingRpcClient;
 import org.apache.hadoop.hbase.ipc.NettyRpcClient;
-import org.apache.hadoop.hbase.ipc.NettyRpcServer;
 import org.apache.hadoop.hbase.ipc.RpcClientFactory;
 import org.apache.hadoop.hbase.ipc.RpcServerFactory;
-import org.apache.hadoop.hbase.ipc.SimpleRpcServer;
 import org.apache.hadoop.hbase.security.AccessDeniedException;
 import org.apache.hadoop.hbase.security.HBaseKerberosUtils;
 import org.apache.hadoop.hbase.security.SaslUtil;
@@ -83,8 +79,6 @@ import org.apache.hadoop.hbase.security.SecurityInfo;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.security.token.SecureTestCluster;
 import org.apache.hadoop.hbase.security.token.TokenProvider;
-import org.apache.hadoop.hbase.testclassification.MediumTests;
-import org.apache.hadoop.hbase.testclassification.SecurityTests;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.CommonFSUtils;
 import org.apache.hadoop.hbase.util.Pair;
@@ -100,13 +94,10 @@ import org.apache.hadoop.security.token.TokenIdentifier;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -116,48 +107,30 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.RPCProtos.UserInformati
 
 /**
  * Tests the pluggable authentication framework with SASL using a contrived authentication system.
- *
- * This tests holds a "user database" in memory as a hashmap. Clients provide their password
- * in the client Hadoop configuration. The servers validate this password via the "user database".
+ * This tests holds a "user database" in memory as a hashmap. Clients provide their password in the
+ * client Hadoop configuration. The servers validate this password via the "user database".
  */
-@RunWith(Parameterized.class)
-@Category({MediumTests.class, SecurityTests.class})
-public class TestCustomSaslAuthenticationProvider {
-  private static final Logger LOG = LoggerFactory.getLogger(
-      TestCustomSaslAuthenticationProvider.class);
+public abstract class CustomSaslAuthenticationProviderTestBase {
 
-  @ClassRule
-  public static final HBaseClassTestRule CLASS_RULE =
-      HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProvider.class);
+  private static final Logger LOG =
+    LoggerFactory.getLogger(CustomSaslAuthenticationProviderTestBase.class);
 
-  private static final Map<String,String> USER_DATABASE = createUserDatabase();
+  private static final Map<String, String> USER_DATABASE = createUserDatabase();
 
   private static final String USER1_PASSWORD = "foobarbaz";
   private static final String USER2_PASSWORD = "bazbarfoo";
 
-  @Parameterized.Parameters(name = "{index}: rpcClientImpl={0}, rpcServerImpl={1}")
+  @Parameters
   public static Collection<Object[]> parameters() {
-    List<Object[]> params = new ArrayList<>();
-    List<String> rpcClientImpls = Arrays.asList(
-        BlockingRpcClient.class.getName(), NettyRpcClient.class.getName());
-    List<String> rpcServerImpls = Arrays.asList(
-        SimpleRpcServer.class.getName(), NettyRpcServer.class.getName());
-    for (String rpcClientImpl : rpcClientImpls) {
-      for (String rpcServerImpl : rpcServerImpls) {
-        params.add(new Object[] { rpcClientImpl, rpcServerImpl });
-      }
-    }
-    return params;
+    return Arrays.asList(new Object[] { BlockingRpcClient.class.getName() },
+      new Object[] { NettyRpcClient.class.getName() });
   }
 
-  @Parameterized.Parameter(0)
+  @Parameter
   public String rpcClientImpl;
 
-  @Parameterized.Parameter(1)
-  public String rpcServerImpl;
-
-  private static Map<String,String> createUserDatabase() {
-    Map<String,String> db = new ConcurrentHashMap<>();
+  private static Map<String, String> createUserDatabase() {
+    Map<String, String> db = new ConcurrentHashMap<>();
     db.put("user1", USER1_PASSWORD);
     db.put("user2", USER2_PASSWORD);
     return db;
@@ -172,14 +145,15 @@ public class TestCustomSaslAuthenticationProvider {
   }
 
   /**
-   * A custom token identifier for our custom auth'n method. Unique from the TokenIdentifier
-   * used for delegation tokens.
+   * A custom token identifier for our custom auth'n method. Unique from the TokenIdentifier used
+   * for delegation tokens.
    */
   public static class PasswordAuthTokenIdentifier extends TokenIdentifier {
     public static final Text PASSWORD_AUTH_TOKEN = new Text("HBASE_PASSWORD_TEST_TOKEN");
     private String username;
 
-    public PasswordAuthTokenIdentifier() {}
+    public PasswordAuthTokenIdentifier() {
+    }
 
     public PasswordAuthTokenIdentifier(String username) {
       this.username = username;
@@ -209,29 +183,29 @@ public class TestCustomSaslAuthenticationProvider {
     }
   }
 
-  public static Token<? extends TokenIdentifier> createPasswordToken(
-      String username, String password, String clusterId) {
+  public static Token<? extends TokenIdentifier> createPasswordToken(String username,
+    String password, String clusterId) {
     PasswordAuthTokenIdentifier id = new PasswordAuthTokenIdentifier(username);
-    Token<? extends TokenIdentifier> token = new Token<>(id.getBytes(), Bytes.toBytes(password),
-        id.getKind(), new Text(clusterId));
+    Token<? extends TokenIdentifier> token =
+      new Token<>(id.getBytes(), Bytes.toBytes(password), id.getKind(), new Text(clusterId));
     return token;
   }
 
   /**
-   * Client provider that finds custom Token in the user's UGI and authenticates with the server
-   * via DIGEST-MD5 using that password.
+   * Client provider that finds custom Token in the user's UGI and authenticates with the server via
+   * DIGEST-MD5 using that password.
    */
   public static class InMemoryClientProvider extends AbstractSaslClientAuthenticationProvider {
     public static final String MECHANISM = "DIGEST-MD5";
-    public static final SaslAuthMethod SASL_AUTH_METHOD = new SaslAuthMethod(
-        "IN_MEMORY", (byte)42, MECHANISM, AuthenticationMethod.TOKEN);
+    public static final SaslAuthMethod SASL_AUTH_METHOD =
+      new SaslAuthMethod("IN_MEMORY", (byte) 42, MECHANISM, AuthenticationMethod.TOKEN);
 
     @Override
     public SaslClient createClient(Configuration conf, InetAddress serverAddr,
-        SecurityInfo securityInfo, Token<? extends TokenIdentifier> token, boolean fallbackAllowed,
-        Map<String, String> saslProps) throws IOException {
+      SecurityInfo securityInfo, Token<? extends TokenIdentifier> token, boolean fallbackAllowed,
+      Map<String, String> saslProps) throws IOException {
       return Sasl.createSaslClient(new String[] { MECHANISM }, null, null,
-          SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryClientProviderCallbackHandler(token));
+        SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryClientProviderCallbackHandler(token));
     }
 
     public Optional<Token<? extends TokenIdentifier>> findToken(User user) {
@@ -253,11 +227,12 @@ public class TestCustomSaslAuthenticationProvider {
     }
 
     /**
-     * Sasl CallbackHandler which extracts information from our custom token and places
-     * it into the Sasl objects.
+     * Sasl CallbackHandler which extracts information from our custom token and places it into the
+     * Sasl objects.
      */
     public class InMemoryClientProviderCallbackHandler implements CallbackHandler {
       private final Token<? extends TokenIdentifier> token;
+
       public InMemoryClientProviderCallbackHandler(Token<? extends TokenIdentifier> token) {
         this.token = token;
       }
@@ -302,21 +277,21 @@ public class TestCustomSaslAuthenticationProvider {
    * Server provider which validates credentials from an in-memory database.
    */
   public static class InMemoryServerProvider extends InMemoryClientProvider
-      implements SaslServerAuthenticationProvider {
+    implements SaslServerAuthenticationProvider {
 
     @Override
-    public AttemptingUserProvidingSaslServer createServer(
-        SecretManager<TokenIdentifier> secretManager,
-        Map<String, String> saslProps) throws IOException {
+    public AttemptingUserProvidingSaslServer
+      createServer(SecretManager<TokenIdentifier> secretManager, Map<String, String> saslProps)
+        throws IOException {
       return new AttemptingUserProvidingSaslServer(
-          Sasl.createSaslServer(getSaslAuthMethod().getSaslMechanism(), null,
-              SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryServerProviderCallbackHandler()),
+        Sasl.createSaslServer(getSaslAuthMethod().getSaslMechanism(), null,
+          SaslUtil.SASL_DEFAULT_REALM, saslProps, new InMemoryServerProviderCallbackHandler()),
         () -> null);
     }
 
     /**
-     * Pulls the correct password for the user who started the SASL handshake so that SASL
-     * can validate that the user provided the right password.
+     * Pulls the correct password for the user who started the SASL handshake so that SASL can
+     * validate that the user provided the right password.
      */
     private class InMemoryServerProviderCallbackHandler implements CallbackHandler {
 
@@ -344,11 +319,11 @@ public class TestCustomSaslAuthenticationProvider {
           try {
             id.readFields(new DataInputStream(new ByteArrayInputStream(encodedId)));
           } catch (IOException e) {
-            throw (InvalidToken) new InvalidToken(
-                "Can't de-serialize tokenIdentifier").initCause(e);
+            throw (InvalidToken) new InvalidToken("Can't de-serialize tokenIdentifier")
+              .initCause(e);
           }
-          char[] actualPassword = SaslUtil.encodePassword(
-              Bytes.toBytes(getPassword(id.getUser().getUserName())));
+          char[] actualPassword =
+            SaslUtil.encodePassword(Bytes.toBytes(getPassword(id.getUser().getUserName())));
           pc.setPassword(actualPassword);
         }
         if (ac != null) {
@@ -373,7 +348,7 @@ public class TestCustomSaslAuthenticationProvider {
 
     @Override
     public UserGroupInformation getAuthorizedUgi(String authzId,
-        SecretManager<TokenIdentifier> secretManager) throws IOException {
+      SecretManager<TokenIdentifier> secretManager) throws IOException {
       UserGroupInformation authorizedUgi;
       byte[] encodedId = SaslUtil.decodeIdentifier(authzId);
       PasswordAuthTokenIdentifier tokenId = new PasswordAuthTokenIdentifier();
@@ -384,8 +359,7 @@ public class TestCustomSaslAuthenticationProvider {
       }
       authorizedUgi = tokenId.getUser();
       if (authorizedUgi == null) {
-        throw new AccessDeniedException(
-            "Can't retrieve username from tokenIdentifier.");
+        throw new AccessDeniedException("Can't retrieve username from tokenIdentifier.");
       }
       authorizedUgi.addTokenIdentifier(tokenId);
       authorizedUgi.setAuthenticationMethod(getSaslAuthMethod().getAuthMethod());
@@ -394,30 +368,28 @@ public class TestCustomSaslAuthenticationProvider {
   }
 
   /**
-   * Custom provider which can select our custom provider, amongst other tokens which
-   * may be available.
+   * Custom provider which can select our custom provider, amongst other tokens which may be
+   * available.
    */
   public static class InMemoryProviderSelector extends BuiltInProviderSelector {
     private InMemoryClientProvider inMemoryProvider;
 
     @Override
     public void configure(Configuration conf,
-        Collection<SaslClientAuthenticationProvider> providers) {
+      Collection<SaslClientAuthenticationProvider> providers) {
       super.configure(conf, providers);
-      Optional<SaslClientAuthenticationProvider> o = providers.stream()
-        .filter((p) -> p instanceof InMemoryClientProvider)
-        .findAny();
+      Optional<SaslClientAuthenticationProvider> o =
+        providers.stream().filter((p) -> p instanceof InMemoryClientProvider).findAny();
 
-      inMemoryProvider = (InMemoryClientProvider) o.orElseThrow(
-        () -> new RuntimeException("InMemoryClientProvider not found in available providers: "
-              + providers));
+      inMemoryProvider = (InMemoryClientProvider) o.orElseThrow(() -> new RuntimeException(
+        "InMemoryClientProvider not found in available providers: " + providers));
     }
 
     @Override
-    public Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>> selectProvider(
-        String clusterId, User user) {
+    public Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>>
+      selectProvider(String clusterId, User user) {
       Pair<SaslClientAuthenticationProvider, Token<? extends TokenIdentifier>> superPair =
-          super.selectProvider(clusterId, user);
+        super.selectProvider(clusterId, user);
 
       Optional<Token<? extends TokenIdentifier>> optional = inMemoryProvider.findToken(user);
       if (optional.isPresent()) {
@@ -430,21 +402,21 @@ public class TestCustomSaslAuthenticationProvider {
     }
   }
 
-  static void createBaseCluster(HBaseTestingUtility util, File keytabFile,
-      MiniKdc kdc) throws Exception {
+  private static void createBaseCluster(HBaseTestingUtility util, File keytabFile, MiniKdc kdc)
+    throws Exception {
     String servicePrincipal = "hbase/localhost";
     String spnegoPrincipal = "HTTP/localhost";
     kdc.createPrincipal(keytabFile, servicePrincipal);
     util.startMiniZKCluster();
 
     HBaseKerberosUtils.setSecuredConfiguration(util.getConfiguration(),
-        servicePrincipal + "@" + kdc.getRealm(), spnegoPrincipal + "@" + kdc.getRealm());
+      servicePrincipal + "@" + kdc.getRealm(), spnegoPrincipal + "@" + kdc.getRealm());
     HBaseKerberosUtils.setSSLConfiguration(util, SecureTestCluster.class);
 
     util.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
-        TokenProvider.class.getName());
+      TokenProvider.class.getName());
     util.startMiniDFSCluster(1);
-    Path rootdir = util.getDataTestDirOnTestFS("TestGenerateDelegationToken");
+    Path rootdir = util.getDataTestDirOnTestFS("TestCustomSaslAuthenticationProvider");
     CommonFSUtils.setRootDir(util.getConfiguration(), rootdir);
   }
 
@@ -453,76 +425,66 @@ public class TestCustomSaslAuthenticationProvider {
   private static LocalHBaseCluster CLUSTER;
   private static File KEYTAB_FILE;
 
-  @BeforeClass
-  public static void setupCluster() throws Exception {
-    KEYTAB_FILE = new File(
-        UTIL.getDataTestDir("keytab").toUri().getPath());
+  protected static void startCluster(String rpcServerImpl) throws Exception {
+    KEYTAB_FILE = new File(UTIL.getDataTestDir("keytab").toUri().getPath());
     final MiniKdc kdc = UTIL.setupMiniKdc(KEYTAB_FILE);
 
     // Adds our test impls instead of creating service loader entries which
     // might inadvertently get them loaded on a real cluster.
     CONF.setStrings(SaslClientAuthenticationProviders.EXTRA_PROVIDERS_KEY,
-        InMemoryClientProvider.class.getName());
+      InMemoryClientProvider.class.getName());
     CONF.setStrings(SaslServerAuthenticationProviders.EXTRA_PROVIDERS_KEY,
-        InMemoryServerProvider.class.getName());
+      InMemoryServerProvider.class.getName());
     CONF.set(SaslClientAuthenticationProviders.SELECTOR_KEY,
-        InMemoryProviderSelector.class.getName());
+      InMemoryProviderSelector.class.getName());
     CONF.setLong(HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN, 600);
     createBaseCluster(UTIL, KEYTAB_FILE, kdc);
-  }
-
-  @Before
-  public void setUpBeforeTest() throws Exception {
-    CONF.unset(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY);
-    CONF.set(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, rpcClientImpl);
     CONF.set(RpcServerFactory.CUSTOM_RPC_SERVER_IMPL_CONF_KEY, rpcServerImpl);
-    if (rpcClientImpl.equals(BlockingRpcClient.class.getName())) {
-      // Set the connection registry to ZKConnectionRegistry since hedging is not supported on
-      // blocking rpc clients.
-      CONF.set(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY,
-          HConstants.ZK_CONNECTION_REGISTRY_CLASS);
-    }
     CLUSTER = new LocalHBaseCluster(CONF, 1);
     CLUSTER.startup();
-    createTable();
   }
 
   @AfterClass
-  public static void teardownCluster() throws Exception {
+  public static void shutdownCluster() throws Exception {
     if (CLUSTER != null) {
       CLUSTER.shutdown();
       CLUSTER = null;
     }
+    UTIL.shutdownMiniDFSCluster();
     UTIL.shutdownMiniZKCluster();
+    UTIL.cleanupTestDir();
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    createTable();
   }
 
   @After
-  public void shutDownCluster() throws IOException {
-    if (CLUSTER != null) {
-      UTIL.deleteTable(name.getTableName());
-      CLUSTER.shutdown();
-    }
+  public void tearDown() throws IOException {
+    UTIL.deleteTable(name.getTableName());
   }
 
   @Rule
   public TableNameTestRule name = new TableNameTestRule();
-  TableName tableName;
-  String clusterId;
 
-  public void createTable() throws Exception {
+  private TableName tableName;
+
+  private String clusterId;
+
+  private void createTable() throws Exception {
     tableName = name.getTableName();
 
     // Create a table and write a record as the service user (hbase)
-    UserGroupInformation serviceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(
-        "hbase/localhost", KEYTAB_FILE.getAbsolutePath());
+    UserGroupInformation serviceUgi = UserGroupInformation
+      .loginUserFromKeytabAndReturnUGI("hbase/localhost", KEYTAB_FILE.getAbsolutePath());
     clusterId = serviceUgi.doAs(new PrivilegedExceptionAction<String>() {
-      @Override public String run() throws Exception {
+      @Override
+      public String run() throws Exception {
         try (Connection conn = ConnectionFactory.createConnection(CONF);
-            Admin admin = conn.getAdmin();) {
-          admin.createTable(TableDescriptorBuilder
-              .newBuilder(tableName)
-              .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1"))
-              .build());
+          Admin admin = conn.getAdmin();) {
+          admin.createTable(TableDescriptorBuilder.newBuilder(tableName)
+            .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1")).build());
 
           UTIL.waitTableAvailable(tableName);
 
@@ -536,21 +498,25 @@ public class TestCustomSaslAuthenticationProvider {
         }
       }
     });
-
     assertNotNull(clusterId);
   }
 
+  private Configuration getClientConf() {
+    Configuration conf = new Configuration(CONF);
+    conf.set(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, rpcClientImpl);
+    return conf;
+  }
+
   @Test
   public void testPositiveAuthentication() throws Exception {
     // Validate that we can read that record back out as the user with our custom auth'n
-    final Configuration clientConf = new Configuration(CONF);
-    UserGroupInformation user1 = UserGroupInformation.createUserForTesting(
-        "user1", new String[0]);
+    UserGroupInformation user1 = UserGroupInformation.createUserForTesting("user1", new String[0]);
     user1.addToken(createPasswordToken("user1", USER1_PASSWORD, clusterId));
     user1.doAs(new PrivilegedExceptionAction<Void>() {
-      @Override public Void run() throws Exception {
-        try (Connection conn = ConnectionFactory.createConnection(clientConf);
-            Table t = conn.getTable(tableName)) {
+      @Override
+      public Void run() throws Exception {
+        try (Connection conn = ConnectionFactory.createConnection(getClientConf());
+          Table t = conn.getTable(tableName)) {
           Result r = t.get(new Get(Bytes.toBytes("r1")));
           assertNotNull(r);
           assertFalse("Should have read a non-empty Result", r.isEmpty());
@@ -563,7 +529,7 @@ public class TestCustomSaslAuthenticationProvider {
     });
   }
 
-  @org.junit.Ignore @Test // See HBASE-24047 and its sub-issue to reenable.
+  @Test
   public void testNegativeAuthentication() throws Exception {
     // Validate that we can read that record back out as the user with our custom auth'n
     final Configuration clientConf = new Configuration(CONF);
@@ -585,15 +551,15 @@ public class TestCustomSaslAuthenticationProvider {
         // since it makes sense only when master registry is in use (which has RPCs to master).
         // That is the reason if you see a slight difference in the test between 3.x and 2.x.
         try (Connection conn = ConnectionFactory.createConnection(clientConf);
-            Table t = conn.getTable(tableName)) {
+          Table t = conn.getTable(tableName)) {
           t.get(new Get(Bytes.toBytes("r1")));
           fail("Should not successfully authenticate with HBase");
         } catch (RetriesExhaustedException re) {
           assertTrue(re.getMessage(), re.getMessage().contains("SaslException"));
         } catch (Exception e) {
           // Any other exception is unexpected.
-          fail("Unexpected exception caught, was expecting a authentication error: "
-              + Throwables.getStackTraceAsString(e));
+          fail("Unexpected exception caught, was expecting a authentication error: " +
+            Throwables.getStackTraceAsString(e));
         }
         return null;
       }
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderNettyRpcServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderNettyRpcServer.java
new file mode 100644
index 0000000..3fd8a51
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderNettyRpcServer.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.security.provider;
+
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.ipc.NettyRpcServer;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.testclassification.SecurityTests;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+@Category({ MediumTests.class, SecurityTests.class })
+public class TestCustomSaslAuthenticationProviderNettyRpcServer
+  extends CustomSaslAuthenticationProviderTestBase {
+
+  @ClassRule
+  public static final HBaseClassTestRule CLASS_RULE =
+    HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProviderNettyRpcServer.class);
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    startCluster(NettyRpcServer.class.getName());
+  }
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderSimpleRpcServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderSimpleRpcServer.java
new file mode 100644
index 0000000..58bca98
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/provider/TestCustomSaslAuthenticationProviderSimpleRpcServer.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.security.provider;
+
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.ipc.SimpleRpcServer;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.testclassification.SecurityTests;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+@Category({ MediumTests.class, SecurityTests.class })
+public class TestCustomSaslAuthenticationProviderSimpleRpcServer
+  extends CustomSaslAuthenticationProviderTestBase {
+
+  @ClassRule
+  public static final HBaseClassTestRule CLASS_RULE =
+    HBaseClassTestRule.forClass(TestCustomSaslAuthenticationProviderSimpleRpcServer.class);
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    startCluster(SimpleRpcServer.class.getName());
+  }
+}