You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zg...@apache.org on 2019/03/19 07:09:07 UTC

[hbase] branch branch-2 updated: HBASE-22015 UserPermission should be annotated as InterfaceAudience.Public

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

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


The following commit(s) were added to refs/heads/branch-2 by this push:
     new 3317f03  HBASE-22015 UserPermission should be annotated as InterfaceAudience.Public
3317f03 is described below

commit 3317f03d417493524e0d57fe515a2d0c8da61f59
Author: meiyi <my...@gamil.com>
AuthorDate: Mon Mar 18 11:43:07 2019 +0800

    HBASE-22015 UserPermission should be annotated as InterfaceAudience.Public
    
    Signed-off-by: Guanghao Zhang <zg...@apache.org>
---
 .../java/org/apache/hadoop/hbase/client/Admin.java |  13 +-
 .../org/apache/hadoop/hbase/client/AsyncAdmin.java |  13 +-
 .../hadoop/hbase/client/AsyncHBaseAdmin.java       |  10 +-
 .../org/apache/hadoop/hbase/client/HBaseAdmin.java |  12 +-
 .../hadoop/hbase/client/RawAsyncHBaseAdmin.java    |  20 ++-
 .../hbase/security/access/AccessControlClient.java |  20 +--
 .../hbase/security/access/AccessControlUtil.java   |  47 ++++----
 .../hbase/security/access/GlobalPermission.java    |  17 +--
 .../hbase/security/access/NamespacePermission.java |  21 +---
 .../hadoop/hbase/security/access/Permission.java   |  32 ++++-
 .../security/access/ShadedAccessControlUtil.java   |  31 +++--
 .../hbase/security/access/TablePermission.java     |  67 +----------
 .../hbase/security/access/UserPermission.java      |  85 +------------
 .../hbase/security/access/AccessControlLists.java  |   9 +-
 .../hbase/security/access/AccessController.java    |  21 ++--
 .../hbase/snapshot/RestoreSnapshotHelper.java      |   6 +-
 .../hbase/security/access/SecureTestUtil.java      |  45 ++++---
 .../security/access/TestAccessController.java      |  49 ++++----
 .../security/access/TestNamespaceCommands.java     |  18 +--
 .../security/access/TestPermissionBuilder.java     |  11 +-
 .../security/access/TestTablePermissions.java      | 134 +++++++++++++--------
 .../access/TestWithDisabledAuthorization.java      |  24 ++--
 .../security/access/TestZKPermissionWatcher.java   |   7 +-
 .../hadoop/hbase/thrift2/client/ThriftAdmin.java   |   6 +-
 24 files changed, 304 insertions(+), 414 deletions(-)

diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
index 36a555e..5553093 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
@@ -56,7 +56,7 @@ import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
 import org.apache.hadoop.hbase.replication.ReplicationException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
@@ -2905,21 +2905,18 @@ public interface Admin extends Abortable, Closeable {
 
   /**
    * Grants user specific permissions
-   * @param userName user name
-   * @param permission the specific permission
+   * @param userPermission user name and the specific permission
    * @param mergeExistingPermissions If set to false, later granted permissions will override
    *          previous granted permissions. otherwise, it'll merge with previous granted
    *          permissions.
    * @throws IOException if a remote or network exception occurs
    */
-  void grant(String userName, Permission permission, boolean mergeExistingPermissions)
-      throws IOException;
+  void grant(UserPermission userPermission, boolean mergeExistingPermissions) throws IOException;
 
   /**
    * Revokes user specific permissions
-   * @param userName user name
-   * @param permission the specific permission
+   * @param userPermission user name and the specific permission
    * @throws IOException if a remote or network exception occurs
    */
-  void revoke(String userName, Permission permission) throws IOException;
+  void revoke(UserPermission userPermission) throws IOException;
 }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
index 54450bf..2df18fe 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
@@ -42,7 +42,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.yetus.audience.InterfaceAudience;
 
 /**
@@ -1395,19 +1395,16 @@ public interface AsyncAdmin {
 
   /**
    * Grants user specific permissions
-   * @param userName user name
-   * @param permission the specific permission
+   * @param userPermission user name and the specific permission
    * @param mergeExistingPermissions If set to false, later granted permissions will override
    *          previous granted permissions. otherwise, it'll merge with previous granted
    *          permissions.
    */
-  CompletableFuture<Void> grant(String userName, Permission permission,
-      boolean mergeExistingPermissions);
+  CompletableFuture<Void> grant(UserPermission userPermission, boolean mergeExistingPermissions);
 
   /**
    * Revokes user specific permissions
-   * @param userName user name
-   * @param permission the specific permission
+   * @param userPermission user name and the specific permission
    */
-  CompletableFuture<Void> revoke(String userName, Permission permission);
+  CompletableFuture<Void> revoke(UserPermission userPermission);
 }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
index d0c4f56..e62f3bb 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
@@ -41,7 +41,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.hadoop.hbase.util.FutureUtils;
 import org.apache.yetus.audience.InterfaceAudience;
 
