@Override
  public void postGrant(ObserverContext<MasterCoprocessorEnvironment> c,
    UserPermission userPermission, boolean mergeExistingPermissions) throws IOException {
    if (
      !checkInitialized(
        "grant " + userPermission + ", merge existing permissions " + mergeExistingPermissions)
    ) {
      return;
    }
    try (Table aclTable =
      c.getEnvironment().getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
      Configuration conf = c.getEnvironment().getConfiguration();
      String userName = userPermission.getUser();
      switch (userPermission.getAccessScope()) {
        case GLOBAL:
          UserPermission perm = getUserGlobalPermission(conf, userName);
          if (perm != null && hdfsAclHelper.containReadAction(perm)) {
            if (!isHdfsAclSet(aclTable, userName)) {
              // 1. Get namespaces and tables which global user acls are already synced
              Pair<Set<String>, Set<TableName>> skipNamespaceAndTables =
                SnapshotScannerHDFSAclStorage.getUserNamespaceAndTable(aclTable, userName);
              Set<String> skipNamespaces = skipNamespaceAndTables.getFirst();
              Set<TableName> skipTables = skipNamespaceAndTables.getSecond().stream()
                .filter(t -> !skipNamespaces.contains(t.getNamespaceAsString()))
                .collect(Collectors.toSet());
              // 2. Add HDFS acl(skip namespaces and tables directories whose acl is set)
              hdfsAclHelper.grantAcl(userPermission, skipNamespaces, skipTables);
              // 3. Record global acl is sync to HDFS
              SnapshotScannerHDFSAclStorage.addUserGlobalHdfsAcl(aclTable, userName);
            }
          } else {
            // The merged user permission doesn't contain READ, so remove user global HDFS acls if
            // it's set
            removeUserGlobalHdfsAcl(aclTable, userName, userPermission);
          }
          break;
        case NAMESPACE:
          String namespace = ((NamespacePermission) userPermission.getPermission()).getNamespace();
          UserPermission nsPerm = getUserNamespacePermission(conf, userName, namespace);
          if (nsPerm != null && hdfsAclHelper.containReadAction(nsPerm)) {
            if (!isHdfsAclSet(aclTable, userName, namespace)) {
              // 1. Get tables which namespace user acls are already synced
              Set<TableName> skipTables = SnapshotScannerHDFSAclStorage
                .getUserNamespaceAndTable(aclTable, userName).getSecond();
              // 2. Add HDFS acl(skip tables directories whose acl is set)
              hdfsAclHelper.grantAcl(userPermission, new HashSet<>(0), skipTables);
            }
            // 3. Record namespace acl is synced to HDFS
            SnapshotScannerHDFSAclStorage.addUserNamespaceHdfsAcl(aclTable, userName, namespace);
          } else {
            // The merged user permission doesn't contain READ, so remove user namespace HDFS acls
            // if it's set
            removeUserNamespaceHdfsAcl(aclTable, userName, namespace, userPermission);
          }
          break;
        case TABLE:
          TablePermission tablePerm = (TablePermission) userPermission.getPermission();
          if (needHandleTableHdfsAcl(tablePerm)) {
            TableName tableName = tablePerm.getTableName();
            UserPermission tPerm = getUserTablePermission(conf, userName, tableName);
            if (tPerm != null && hdfsAclHelper.containReadAction(tPerm)) {
              if (!isHdfsAclSet(aclTable, userName, tableName)) {
                // 1. create table dirs
                hdfsAclHelper.createTableDirectories(tableName);
                // 2. Add HDFS acl
                hdfsAclHelper.grantAcl(userPermission, new HashSet<>(0), new HashSet<>(0));
              }
              // 2. Record table acl is synced to HDFS
              SnapshotScannerHDFSAclStorage.addUserTableHdfsAcl(aclTable, userName, tableName);
            } else {
              // The merged user permission doesn't contain READ, so remove user table HDFS acls if
              // it's set
              removeUserTableHdfsAcl(aclTable, userName, tableName, userPermission);
            }
          }
          break;
        default:
          throw new IllegalArgumentException(
            "Illegal user permission scope " + userPermission.getAccessScope());
      }
    }
  }
Delete namespace tmp directory because it's created by this coprocessor when namespace is
created to make namespace default acl can be inherited by tables. The namespace data
directory is deleted by DeleteNamespaceProcedure, the namespace archive directory is
deleted by HFileCleaner.
hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclController.java