private static Pair<String, Permission> parsePermissionRecord(byte[] entryName, Cell kv,
    byte[] cf, byte[] cq, boolean filterPerms, String filterUser) {
    // return X given a set of permissions encoded in the permissionRecord kv.
    byte[] family = CellUtil.cloneFamily(kv);
    if (!Bytes.equals(family, ACL_LIST_FAMILY)) {
      return null;
    }

    byte[] key = CellUtil.cloneQualifier(kv);
    byte[] value = CellUtil.cloneValue(kv);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Read acl: entry[" + Bytes.toStringBinary(entryName) + "], kv ["
        + Bytes.toStringBinary(key) + ": " + Bytes.toStringBinary(value) + "]");
    }

    // check for a column family appended to the key
    // TODO: avoid the string conversion to make this more efficient
    String username = Bytes.toString(key);

    // Retrieve group list for the filterUser if cell key is a group.
    // Group list is not required when filterUser itself a group
    List<String> filterUserGroups = null;
    if (filterPerms) {
      if (
        username.charAt(0) == '@' && !StringUtils.isEmpty(filterUser) && filterUser.charAt(0) != '@'
      ) {
        filterUserGroups = AccessChecker.getUserGroups(filterUser);
      }
    }

    // Handle namespace entry
    if (isNamespaceEntry(entryName)) {
      // Filter the permissions cell record if client query
      if (filterPerms && !validateFilterUser(username, filterUser, filterUserGroups)) {
        return null;
      }

      return new Pair<>(username, Permission
        .newBuilder(Bytes.toString(fromNamespaceEntry(entryName))).withActionCodes(value).build());
    }

    // Handle global entry
    if (isGlobalEntry(entryName)) {
      // Filter the permissions cell record if client query
      if (filterPerms && !validateFilterUser(username, filterUser, filterUserGroups)) {
        return null;
      }

      return new Pair<>(username, Permission.newBuilder().withActionCodes(value).build());
    }

    // Handle table entry
    int idx = username.indexOf(ACL_KEY_DELIMITER);
    byte[] permFamily = null;
    byte[] permQualifier = null;
    if (idx > 0 && idx < username.length() - 1) {
      String remainder = username.substring(idx + 1);
      username = username.substring(0, idx);
      idx = remainder.indexOf(ACL_KEY_DELIMITER);
      if (idx > 0 && idx < remainder.length() - 1) {
        permFamily = Bytes.toBytes(remainder.substring(0, idx));
        permQualifier = Bytes.toBytes(remainder.substring(idx + 1));
      } else {
        permFamily = Bytes.toBytes(remainder);
      }
    }

    // Filter the permissions cell record if client query
    if (filterPerms) {
      // ACL table contain 3 types of cell key entries; hbase:Acl, namespace and table. So to filter
      // the permission cell records additional validations are required at CF, CQ and username.
      // Here we can proceed based on client input whether it contain filterUser.
      // Validate the filterUser when specified
      if (filterUser != null && !validateFilterUser(username, filterUser, filterUserGroups)) {
        return null;
      }
      if (!validateCFAndCQ(permFamily, cf, permQualifier, cq)) {
        return null;
      }
    }

    return new Pair<>(username, Permission.newBuilder(TableName.valueOf(entryName))
      .withFamily(permFamily).withQualifier(permQualifier).withActionCodes(value).build());
  }
Parse and filter permission based on the specified column family, column qualifier and user
name.
hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/PermissionStorage.java