@@ -791,13 +791,13 @@ class AsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
-  public CompletableFuture<Void> grant(String userName, Permission permission,
+  public CompletableFuture<Void> grant(UserPermission userPermission,
       boolean mergeExistingPermissions) {
-    return wrap(rawAdmin.grant(userName, permission, mergeExistingPermissions));
+    return wrap(rawAdmin.grant(userPermission, mergeExistingPermissions));
   }
 
   @Override
-  public CompletableFuture<Void> revoke(String userName, Permission permission) {
-    return wrap(rawAdmin.revoke(userName, permission));
+  public CompletableFuture<Void> revoke(UserPermission userPermission) {
+    return wrap(rawAdmin.revoke(userPermission));
   }
 }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
index f04af84..e75b869 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
@@ -87,7 +87,6 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
 import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil;
 import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
@@ -4233,13 +4232,13 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
-  public void grant(String userName, Permission permission, boolean mergeExistingPermissions)
+  public void grant(UserPermission userPermission, boolean mergeExistingPermissions)
       throws IOException {
     executeCallable(new MasterCallable<Void>(getConnection(), getRpcControllerFactory()) {
       @Override
       protected Void rpcCall() throws Exception {
-        GrantRequest req = ShadedAccessControlUtil
-            .buildGrantRequest(new UserPermission(userName, permission), mergeExistingPermissions);
+        GrantRequest req =
+            ShadedAccessControlUtil.buildGrantRequest(userPermission, mergeExistingPermissions);
         this.master.grant(getRpcController(), req);
         return null;
       }
@@ -4247,12 +4246,11 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
-  public void revoke(String userName, Permission permission) throws IOException {
+  public void revoke(UserPermission userPermission) throws IOException {
     executeCallable(new MasterCallable<Void>(getConnection(), getRpcControllerFactory()) {
       @Override
       protected Void rpcCall() throws Exception {
-        RevokeRequest req =
-            ShadedAccessControlUtil.buildRevokeRequest(new UserPermission(userName, permission));
+        RevokeRequest req = ShadedAccessControlUtil.buildRevokeRequest(userPermission);
         this.master.revoke(getRpcController(), req);
         return null;
       }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
index 7df20a8..0eba0fd 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
@@ -84,7 +84,6 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
 import org.apache.hadoop.hbase.replication.ReplicationException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
 import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil;
 import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
@@ -3743,24 +3742,21 @@ class RawAsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
-  public CompletableFuture<Void> grant(String userName, Permission permission,
+  public CompletableFuture<Void> grant(UserPermission userPermission,
       boolean mergeExistingPermissions) {
     return this.<Void> newMasterCaller()
-        .action(
-          (controller, stub) -> this.<GrantRequest, GrantResponse, Void> call(controller, stub,
-            ShadedAccessControlUtil.buildGrantRequest(new UserPermission(userName, permission),
-              mergeExistingPermissions),
-            (s, c, req, done) -> s.grant(c, req, done), resp -> null))
+        .action((controller, stub) -> this.<GrantRequest, GrantResponse, Void> call(controller,
+          stub, ShadedAccessControlUtil.buildGrantRequest(userPermission, mergeExistingPermissions),
+          (s, c, req, done) -> s.grant(c, req, done), resp -> null))
         .call();
   }
 
   @Override
-  public CompletableFuture<Void> revoke(String userName, Permission permission) {
+  public CompletableFuture<Void> revoke(UserPermission userPermission) {
     return this.<Void> newMasterCaller()
-        .action(
-          (controller, stub) -> this.<RevokeRequest, RevokeResponse, Void> call(controller, stub,
-            ShadedAccessControlUtil.buildRevokeRequest(new UserPermission(userName, permission)),
-            (s, c, req, done) -> s.revoke(c, req, done), resp -> null))
+        .action((controller, stub) -> this.<RevokeRequest, RevokeResponse, Void> call(controller,
+          stub, ShadedAccessControlUtil.buildRevokeRequest(userPermission),
+          (s, c, req, done) -> s.revoke(c, req, done), resp -> null))
         .call();
   }
 }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java
index 05876f0..91e4382 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java
@@ -93,7 +93,8 @@ public class AccessControlClient {
   private static void grant(Connection connection, final TableName tableName,
       final String userName, final byte[] family, final byte[] qual, boolean mergeExistingPermissions,
       final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().grant(userName, new TablePermission(tableName, family, qual, actions),
+    connection.getAdmin().grant(new UserPermission(userName, Permission.newBuilder(tableName)
+        .withFamily(family).withQualifier(qual).withActions(actions).build()),
       mergeExistingPermissions);
   }
 
@@ -126,7 +127,8 @@ public class AccessControlClient {
    */
   private static void grant(Connection connection, final String namespace, final String userName,
       boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().grant(userName, new NamespacePermission(namespace, actions),
+    connection.getAdmin().grant(
+      new UserPermission(userName, Permission.newBuilder(namespace).withActions(actions).build()),
       mergeExistingPermissions);
   }
 
@@ -157,7 +159,9 @@ public class AccessControlClient {
    */
   private static void grant(Connection connection, final String userName,
       boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().grant(userName, new GlobalPermission(actions), mergeExistingPermissions);
+    connection.getAdmin().grant(
+      new UserPermission(userName, Permission.newBuilder().withActions(actions).build()),
+      mergeExistingPermissions);
   }
 
   /**
@@ -194,8 +198,8 @@ public class AccessControlClient {
   public static void revoke(Connection connection, final TableName tableName,
       final String username, final byte[] family, final byte[] qualifier,
       final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().revoke(username,
-      new TablePermission(tableName, family, qualifier, actions));
+    connection.getAdmin().revoke(new UserPermission(username, Permission.newBuilder(tableName)
+        .withFamily(family).withQualifier(qualifier).withActions(actions).build()));
   }
 
   /**
@@ -208,7 +212,8 @@ public class AccessControlClient {
    */
   public static void revoke(Connection connection, final String namespace,
       final String userName, final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().revoke(userName, new NamespacePermission(namespace, actions));
+    connection.getAdmin().revoke(
+      new UserPermission(userName, Permission.newBuilder(namespace).withActions(actions).build()));
   }
 
   /**
@@ -217,7 +222,8 @@ public class AccessControlClient {
    */
   public static void revoke(Connection connection, final String userName,
       final Permission.Action... actions) throws Throwable {
-    connection.getAdmin().revoke(userName, new GlobalPermission(actions));
+    connection.getAdmin()
+        .revoke(new UserPermission(userName, Permission.newBuilder().withActions(actions).build()));
   }
 
   /**
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java
index 216b332..05f173e 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java
@@ -247,7 +247,7 @@ public class AccessControlUtil {
    * @return the converted TablePermission
    */
   public static TablePermission toTablePermission(AccessControlProtos.TablePermission proto) {
-    List<Permission.Action> actions = toPermissionActions(proto.getActionList());
+    Permission.Action[] actions = toPermissionActions(proto.getActionList());
     TableName table = null;
     byte[] qualifier = null;
     byte[] family = null;
@@ -261,8 +261,7 @@ public class AccessControlUtil {
     if (proto.hasQualifier()) {
       qualifier = proto.getQualifier().toByteArray();
     }
-    return new TablePermission(table, family, qualifier,
-        actions.toArray(new Permission.Action[actions.size()]));
+    return new TablePermission(table, family, qualifier, actions);
   }
 
   /**
@@ -273,21 +272,21 @@ public class AccessControlUtil {
   public static Permission toPermission(AccessControlProtos.Permission proto) {
     if (proto.getType() == AccessControlProtos.Permission.Type.Global) {
       AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission();
-      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
-      return new GlobalPermission(actions.toArray(new Permission.Action[actions.size()]));
+      Permission.Action[] actions = toPermissionActions(perm.getActionList());
+      return Permission.newBuilder().withActions(actions).build();
     }
     if (proto.getType() == AccessControlProtos.Permission.Type.Namespace) {
       AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission();
-      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+      Permission.Action[] actions = toPermissionActions(perm.getActionList());
       if (!proto.hasNamespacePermission()) {
         throw new IllegalStateException("Namespace must not be empty in NamespacePermission");
       }
-      return new NamespacePermission(perm.getNamespaceName().toStringUtf8(),
-        actions.toArray(new Permission.Action[actions.size()]));
+      return Permission.newBuilder(perm.getNamespaceName().toStringUtf8()).withActions(actions)
+          .build();
     }
     if (proto.getType() == AccessControlProtos.Permission.Type.Table) {
       AccessControlProtos.TablePermission perm = proto.getTablePermission();
-      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+      Permission.Action[] actions = toPermissionActions(perm.getActionList());
       byte[] qualifier = null;
       byte[] family = null;
       TableName table = null;
@@ -301,8 +300,8 @@ public class AccessControlUtil {
       if (perm.hasQualifier()) {
         qualifier = perm.getQualifier().toByteArray();
       }
-      return new TablePermission(table, family, qualifier,
-        actions.toArray(new Permission.Action[actions.size()]));
+      return Permission.newBuilder(table).withFamily(family).withQualifier(qualifier)
+          .withActions(actions).build();
     }
     throw new IllegalStateException("Unrecognize Perm Type: " + proto.getType());
   }
@@ -364,16 +363,16 @@ public class AccessControlUtil {
   }
 
   /**
-   * Converts a list of Permission.Action proto to a list of client Permission.Action objects.
+   * Converts a list of Permission.Action proto to an array of client Permission.Action objects.
    *
    * @param protoActions the list of protobuf Actions
-   * @return the converted list of Actions
+   * @return the converted array of Actions
    */
-  public static List<Permission.Action> toPermissionActions(
-      List<AccessControlProtos.Permission.Action> protoActions) {
-    List<Permission.Action> actions = new ArrayList<>(protoActions.size());
-    for (AccessControlProtos.Permission.Action a : protoActions) {
-      actions.add(toPermissionAction(a));
+  public static Permission.Action[]
+      toPermissionActions(List<AccessControlProtos.Permission.Action> protoActions) {
+    Permission.Action[] actions = new Permission.Action[protoActions.size()];
+    for (int i = 0; i < protoActions.size(); i++) {
+      actions[i] = toPermissionAction(protoActions.get(i));
     }
     return actions;
   }
@@ -491,7 +490,7 @@ public class AccessControlUtil {
    * @param userShortName the short name of the user to grant permissions
    * @param actions the permissions to be granted
    * @throws ServiceException
-   * @deprecated Use {@link Admin#grant(String, Permission, boolean)} instead.
+   * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead.
    */
   @Deprecated
   public static void grant(RpcController controller,
@@ -520,7 +519,7 @@ public class AccessControlUtil {
    * @param q optional qualifier
    * @param actions the permissions to be granted
    * @throws ServiceException
-   * @deprecated Use {@link Admin#grant(String, Permission, boolean)} instead.
+   * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead.
    */
   @Deprecated
   public static void grant(RpcController controller,
@@ -548,7 +547,7 @@ public class AccessControlUtil {
    * @param namespace the short name of the user to grant permissions
    * @param actions the permissions to be granted
    * @throws ServiceException
-   * @deprecated Use {@link Admin#grant(String, Permission, boolean)} instead.
+   * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead.
    */
   @Deprecated
   public static void grant(RpcController controller,
@@ -574,7 +573,7 @@ public class AccessControlUtil {
    * @param userShortName the short name of the user to revoke permissions
    * @param actions the permissions to be revoked
    * @throws ServiceException on failure
-   * @deprecated Use {@link Admin#revoke(String, Permission)} instead.
+   * @deprecated Use {@link Admin#revoke(UserPermission)} instead.
    */
   @Deprecated
   public static void revoke(RpcController controller,
@@ -604,7 +603,7 @@ public class AccessControlUtil {
    * @param q optional qualifier
    * @param actions the permissions to be revoked
    * @throws ServiceException on failure
-   * @deprecated Use {@link Admin#revoke(String, Permission)} instead.
+   * @deprecated Use {@link Admin#revoke(UserPermission)} instead.
    */
   @Deprecated
   public static void revoke(RpcController controller,
@@ -631,7 +630,7 @@ public class AccessControlUtil {
    * @param namespace optional table name
    * @param actions the permissions to be revoked
    * @throws ServiceException on failure
-   * @deprecated Use {@link Admin#revoke(String, Permission)} instead.
+   * @deprecated Use {@link Admin#revoke(UserPermission)} instead.
    */
   @Deprecated
   public static void revoke(RpcController controller,
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/GlobalPermission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/GlobalPermission.java
index b29317a..01d53eb 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/GlobalPermission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/GlobalPermission.java
@@ -23,15 +23,9 @@ import org.apache.yetus.audience.InterfaceAudience;
 /**
  * Represents an authorization for access whole cluster.
  */
-@InterfaceAudience.Private
+@InterfaceAudience.Public
 public class GlobalPermission extends Permission {
 
-  /** Default constructor for Writable, do not use */
-  public GlobalPermission() {
-    super();
-    this.scope = Scope.EMPTY;
-  }
-
   /**
    * Construct a global permission.
    * @param assigned assigned actions
@@ -41,15 +35,6 @@ public class GlobalPermission extends Permission {
     this.scope = Scope.GLOBAL;
   }
 
-  /**
-   * Construct a global permission.
-   * @param actionCode assigned actions
-   */
-  GlobalPermission(byte[] actionCode) {
-    super(actionCode);
-    this.scope = Scope.GLOBAL;
-  }
-
   @Override
   public int hashCode() {
     return super.hashCode();
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/NamespacePermission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/NamespacePermission.java
index c7ede96..7781d22 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/NamespacePermission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/NamespacePermission.java
@@ -30,39 +30,22 @@ import org.apache.yetus.audience.InterfaceAudience;
 /**
  * Represents an authorization for access for the given namespace.
  */
-@InterfaceAudience.Private
+@InterfaceAudience.Public
 public class NamespacePermission extends Permission {
 
   private String namespace = NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR;
 
-  /** Default constructor for Writable, do not use */
-  public NamespacePermission() {
-    super();
-    this.scope = Scope.EMPTY;
-  }
-
   /**
    * Construct a namespace permission.
    * @param namespace namespace's name
    * @param assigned assigned actions
    */
-  public NamespacePermission(String namespace, Action... assigned) {
+  NamespacePermission(String namespace, Action... assigned) {
     super(assigned);
     this.namespace = namespace;
     this.scope = Scope.NAMESPACE;
   }
 
-  /**
-   * Construct a namespace permission.
-   * @param namespace namespace's name
-   * @param actionCode assigned actions
-   */
-  public NamespacePermission(String namespace, byte[] actionCode) {
-    super(actionCode);
-    this.namespace = namespace;
-    this.scope = Scope.NAMESPACE;
-  }
-
   public String getNamespace() {
     return namespace;
   }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/Permission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/Permission.java
index e80cd33..49f2432 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/Permission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/Permission.java
@@ -21,8 +21,10 @@ package org.apache.hadoop.hbase.security.access;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -275,7 +277,7 @@ public class Permission extends VersionedWritable {
     private TableName tableName;
     private byte[] family;
     private byte[] qualifier;
-    private Action[] actions;
+    private List<Action> actions = new ArrayList<>();
 
     private Builder() {
     }
@@ -301,17 +303,37 @@ public class Permission extends VersionedWritable {
     }
 
     public Builder withActions(Action... actions) {
-      this.actions = actions;
+      for (Action action : actions) {
+        if (action != null) {
+          this.actions.add(action);
+        }
+      }
+      return this;
+    }
+
+    public Builder withActionCodes(byte[] actionCodes) {
+      if (actionCodes != null) {
+        for (byte code : actionCodes) {
+          Action action = ACTION_BY_CODE.get(code);
+          if (action == null) {
+            LOG.error("Ignoring unknown action code '{}'",
+              Bytes.toStringBinary(new byte[] { code }));
+            continue;
+          }
+          this.actions.add(action);
+        }
+      }
       return this;
     }
 
     public Permission build() {
+      Action[] actionArray = actions.toArray(new Action[actions.size()]);
       if (namespace != null) {
-        return new NamespacePermission(namespace, actions);
+        return new NamespacePermission(namespace, actionArray);
       } else if (tableName != null) {
-        return new TablePermission(tableName, family, qualifier, actions);
+        return new TablePermission(tableName, family, qualifier, actionArray);
       } else {
-        return new GlobalPermission(actions);
+        return new GlobalPermission(actionArray);
       }
     }
   }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
index 67fdba3..b354d87 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
@@ -18,7 +18,6 @@
 
 package org.apache.hadoop.hbase.security.access;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -86,16 +85,16 @@ public class ShadedAccessControlUtil {
   }
 
   /**
-   * Converts a list of Permission.Action shaded proto to a list of client Permission.Action
+   * Converts a list of Permission.Action shaded proto to an array of client Permission.Action
    * objects.
    * @param protoActions the list of shaded protobuf Actions
-   * @return the converted list of Actions
+   * @return the converted array of Actions
    */
-  public static List<Permission.Action> toPermissionActions(
-      List<AccessControlProtos.Permission.Action> protoActions) {
-    List<Permission.Action> actions = new ArrayList<>(protoActions.size());
-    for (AccessControlProtos.Permission.Action a : protoActions) {
-      actions.add(toPermissionAction(a));
+  public static Permission.Action[]
+      toPermissionActions(List<AccessControlProtos.Permission.Action> protoActions) {
+    Permission.Action[] actions = new Permission.Action[protoActions.size()];
+    for (int i = 0; i < protoActions.size(); i++) {
+      actions[i] = toPermissionAction(protoActions.get(i));
     }
     return actions;
   }
@@ -121,23 +120,22 @@ public class ShadedAccessControlUtil {
 
     if (proto.getType() == AccessControlProtos.Permission.Type.Global) {
       AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission();
-      List<Action> actions = toPermissionActions(perm.getActionList());
-
-      return new GlobalPermission(actions.toArray(new Permission.Action[actions.size()]));
+      Action[] actions = toPermissionActions(perm.getActionList());
+      return Permission.newBuilder().withActions(actions).build();
     }
     if (proto.getType() == AccessControlProtos.Permission.Type.Namespace) {
       AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission();
-      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+      Action[] actions = toPermissionActions(perm.getActionList());
 
       if (!proto.hasNamespacePermission()) {
         throw new IllegalStateException("Namespace must not be empty in NamespacePermission");
       }
       String ns = perm.getNamespaceName().toStringUtf8();
-      return new NamespacePermission(ns, actions.toArray(new Permission.Action[actions.size()]));
+      return Permission.newBuilder(ns).withActions(actions).build();
     }
     if (proto.getType() == AccessControlProtos.Permission.Type.Table) {
       AccessControlProtos.TablePermission perm = proto.getTablePermission();
-      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+      Action[] actions = toPermissionActions(perm.getActionList());
 
       byte[] qualifier = null;
       byte[] family = null;
@@ -149,9 +147,8 @@ public class ShadedAccessControlUtil {
 
       if (perm.hasFamily()) family = perm.getFamily().toByteArray();
       if (perm.hasQualifier()) qualifier = perm.getQualifier().toByteArray();
-
-      return new TablePermission(table, family, qualifier,
-          actions.toArray(new Permission.Action[actions.size()]));
+      return Permission.newBuilder(table).withFamily(family).withQualifier(qualifier)
+          .withActions(actions).build();
     }
     throw new IllegalStateException("Unrecognize Perm Type: " + proto.getType());
   }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
index 36ed8e4..f17919f 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
@@ -34,38 +34,13 @@ import org.apache.hadoop.hbase.util.Bytes;
  * given table. If the family property is <code>null</code>, it implies
  * full table access.
  */
-@InterfaceAudience.Private
+@InterfaceAudience.Public
 public class TablePermission extends Permission {
 
   private TableName table;
   private byte[] family;
   private byte[] qualifier;
 
-  /** Nullary constructor for Writable, do not use */
-  public TablePermission() {
-    super();
-    this.scope = Scope.EMPTY;
-  }
-
-  /**
-   * Construct a table permission.
-   * @param table table name
-   * @param assigned assigned actions
-   */
-  public TablePermission(TableName table, Action... assigned) {
-    this(table, null, null, assigned);
-  }
-
-  /**
-   * Construct a table:family permission.
-   * @param table table name
-   * @param family family name
-   * @param assigned assigned actions
-   */
-  public TablePermission(TableName table, byte[] family, Action... assigned) {
-    this(table, family, null, assigned);
-  }
-
   /**
    * Construct a table:family:qualifier permission.
    * @param table table name
@@ -73,7 +48,7 @@ public class TablePermission extends Permission {
    * @param qualifier qualifier name
    * @param assigned assigned actions
    */
-  public TablePermission(TableName table, byte[] family, byte[] qualifier, Action... assigned) {
+  TablePermission(TableName table, byte[] family, byte[] qualifier, Action... assigned) {
     super(assigned);
     this.table = table;
     this.family = family;
@@ -81,48 +56,10 @@ public class TablePermission extends Permission {
     this.scope = Scope.TABLE;
   }
 
-  /**
-   * Construct a table permission.
-   * @param table table name
-   * @param actionCodes assigned actions
-   */
-  public TablePermission(TableName table, byte[] actionCodes) {
-    this(table, null, null, actionCodes);
-  }
-
-  /**
-   * Construct a table:family permission.
-   * @param table table name
-   * @param family family name
-   * @param actionCodes assigned actions
-   */
-  public TablePermission(TableName table, byte[] family, byte[] actionCodes) {
-    this(table, family, null, actionCodes);
-  }
-
-  /**
-   * Construct a table:family:qualifier permission.
-   * @param table table name
-   * @param family family name
-   * @param qualifier qualifier name
-   * @param actionCodes assigned actions
-   */
-  public TablePermission(TableName table, byte[] family, byte[] qualifier, byte[] actionCodes) {
-    super(actionCodes);
-    this.table = table;
-    this.family = family;
-    this.qualifier = qualifier;
-    this.scope = Scope.TABLE;
-  }
-
   public TableName getTableName() {
     return table;
   }
 
-  public void setTableName(TableName table) {
-    this.table = table;
-  }
-
   public boolean hasFamily() {
     return family != null;
   }
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/UserPermission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/UserPermission.java
index 2a9a109..896ba52 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/UserPermission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/UserPermission.java
@@ -20,102 +20,19 @@ package org.apache.hadoop.hbase.security.access;
 
 import java.util.Objects;
 
-import org.apache.hadoop.hbase.TableName;
 import org.apache.yetus.audience.InterfaceAudience;
 
 /**
  * UserPermission consists of a user name and a permission.
  * Permission can be one of [Global, Namespace, Table] permission.
  */
-@InterfaceAudience.Private
+@InterfaceAudience.Public
 public class UserPermission {
 
   private String user;
   private Permission permission;
 
   /**
-   * Construct a global user permission.
-   * @param user user name
-   * @param assigned assigned actions
-   */
-  public UserPermission(String user, Permission.Action... assigned) {
-    this.user = user;
-    this.permission = new GlobalPermission(assigned);
-  }
-
-  /**
-   * Construct a global user permission.
-   * @param user user name
-   * @param actionCode action codes
-   */
-  public UserPermission(String user, byte[] actionCode) {
-    this.user = user;
-    this.permission = new GlobalPermission(actionCode);
-  }
-
-  /**
-   * Construct a namespace user permission.
-   * @param user user name
-   * @param namespace namespace
-   * @param assigned assigned actions
-   */
-  public UserPermission(String user, String namespace, Permission.Action... assigned) {
-    this.user = user;
-    this.permission = new NamespacePermission(namespace, assigned);
-  }
-
-  /**
-   * Construct a table user permission.
-   * @param user user name
-   * @param tableName table name
-   * @param assigned assigned actions
-   */
-  public UserPermission(String user, TableName tableName, Permission.Action... assigned) {
-    this.user = user;
-    this.permission = new TablePermission(tableName, assigned);
-  }
-
-  /**
-   * Construct a table:family user permission.
-   * @param user user name
-   * @param tableName table name
-   * @param family family name of table
-   * @param assigned assigned actions
-   */
-  public UserPermission(String user, TableName tableName, byte[] family,
-    Permission.Action... assigned) {
-    this(user, tableName, family, null, assigned);
-  }
-
-  /**
-   * Construct a table:family:qualifier user permission.
-   * @param user user name
-   * @param tableName table name
-   * @param family family name of table
-   * @param qualifier qualifier name of table
-   * @param assigned assigned actions
-   */
-  public UserPermission(String user, TableName tableName, byte[] family, byte[] qualifier,
-      Permission.Action... assigned) {
-    this.user = user;
-    this.permission = new TablePermission(tableName, family, qualifier, assigned);
-  }
-
-  /**
-   * Construct a table:family:qualifier user permission.
-   * @param user user name
-   * @param tableName table name
-   * @param family family name of table
-   * @param qualifier qualifier name of table
-   * @param actionCodes assigned actions
-   */
-  public UserPermission(String user, TableName tableName, byte[] family, byte[] qualifier,
-      byte[] actionCodes) {
-    this.user = user;
-    this.permission = new TablePermission(tableName, family, qualifier, actionCodes);
-  }
-
-  /**
    * Construct a user permission given permission.
    * @param user user name
    * @param permission one of [Global, Namespace, Table] permission
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java
index b5bf3a4..74c848d 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java
@@ -638,7 +638,8 @@ public class AccessControlLists {
       }
 
       return new Pair<>(username,
-        new NamespacePermission(Bytes.toString(fromNamespaceEntry(entryName)), value));
+          Permission.newBuilder(Bytes.toString(fromNamespaceEntry(entryName)))
+              .withActionCodes(value).build());
     }
 
     // Handle global entry
@@ -648,7 +649,7 @@ public class AccessControlLists {
         return null;
       }
 
-      return new Pair<>(username, new GlobalPermission(value));
+      return new Pair<>(username, Permission.newBuilder().withActionCodes(value).build());
     }
 
     // Handle table entry
@@ -681,8 +682,8 @@ public class AccessControlLists {
       }
     }
 
-    return new Pair<>(username,
-        new TablePermission(TableName.valueOf(entryName), permFamily, permQualifier, value));
+    return new Pair<>(username, Permission.newBuilder(TableName.valueOf(entryName))
+        .withFamily(permFamily).withQualifier(permQualifier).withActionCodes(value).build());
   }
 
   /*
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
index 67eff4b..6d57076 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
@@ -886,7 +886,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         if (owner == null)
           owner = getActiveUser(c).getShortName();
         final UserPermission userPermission = new UserPermission(owner,
-          desc.getTableName(), Action.values());
+            Permission.newBuilder(desc.getTableName()).withActions(Action.values()).build());
         // switch to the real hbase master user for doing the RPC on the ACL table
         User.runAsLoginUser(new PrivilegedExceptionAction<Void>() {
           @Override
@@ -989,9 +989,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       @Override
       public Void run() throws Exception {
         UserPermission userperm = new UserPermission(owner,
-          htd.getTableName(), Action.values());
-        try (Table table = c.getEnvironment().getConnection().
-            getTable(AccessControlLists.ACL_TABLE_NAME)) {
+            Permission.newBuilder(htd.getTableName()).withActions(Action.values()).build());
+        try (Table table =
+            c.getEnvironment().getConnection().getTable(AccessControlLists.ACL_TABLE_NAME)) {
           AccessControlLists.addUserPermission(conf, userperm, table);
         }
         return null;
@@ -2054,7 +2054,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   /* ---- Protobuf AccessControlService implementation ---- */
 
   /**
-   * @deprecated Use {@link Admin#grant(String, Permission, boolean)} instead.
+   * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead.
    */
   @Deprecated
   @Override
@@ -2077,7 +2077,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         preGrantOrRevoke(caller, "grant", perm);
 
         // regionEnv is set at #start. Hopefully not null at this point.
-        regionEnv.getConnection().getAdmin().grant(perm.getUser(), perm.getPermission(),
+        regionEnv.getConnection().getAdmin().grant(
+          new UserPermission(perm.getUser(), perm.getPermission()),
           request.getMergeExistingPermissions());
         if (AUDITLOG.isTraceEnabled()) {
           // audit log should store permission changes in addition to auth results
@@ -2096,7 +2097,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   }
 
   /**
-   * @deprecated Use {@link Admin#revoke(String, Permission)} instead.
+   * @deprecated Use {@link Admin#revoke(UserPermission)} instead.
    */
   @Deprecated
   @Override
@@ -2117,7 +2118,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         }
         preGrantOrRevoke(caller, "revoke", perm);
         // regionEnv is set at #start. Hopefully not null here.
-        regionEnv.getConnection().getAdmin().revoke(perm.getUser(), perm.getPermission());
+        regionEnv.getConnection().getAdmin()
+            .revoke(new UserPermission(perm.getUser(), perm.getPermission()));
         if (AUDITLOG.isTraceEnabled()) {
           // audit log should record all permission changes
           AUDITLOG.trace("Revoked permission " + perm.toString());
@@ -2212,7 +2214,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
             // them. Also using acl as table name to be inline with the results of global admin and
             // will help in avoiding any leakage of information about being superusers.
             for (String user : Superusers.getSuperUsers()) {
-              perms.add(new UserPermission(user, Action.values()));
+              perms.add(new UserPermission(user,
+                  Permission.newBuilder().withActions(Action.values()).build()));
             }
           }
         }
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
index 0acfb1a..ec251b8 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
@@ -865,10 +865,8 @@ public class RestoreSnapshotHelper {
         for (Entry<String, Permission> e : perms.entries()) {
           String user = e.getKey();
           TablePermission tablePerm = (TablePermission) e.getValue();
-          TablePermission newPerm = new TablePermission(newTableName,
-            tablePerm.getFamily(), tablePerm.getQualifier(), tablePerm.getActions());
-          AccessControlClient.grant(conn, newPerm.getTableName(), user, newPerm.getFamily(),
-            newPerm.getQualifier(), newPerm.getActions());
+          AccessControlClient.grant(conn, newTableName, user, tablePerm.getFamily(),
+            tablePerm.getQualifier(), tablePerm.getActions());
         }
       } catch (Throwable e) {
         throw new IOException("Grant acl into newly creatd table failed. snapshot: " + snapshot
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
index ef448ce..129f2b6 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
@@ -378,7 +378,8 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin().grant(user, new GlobalPermission(actions), false);
+          connection.getAdmin().grant(
+            new UserPermission(user, Permission.newBuilder().withActions(actions).build()), false);
         }
         return null;
       }
@@ -397,8 +398,8 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().grant(user, Permission.newBuilder().withActions(actions).build(),
-            false);
+          connection.getAdmin().grant(
+            new UserPermission(user, Permission.newBuilder().withActions(actions).build()), false);
         }
         return null;
       }
@@ -416,7 +417,8 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin().revoke(user, new GlobalPermission(actions));
+          connection.getAdmin().revoke(
+            new UserPermission(user, Permission.newBuilder().withActions(actions).build()));
         }
         return null;
       }
@@ -435,7 +437,8 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().revoke(user, Permission.newBuilder().withActions(actions).build());
+          connection.getAdmin().revoke(
+            new UserPermission(user, Permission.newBuilder().withActions(actions).build()));
         }
         return null;
       }
@@ -453,8 +456,9 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin()
-              .grant(user, new NamespacePermission(namespace, actions), false);
+          connection.getAdmin().grant(
+            new UserPermission(user, Permission.newBuilder(namespace).withActions(actions).build()),
+            false);
         }
         return null;
       }
@@ -474,8 +478,9 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().grant(user,
-            Permission.newBuilder(namespace).withActions(actions).build(), false);
+          connection.getAdmin().grant(
+            new UserPermission(user, Permission.newBuilder(namespace).withActions(actions).build()),
+            false);
         }
         return null;
       }
@@ -535,7 +540,8 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin().revoke(user, new NamespacePermission(namespace, actions));
+          connection.getAdmin().revoke(new UserPermission(user,
+              Permission.newBuilder(namespace).withActions(actions).build()));
         }
         return null;
       }
@@ -555,8 +561,8 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().revoke(user,
-            Permission.newBuilder(namespace).withActions(actions).build());
+          connection.getAdmin().revoke(new UserPermission(user,
+              Permission.newBuilder(namespace).withActions(actions).build()));
         }
         return null;
       }
@@ -575,7 +581,8 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin().grant(user, new TablePermission(table, family, qualifier, actions),
+          connection.getAdmin().grant(new UserPermission(user, Permission.newBuilder(table)
+              .withFamily(family).withQualifier(qualifier).withActions(actions).build()),
             false);
         }
         return null;
@@ -596,8 +603,8 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().grant(user, Permission.newBuilder(table).withFamily(family)
-              .withQualifier(qualifier).withActions(actions).build(),
+          connection.getAdmin().grant(new UserPermission(user, Permission.newBuilder(table)
+              .withFamily(family).withQualifier(qualifier).withActions(actions).build()),
             false);
         }
         return null;
@@ -659,8 +666,8 @@ public class SecureTestUtil {
       @Override
       public Void call() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
-          connection.getAdmin().revoke(user,
-            new TablePermission(table, family, qualifier, actions));
+          connection.getAdmin().revoke(new UserPermission(user, Permission.newBuilder(table)
+              .withFamily(family).withQualifier(qualifier).withActions(actions).build()));
         }
         return null;
       }
@@ -680,8 +687,8 @@ public class SecureTestUtil {
       public Void call() throws Exception {
         Configuration conf = util.getConfiguration();
         try (Connection connection = ConnectionFactory.createConnection(conf, caller)) {
-          connection.getAdmin().revoke(user, Permission.newBuilder(table).withFamily(family)
-              .withQualifier(qualifier).withActions(actions).build());
+          connection.getAdmin().revoke(new UserPermission(user, Permission.newBuilder(table)
+              .withFamily(family).withQualifier(qualifier).withActions(actions).build()));
         }
         return null;
       }
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
index 2d64db5..9e66dae 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
@@ -1168,8 +1168,9 @@ public class TestAccessController extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection conn = ConnectionFactory.createConnection(conf)) {
-          conn.getAdmin().grant(USER_RO.getShortName(),
-            new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ), false);
+          conn.getAdmin().grant(new UserPermission(USER_RO.getShortName(), Permission
+              .newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withActions(Action.READ).build()),
+            false);
         }
         return null;
       }
@@ -1179,8 +1180,8 @@ public class TestAccessController extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection conn = ConnectionFactory.createConnection(conf)) {
-          conn.getAdmin().revoke(USER_RO.getShortName(), Permission.newBuilder(TEST_TABLE)
-              .withFamily(TEST_FAMILY).withActions(Action.READ).build());
+          conn.getAdmin().revoke(new UserPermission(USER_RO.getShortName(), Permission
+              .newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withActions(Action.READ).build()));
         }
         return null;
       }
@@ -1218,8 +1219,8 @@ public class TestAccessController extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         ACCESS_CONTROLLER.preGrant(ObserverContextImpl.createAndPrepare(CP_ENV),
-          new UserPermission(USER_RO.getShortName(),
-              new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ)),
+          new UserPermission(USER_RO.getShortName(), Permission.newBuilder(TEST_TABLE)
+              .withFamily(TEST_FAMILY).withActions(Action.READ).build()),
           false);
         return null;
       }
@@ -1229,8 +1230,8 @@ public class TestAccessController extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         ACCESS_CONTROLLER.preRevoke(ObserverContextImpl.createAndPrepare(CP_ENV),
-          new UserPermission(USER_RO.getShortName(),
-              new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ)));
+          new UserPermission(USER_RO.getShortName(), Permission.newBuilder(TEST_TABLE)
+              .withFamily(TEST_FAMILY).withActions(Action.READ).build()));
         return null;
       }
     };
@@ -1689,8 +1690,8 @@ public class TestAccessController extends SecureTestUtil {
         acl.close();
       }
 
-      UserPermission ownerperm =
-          new UserPermission(USER_OWNER.getName(), tableName, Action.values());
+      UserPermission ownerperm = new UserPermission(USER_OWNER.getName(),
+          Permission.newBuilder(tableName).withActions(Action.values()).build());
       assertTrue("Owner should have all permissions on table",
         hasFoundUserPermission(ownerperm, perms));
 
@@ -1698,7 +1699,8 @@ public class TestAccessController extends SecureTestUtil {
       String userName = user.getShortName();
 
       UserPermission up =
-          new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ);
+          new UserPermission(userName, Permission.newBuilder(tableName).withFamily(family1)
+              .withQualifier(qualifier).withActions(Permission.Action.READ).build());
       assertFalse("User should not be granted permission: " + up.toString(),
         hasFoundUserPermission(up, perms));
 
@@ -1717,12 +1719,13 @@ public class TestAccessController extends SecureTestUtil {
       }
 
       UserPermission upToVerify =
-          new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ);
+          new UserPermission(userName, Permission.newBuilder(tableName).withFamily(family1)
+              .withQualifier(qualifier).withActions(Permission.Action.READ).build());
       assertTrue("User should be granted permission: " + upToVerify.toString(),
         hasFoundUserPermission(upToVerify, perms));
 
-      upToVerify =
-          new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE);
+      upToVerify = new UserPermission(userName, Permission.newBuilder(tableName).withFamily(family1)
+          .withQualifier(qualifier).withActions(Permission.Action.WRITE).build());
       assertFalse("User should not be granted permission: " + upToVerify.toString(),
         hasFoundUserPermission(upToVerify, perms));
 
@@ -1740,9 +1743,9 @@ public class TestAccessController extends SecureTestUtil {
         acl.close();
       }
 
-      upToVerify =
-          new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE,
-              Permission.Action.READ);
+      upToVerify = new UserPermission(userName,
+          Permission.newBuilder(tableName).withFamily(family1).withQualifier(qualifier)
+              .withActions(Permission.Action.WRITE, Permission.Action.READ).build());
       assertTrue("User should be granted permission: " + upToVerify.toString(),
         hasFoundUserPermission(upToVerify, perms));
 
@@ -1780,8 +1783,8 @@ public class TestAccessController extends SecureTestUtil {
         acl.close();
       }
 
-      UserPermission newOwnerperm =
-          new UserPermission(newOwner.getName(), tableName, Action.values());
+      UserPermission newOwnerperm = new UserPermission(newOwner.getName(),
+          Permission.newBuilder(tableName).withActions(Action.values()).build());
       assertTrue("New owner should have all permissions on table",
         hasFoundUserPermission(newOwnerperm, perms));
     } finally {
@@ -1805,10 +1808,12 @@ public class TestAccessController extends SecureTestUtil {
 
     Collection<String> superUsers = Superusers.getSuperUsers();
     List<UserPermission> adminPerms = new ArrayList<>(superUsers.size() + 1);
-    adminPerms.add(new UserPermission(USER_ADMIN.getShortName(), Bytes.toBytes("ACRW")));
-    for(String user: superUsers) {
+    adminPerms.add(new UserPermission(USER_ADMIN.getShortName(), Permission.newBuilder()
+        .withActions(Action.ADMIN, Action.CREATE, Action.READ, Action.WRITE).build()));
+    for (String user : superUsers) {
       // Global permission
-      adminPerms.add(new UserPermission(user, Action.values()));
+      adminPerms.add(
+        new UserPermission(user, Permission.newBuilder().withActions(Action.values()).build()));
     }
     assertTrue("Only super users, global users and user admin has permission on table hbase:acl " +
         "per setup", perms.size() == 5 + superUsers.size() &&
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
index 53f709e..4e35dc1 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
@@ -362,8 +362,9 @@ public class TestNamespaceCommands extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(conf)) {
-          connection.getAdmin().grant(testUser,
-            new NamespacePermission(TEST_NAMESPACE, Action.WRITE), false);
+          connection.getAdmin().grant(new UserPermission(testUser,
+              Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()),
+            false);
         }
         return null;
       }
@@ -372,8 +373,9 @@ public class TestNamespaceCommands extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection conn = ConnectionFactory.createConnection(conf)) {
-          conn.getAdmin().grant(USER_GROUP_NS_ADMIN.getShortName(),
-            new NamespacePermission(TEST_NAMESPACE, Action.READ), false);
+          conn.getAdmin().grant(new UserPermission(USER_GROUP_NS_ADMIN.getShortName(),
+              Permission.newBuilder(TEST_NAMESPACE).withActions(Action.READ).build()),
+            false);
         }
         return null;
       }
@@ -383,8 +385,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(conf)) {
-          connection.getAdmin().revoke(testUser,
-            new NamespacePermission(TEST_NAMESPACE, Action.WRITE));
+          connection.getAdmin().revoke(new UserPermission(testUser,
+              Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()));
         }
         return null;
       }
@@ -393,8 +395,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
       @Override
       public Object run() throws Exception {
         try (Connection connection = ConnectionFactory.createConnection(conf)) {
-          connection.getAdmin().revoke(USER_GROUP_NS_ADMIN.getShortName(),
-            new NamespacePermission(TEST_NAMESPACE, Action.READ));
+          connection.getAdmin().revoke(new UserPermission(USER_GROUP_NS_ADMIN.getShortName(),
+              Permission.newBuilder(TEST_NAMESPACE).withActions(Action.READ).build()));
         }
         return null;
       }
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestPermissionBuilder.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestPermissionBuilder.java
index 74a0c62..ff002b1 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestPermissionBuilder.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestPermissionBuilder.java
@@ -46,7 +46,7 @@ public class TestPermissionBuilder {
     assertEquals(0, permission.getActions().length);
 
     // check global permission with ADMIN action
-    permission = Permission.newBuilder().withActions(Action.ADMIN).build();
+    permission = Permission.newBuilder().withActionCodes(Bytes.toBytes("A")).build();
     assertTrue(permission instanceof GlobalPermission);
     assertEquals(1, permission.getActions().length);
     assertTrue(permission.getActions()[0] == Action.ADMIN);
@@ -57,8 +57,15 @@ public class TestPermissionBuilder {
           .withActions(Action.CREATE, Action.READ).build();
       fail("Should throw NPE");
     } catch (NullPointerException e) {
-      // catch NPE because set family but table name is null
+      // catch NPE because set qualifier but table name is null
     }
+
+    permission = Permission.newBuilder().withActionCodes(Bytes.toBytes("ACP"))
+        .withActions(Action.READ, Action.ADMIN).build();
+    assertEquals(3, permission.getActions().length);
+    assertEquals(Action.READ, permission.getActions()[0]);
+    assertEquals(Action.CREATE, permission.getActions()[1]);
+    assertEquals(Action.ADMIN, permission.getActions()[2]);
   }
 
   @Test
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java
index 1c478b2..8363665 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java
@@ -143,14 +143,18 @@ public class TestTablePermissions {
     try (Connection connection = ConnectionFactory.createConnection(conf)) {
       // add some permissions
       addUserPermission(conf,
-        new UserPermission("george", TEST_TABLE, Permission.Action.READ, Permission.Action.WRITE),
+        new UserPermission("george",
+            Permission.newBuilder(TEST_TABLE)
+                .withActions(Permission.Action.READ, Permission.Action.WRITE).build()),
         connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-        new UserPermission("hubert", TEST_TABLE, Permission.Action.READ),
+        new UserPermission("hubert",
+            Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build()),
         connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-        new UserPermission("humphrey", TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER,
-          Permission.Action.READ),
+        new UserPermission("humphrey",
+            Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_QUALIFIER)
+                .withActions(Permission.Action.READ).build()),
         connection.getTable(AccessControlLists.ACL_TABLE_NAME));
     }
     // retrieve the same
@@ -211,7 +215,8 @@ public class TestTablePermissions {
     try (Connection connection = ConnectionFactory.createConnection(conf);
         Table table = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) {
       AccessControlLists.addUserPermission(conf,
-        new UserPermission("hubert", TEST_TABLE2, Permission.Action.READ, Permission.Action.WRITE),
+        new UserPermission("hubert", Permission.newBuilder(TEST_TABLE2)
+            .withActions(Permission.Action.READ, Permission.Action.WRITE).build()),
         table);
     }
     // check full load
@@ -246,17 +251,24 @@ public class TestTablePermissions {
     Configuration conf = UTIL.getConfiguration();
     try (Connection connection = ConnectionFactory.createConnection(conf)) {
       addUserPermission(conf,
-        new UserPermission("albert", TEST_TABLE, Permission.Action.READ),
-          connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("albert",
+            Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-        new UserPermission("betty", TEST_TABLE, Permission.Action.READ, Permission.Action.WRITE),
-          connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("betty",
+            Permission.newBuilder(TEST_TABLE)
+                .withActions(Permission.Action.READ, Permission.Action.WRITE).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-        new UserPermission("clark", TEST_TABLE, TEST_FAMILY, Permission.Action.READ),
-          connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("clark",
+            Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY)
+                .withActions(Permission.Action.READ).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-        new UserPermission("dwight", TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER,
-          Permission.Action.WRITE), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("dwight",
+            Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_QUALIFIER)
+                .withActions(Permission.Action.WRITE).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
     }
     // verify permissions survive changes in table metadata
     ListMultimap<String, UserPermission> preperms =
@@ -302,17 +314,16 @@ public class TestTablePermissions {
 
   private ListMultimap<String, UserPermission> createPermissions() {
     ListMultimap<String, UserPermission> permissions = ArrayListMultimap.create();
-    permissions.put("george",
-      new UserPermission("george", TEST_TABLE, Permission.Action.READ));
-    permissions.put("george",
-      new UserPermission("george", TEST_TABLE, TEST_FAMILY, Permission.Action.WRITE));
-    permissions.put("george",
-      new UserPermission("george", TEST_TABLE2, Permission.Action.READ));
-    permissions.put("hubert",
-      new UserPermission("hubert", TEST_TABLE2, Permission.Action.READ,
-        Permission.Action.WRITE));
-    permissions.put("bruce",
-      new UserPermission("bruce", TEST_NAMESPACE, Permission.Action.READ));
+    permissions.put("george", new UserPermission("george",
+        Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build()));
+    permissions.put("george", new UserPermission("george", Permission.newBuilder(TEST_TABLE)
+        .withFamily(TEST_FAMILY).withActions(Permission.Action.WRITE).build()));
+    permissions.put("george", new UserPermission("george",
+        Permission.newBuilder(TEST_TABLE2).withActions(Permission.Action.READ).build()));
+    permissions.put("hubert", new UserPermission("hubert", Permission.newBuilder(TEST_TABLE2)
+        .withActions(Permission.Action.READ, Permission.Action.WRITE).build()));
+    permissions.put("bruce", new UserPermission("bruce",
+        Permission.newBuilder(TEST_NAMESPACE).withActions(Permission.Action.READ).build()));
     return permissions;
   }
 
@@ -334,50 +345,58 @@ public class TestTablePermissions {
 
   @Test
   public void testEquals() throws Exception {
-    Permission p1 = new TablePermission(TEST_TABLE, Permission.Action.READ);
-    Permission p2 = new TablePermission(TEST_TABLE, Permission.Action.READ);
+    Permission p1 = Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build();
+    Permission p2 = Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build();
     assertTrue(p1.equals(p2));
     assertTrue(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TablePermission.Action.READ, TablePermission.Action.WRITE);
-    p2 = new TablePermission(TEST_TABLE, TablePermission.Action.WRITE, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_TABLE)
+        .withActions(TablePermission.Action.READ, TablePermission.Action.WRITE).build();
+    p2 = Permission.newBuilder(TEST_TABLE)
+        .withActions(TablePermission.Action.WRITE, TablePermission.Action.READ).build();
     assertTrue(p1.equals(p2));
     assertTrue(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.READ, TablePermission.Action.WRITE);
-    p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.WRITE, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY)
+        .withActions(TablePermission.Action.READ, TablePermission.Action.WRITE).build();
+    p2 = Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY)
+        .withActions(TablePermission.Action.WRITE, TablePermission.Action.READ).build();
     assertTrue(p1.equals(p2));
     assertTrue(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER, TablePermission.Action.READ, TablePermission.Action.WRITE);
-    p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER, TablePermission.Action.WRITE, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_QUALIFIER)
+        .withActions(TablePermission.Action.READ, TablePermission.Action.WRITE).build();
+    p2 = Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_QUALIFIER)
+        .withActions(TablePermission.Action.WRITE, TablePermission.Action.READ).build();
     assertTrue(p1.equals(p2));
     assertTrue(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TablePermission.Action.READ);
-    p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_TABLE).withActions(TablePermission.Action.READ).build();
+    p2 = Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY)
+        .withActions(TablePermission.Action.READ).build();
     assertFalse(p1.equals(p2));
     assertFalse(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TablePermission.Action.READ);
-    p2 = new TablePermission(TEST_TABLE, TablePermission.Action.WRITE);
+    p1 = Permission.newBuilder(TEST_TABLE).withActions(TablePermission.Action.READ).build();
+    p2 = Permission.newBuilder(TEST_TABLE).withActions(TablePermission.Action.WRITE).build();
     assertFalse(p1.equals(p2));
     assertFalse(p2.equals(p1));
-    p2 = new TablePermission(TEST_TABLE, TablePermission.Action.READ, TablePermission.Action.WRITE);
+    p2 = Permission.newBuilder(TEST_TABLE)
+        .withActions(TablePermission.Action.READ, TablePermission.Action.WRITE).build();
     assertFalse(p1.equals(p2));
     assertFalse(p2.equals(p1));
 
-    p1 = new TablePermission(TEST_TABLE, TablePermission.Action.READ);
-    p2 = new TablePermission(TEST_TABLE2, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_TABLE).withActions(TablePermission.Action.READ).build();
+    p2 = Permission.newBuilder(TEST_TABLE2).withActions(TablePermission.Action.READ).build();
     assertFalse(p1.equals(p2));
     assertFalse(p2.equals(p1));
 
-    p1 = new NamespacePermission(TEST_NAMESPACE, TablePermission.Action.READ);
-    p2 = new NamespacePermission(TEST_NAMESPACE, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_NAMESPACE).withActions(TablePermission.Action.READ).build();
+    p2 = Permission.newBuilder(TEST_NAMESPACE).withActions(TablePermission.Action.READ).build();
     assertEquals(p1, p2);
 
-    p1 = new NamespacePermission(TEST_NAMESPACE, TablePermission.Action.READ);
-    p2 = new NamespacePermission(TEST_NAMESPACE2, TablePermission.Action.READ);
+    p1 = Permission.newBuilder(TEST_NAMESPACE).withActions(TablePermission.Action.READ).build();
+    p2 = Permission.newBuilder(TEST_NAMESPACE2).withActions(TablePermission.Action.READ).build();
     assertFalse(p1.equals(p2));
     assertFalse(p2.equals(p1));
   }
@@ -389,15 +408,20 @@ public class TestTablePermissions {
     // add some permissions
     try (Connection connection = ConnectionFactory.createConnection(conf)) {
       addUserPermission(conf,
-          new UserPermission("user1",
-              Permission.Action.READ, Permission.Action.WRITE), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("user1", Permission.newBuilder()
+            .withActions(Permission.Action.READ, Permission.Action.WRITE).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-          new UserPermission("user2",
-              Permission.Action.CREATE), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("user2",
+            Permission.newBuilder().withActions(Permission.Action.CREATE).build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
       addUserPermission(conf,
-          new UserPermission("user3",
-              Permission.Action.ADMIN, Permission.Action.READ, Permission.Action.CREATE),
-          connection.getTable(AccessControlLists.ACL_TABLE_NAME));
+        new UserPermission("user3",
+            Permission.newBuilder()
+                .withActions(Permission.Action.ADMIN, Permission.Action.READ,
+                  Permission.Action.CREATE)
+                .build()),
+        connection.getTable(AccessControlLists.ACL_TABLE_NAME));
     }
     ListMultimap<String, UserPermission> perms =
       AccessControlLists.getTablePermissions(conf, null);
@@ -434,9 +458,13 @@ public class TestTablePermissions {
     User currentUser = User.getCurrent();
     assertTrue(authManager.authorizeUserGlobal(currentUser, Permission.Action.ADMIN));
     try (Connection connection = ConnectionFactory.createConnection(conf)) {
-      for (int i=1; i<=50; i++) {
-        addUserPermission(conf, new UserPermission("testauth"+i,
-          Permission.Action.ADMIN, Permission.Action.READ, Permission.Action.WRITE),
+      for (int i = 1; i <= 50; i++) {
+        addUserPermission(conf,
+          new UserPermission("testauth" + i,
+              Permission.newBuilder()
+                  .withActions(Permission.Action.ADMIN, Permission.Action.READ,
+                    Permission.Action.WRITE)
+                  .build()),
           connection.getTable(AccessControlLists.ACL_TABLE_NAME));
         // make sure the system user still shows as authorized
         assertTrue("Failed current user auth check on iter "+i,
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
index 57d9e4b..dc40bbd 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
@@ -381,11 +381,12 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
     AccessTestAction checkMultiQualifierRead = new AccessTestAction() {
       @Override
       public Void run() throws Exception {
-        checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), new Permission[] {
-          new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
-            Permission.Action.READ),
-          new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2,
-            Permission.Action.READ), });
+        checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(),
+          new Permission[] {
+              Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
+                  .withQualifier(TEST_Q1).withActions(Action.READ).build(),
+              Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
+                  .withQualifier(TEST_Q2).withActions(Action.READ).build() });
         return null;
       }
     };
@@ -397,11 +398,14 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
     AccessTestAction checkMultiQualifierReadWrite = new AccessTestAction() {
       @Override
       public Void run() throws Exception {
-        checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), new Permission[] {
-            new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
-              Permission.Action.READ, Permission.Action.WRITE),
-            new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2,
-              Permission.Action.READ, Permission.Action.WRITE), });
+        checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(),
+          new Permission[] {
+              Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
+                  .withQualifier(TEST_Q1)
+                  .withActions(Permission.Action.READ, Permission.Action.WRITE).build(),
+              Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
+                  .withQualifier(TEST_Q2)
+                  .withActions(Permission.Action.READ, Permission.Action.WRITE).build() });
         return null;
       }
     };
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestZKPermissionWatcher.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestZKPermissionWatcher.java
index cfd6512..327c49d 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestZKPermissionWatcher.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestZKPermissionWatcher.java
@@ -113,8 +113,8 @@ public class TestZKPermissionWatcher {
 
     // update ACL: george RW
     List<UserPermission> acl = new ArrayList<>(1);
-    acl.add(new UserPermission(george.getShortName(), TEST_TABLE,
-      Permission.Action.READ, Permission.Action.WRITE));
+    acl.add(new UserPermission(george.getShortName(), Permission.newBuilder(TEST_TABLE)
+        .withActions(Permission.Action.READ, Permission.Action.WRITE).build()));
     ListMultimap<String, UserPermission> multimap = ArrayListMultimap.create();
     multimap.putAll(george.getShortName(), acl);
     byte[] serialized = AccessControlLists.writePermissionsAsBytes(multimap, conf);
@@ -141,7 +141,8 @@ public class TestZKPermissionWatcher {
 
     // update ACL: hubert R
     List<UserPermission> acl2 = new ArrayList<>(1);
-    acl2.add(new UserPermission(hubert.getShortName(), TEST_TABLE, TablePermission.Action.READ));
+    acl2.add(new UserPermission(hubert.getShortName(),
+        Permission.newBuilder(TEST_TABLE).withActions(TablePermission.Action.READ).build()));
     final long mtimeA = AUTH_A.getMTime();
     multimap.putAll(hubert.getShortName(), acl2);
     byte[] serialized2 = AccessControlLists.writePermissionsAsBytes(multimap, conf);
diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java
index df15256..d701152 100644
--- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java
+++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java
@@ -58,7 +58,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
-import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
 import org.apache.hadoop.hbase.thrift2.ThriftUtilities;
 import org.apache.hadoop.hbase.thrift2.generated.TColumnFamilyDescriptor;
@@ -1341,12 +1341,12 @@ public class ThriftAdmin implements Admin {
   }
 
   @Override
-  public void grant(String userName, Permission permission, boolean mergeExistingPermissions) {
+  public void grant(UserPermission userPermission, boolean mergeExistingPermissions) {
     throw new NotImplementedException("grant not supported in ThriftAdmin");
   }
 
   @Override
-  public void revoke(String userName, Permission permission) {
+  public void revoke(UserPermission userPermission) {
     throw new NotImplementedException("revoke not supported in ThriftAdmin");
   }
 }