You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ch...@apache.org on 2022/04/29 09:46:19 UTC

[iotdb] branch master updated: [IOTDB-3025] add permission check (#5699)

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

chaow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 685ea15ed6 [IOTDB-3025] add permission check (#5699)
685ea15ed6 is described below

commit 685ea15ed64997b7a56a04969311af2c3c6dabd6
Author: 任宇华 <79...@users.noreply.github.com>
AuthorDate: Fri Apr 29 17:46:13 2022 +0800

    [IOTDB-3025] add permission check (#5699)
    
    Co-authored-by: renyuhua <ry...@163.com>
    Co-authored-by: Jinrui.Zhang <xi...@gmail.com>
---
 .../iotdb/confignode/manager/ConfigManager.java    |  13 +-
 .../apache/iotdb/confignode/manager/Manager.java   |  12 ++
 .../confignode/manager/PermissionManager.java      |  11 ++
 .../iotdb/confignode/persistence/AuthorInfo.java   | 128 ++++++++++++++-----
 .../thrift/ConfigNodeRPCServiceProcessor.java      |   7 ++
 .../thrift/ConfigNodeRPCServiceProcessorTest.java  |  22 ++++
 .../org/apache/iotdb/db/auth/AuthorityChecker.java | 138 ++++++++++++++++++++-
 .../db/auth/authorizer/AuthorizerManager.java      |  44 +++++++
 .../db/auth/authorizer/ClusterAuthorizer.java      |  61 ++++++++-
 .../apache/iotdb/db/client/ConfigNodeClient.java   |  16 +++
 .../iotdb/db/mpp/sql/statement/Statement.java      |   9 ++
 .../statement/crud/AggregationQueryStatement.java  |   2 +
 .../mpp/sql/statement/crud/FillQueryStatement.java |   1 +
 .../statement/crud/GroupByFillQueryStatement.java  |   1 +
 .../sql/statement/crud/GroupByQueryStatement.java  |   2 +
 .../sql/statement/crud/InsertBaseStatement.java    |   8 ++
 .../crud/InsertMultiTabletsStatement.java          |   9 ++
 .../mpp/sql/statement/crud/InsertRowStatement.java |  12 ++
 .../crud/InsertRowsOfOneDeviceStatement.java       |  11 ++
 .../sql/statement/crud/InsertRowsStatement.java    |   9 ++
 .../db/mpp/sql/statement/crud/InsertStatement.java |  11 ++
 .../sql/statement/crud/InsertTabletStatement.java  |  11 ++
 .../mpp/sql/statement/crud/LastQueryStatement.java |   2 +
 .../db/mpp/sql/statement/crud/QueryStatement.java  |   5 +
 .../mpp/sql/statement/crud/UDAFQueryStatement.java |   1 +
 .../mpp/sql/statement/crud/UDTFQueryStatement.java |   1 +
 .../metadata/AlterTimeSeriesStatement.java         |   7 ++
 .../mpp/sql/statement/metadata/CountStatement.java |   8 ++
 .../metadata/CreateAlignedTimeSeriesStatement.java |  20 +++
 .../metadata/CreateTimeSeriesStatement.java        |   7 ++
 .../statement/metadata/SchemaFetchStatement.java   |   8 ++
 .../metadata/SetStorageGroupStatement.java         |  10 ++
 .../statement/metadata/ShowDevicesStatement.java   |   8 ++
 .../mpp/sql/statement/metadata/ShowStatement.java  |   9 ++
 .../metadata/ShowStorageGroupStatement.java        |   8 ++
 .../db/mpp/sql/statement/sys/AuthorStatement.java  |  63 +++++++++-
 .../thrift/impl/DataNodeTSIServiceImpl.java        |  79 ++++++++----
 .../java/org/apache/iotdb/rpc/TSStatusCode.java    |   3 +
 .../src/main/thrift/confignode.thrift              |   8 ++
 39 files changed, 721 insertions(+), 64 deletions(-)

diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index c8b55e1bdc..580f5f49f1 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -43,7 +43,6 @@ import org.apache.iotdb.confignode.consensus.response.DataPartitionResp;
 import org.apache.iotdb.confignode.consensus.response.PermissionInfoResp;
 import org.apache.iotdb.confignode.consensus.response.SchemaPartitionResp;
 import org.apache.iotdb.confignode.consensus.response.StorageGroupSchemaResp;
-import org.apache.iotdb.confignode.persistence.AuthorInfo;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -361,7 +360,17 @@ public class ConfigManager implements Manager {
   public TSStatus login(String username, String password) {
     TSStatus status = confirmLeader();
     if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-      return AuthorInfo.getInstance().login(username, password);
+      return permissionManager.login(username, password);
+    } else {
+      return status;
+    }
+  }
+
+  @Override
+  public TSStatus checkUserPrivileges(String username, List<String> paths, int permission) {
+    TSStatus status = confirmLeader();
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      return permissionManager.checkUserPrivileges(username, paths, permission);
     } else {
       return status;
     }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/Manager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/Manager.java
index 1da702de25..4830af4a75 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/Manager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/Manager.java
@@ -34,6 +34,8 @@ import org.apache.iotdb.confignode.consensus.request.write.SetTimePartitionInter
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
 
+import java.util.List;
+
 /**
  * a subset of services provided by {@ConfigManager}. For use internally only, passed to Managers,
  * services.
@@ -170,4 +172,14 @@ public interface Manager {
    * @return
    */
   TSStatus login(String username, String password);
+
+  /**
+   * Check User Privileges
+   *
+   * @param username
+   * @param paths
+   * @param permission
+   * @return
+   */
+  TSStatus checkUserPrivileges(String username, List<String> paths, int permission);
 }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
index e17e9181b5..61ef6a614a 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
@@ -22,6 +22,9 @@ package org.apache.iotdb.confignode.manager;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.confignode.consensus.request.auth.AuthorReq;
 import org.apache.iotdb.confignode.consensus.response.PermissionInfoResp;
+import org.apache.iotdb.confignode.persistence.AuthorInfo;
+
+import java.util.List;
 
 /** manager permission query and operation */
 public class PermissionManager {
@@ -55,4 +58,12 @@ public class PermissionManager {
   private ConsensusManager getConsensusManager() {
     return configManager.getConsensusManager();
   }
+
+  public TSStatus login(String username, String password) {
+    return AuthorInfo.getInstance().login(username, password);
+  }
+
+  public TSStatus checkUserPrivileges(String username, List<String> paths, int permission) {
+    return AuthorInfo.getInstance().checkUserPrivileges(username, paths, permission);
+  }
 }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
index 4428434b44..f489f70449 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.db.auth.entity.PrivilegeType;
 import org.apache.iotdb.db.auth.entity.Role;
 import org.apache.iotdb.db.auth.entity.User;
 import org.apache.iotdb.db.utils.AuthUtils;
+import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -77,7 +78,37 @@ public class AuthorInfo {
     return tsStatus;
   }
 
-  public TSStatus authorNonQuery(AuthorReq authorReq) throws AuthException {
+  public TSStatus checkUserPrivileges(String username, List<String> paths, int permission) {
+    boolean status = true;
+    try {
+      for (String path : paths) {
+        if (!checkOnePath(username, path, permission)) {
+          status = false;
+        }
+      }
+    } catch (AuthException e) {
+      status = false;
+    }
+    if (status) {
+      return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
+    } else {
+      return RpcUtils.getStatus(TSStatusCode.NO_PERMISSION_ERROR);
+    }
+  }
+
+  private boolean checkOnePath(String username, String path, int permission) throws AuthException {
+    try {
+      if (authorizer.checkUserPrivileges(username, path, permission)) {
+        return true;
+      }
+    } catch (AuthException e) {
+      logger.error("Error occurs when checking the seriesPath {} for user {}", path, username, e);
+      throw new AuthException(e);
+    }
+    return false;
+  }
+
+  public TSStatus authorNonQuery(AuthorReq authorReq) {
     ConfigRequestType authorType = authorReq.getAuthorType();
     String userName = authorReq.getUserName();
     String roleName = authorReq.getRoleName();
@@ -129,39 +160,49 @@ public class AuthorInfo {
           authorizer.revokeRoleFromUser(roleName, userName);
           break;
         default:
-          throw new AuthException("execute " + authorReq + " failed");
+          throw new AuthException("unknown type: " + authorReq.getAuthorType());
       }
     } catch (AuthException e) {
-      throw new AuthException("execute " + authorReq + " failed: ", e);
+      return RpcUtils.getStatus(TSStatusCode.EXECUTE_PERMISSION_EXCEPTION_ERROR, e.getMessage());
     }
-    return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+    return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
   }
 
-  public PermissionInfoResp executeListRole() throws AuthException {
+  public PermissionInfoResp executeListRole() {
     PermissionInfoResp result = new PermissionInfoResp();
     List<String> roleList = authorizer.listAllRoles();
     Map<String, List<String>> permissionInfo = new HashMap<>();
     permissionInfo.put(IoTDBConstant.COLUMN_ROLE, roleList);
-    result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
     result.setPermissionInfo(permissionInfo);
     return result;
   }
 
-  public PermissionInfoResp executeListUser() throws AuthException {
+  public PermissionInfoResp executeListUser() {
     PermissionInfoResp result = new PermissionInfoResp();
     List<String> userList = authorizer.listAllUsers();
     Map<String, List<String>> permissionInfo = new HashMap<>();
     permissionInfo.put(IoTDBConstant.COLUMN_USER, userList);
-    result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
     result.setPermissionInfo(permissionInfo);
     return result;
   }
 
   public PermissionInfoResp executeListRoleUsers(AuthorReq plan) throws AuthException {
     PermissionInfoResp result = new PermissionInfoResp();
-    Role role = authorizer.getRole(plan.getRoleName());
-    if (role == null) {
-      throw new AuthException("No such role : " + plan.getRoleName());
+    Map<String, List<String>> permissionInfo = new HashMap<>();
+    Role role;
+    try {
+      role = authorizer.getRole(plan.getRoleName());
+      if (role == null) {
+        result.setStatus(
+            RpcUtils.getStatus(
+                TSStatusCode.ROLE_NOT_EXIST_ERROR, "No such role : " + plan.getRoleName()));
+        result.setPermissionInfo(permissionInfo);
+        return result;
+      }
+    } catch (AuthException e) {
+      throw new AuthException(e);
     }
     List<String> roleUsersList = new ArrayList<>();
     List<String> userList = authorizer.listAllUsers();
@@ -171,35 +212,54 @@ public class AuthorInfo {
         roleUsersList.add(userN);
       }
     }
-    Map<String, List<String>> permissionInfo = new HashMap<>();
     permissionInfo.put(IoTDBConstant.COLUMN_USER, roleUsersList);
-    result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
     result.setPermissionInfo(permissionInfo);
     return result;
   }
 
   public PermissionInfoResp executeListUserRoles(AuthorReq plan) throws AuthException {
     PermissionInfoResp result = new PermissionInfoResp();
-    User user = authorizer.getUser(plan.getUserName());
-    if (user == null) {
-      throw new AuthException("No such user : " + plan.getUserName());
+    Map<String, List<String>> permissionInfo = new HashMap<>();
+    User user;
+    try {
+      user = authorizer.getUser(plan.getUserName());
+      if (user == null) {
+        result.setStatus(
+            RpcUtils.getStatus(
+                TSStatusCode.USER_NOT_EXIST_ERROR, "No such user : " + plan.getUserName()));
+        result.setPermissionInfo(permissionInfo);
+        return result;
+      }
+    } catch (AuthException e) {
+      throw new AuthException(e);
     }
     List<String> userRoleList = new ArrayList<>();
     for (String roleN : user.getRoleList()) {
       userRoleList.add(roleN);
     }
-    Map<String, List<String>> permissionInfo = new HashMap<>();
+
     permissionInfo.put(IoTDBConstant.COLUMN_ROLE, userRoleList);
-    result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
     result.setPermissionInfo(permissionInfo);
     return result;
   }
 
   public PermissionInfoResp executeListRolePrivileges(AuthorReq plan) throws AuthException {
     PermissionInfoResp result = new PermissionInfoResp();
-    Role role = authorizer.getRole(plan.getRoleName());
-    if (role == null) {
-      throw new AuthException("No such role : " + plan.getRoleName());
+    Map<String, List<String>> permissionInfo = new HashMap<>();
+    Role role;
+    try {
+      role = authorizer.getRole(plan.getRoleName());
+      if (role == null) {
+        result.setStatus(
+            RpcUtils.getStatus(
+                TSStatusCode.ROLE_NOT_EXIST_ERROR, "No such role : " + plan.getRoleName()));
+        result.setPermissionInfo(permissionInfo);
+        return result;
+      }
+    } catch (AuthException e) {
+      throw new AuthException(e);
     }
     List<String> rolePrivilegesList = new ArrayList<>();
     for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
@@ -208,27 +268,37 @@ public class AuthorInfo {
         rolePrivilegesList.add(pathPrivilege.toString());
       }
     }
-    Map<String, List<String>> permissionInfo = new HashMap<>();
+
     permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, rolePrivilegesList);
-    result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+    result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
     result.setPermissionInfo(permissionInfo);
     return result;
   }
 
   public PermissionInfoResp executeListUserPrivileges(AuthorReq plan) throws AuthException {
     PermissionInfoResp result = new PermissionInfoResp();
-    User user = authorizer.getUser(plan.getUserName());
-    if (user == null) {
-      throw new AuthException("No such user : " + plan.getUserName());
+    Map<String, List<String>> permissionInfo = new HashMap<>();
+    User user;
+    try {
+      user = authorizer.getUser(plan.getUserName());
+      if (user == null) {
+        result.setStatus(
+            RpcUtils.getStatus(
+                TSStatusCode.USER_NOT_EXIST_ERROR, "No such user : " + plan.getUserName()));
+        result.setPermissionInfo(permissionInfo);
+        return result;
+      }
+    } catch (AuthException e) {
+      throw new AuthException(e);
     }
     List<String> userPrivilegesList = new ArrayList<>();
-    Map<String, List<String>> permissionInfo = new HashMap<>();
+
     if (IoTDBConstant.PATH_ROOT.equals(plan.getUserName())) {
       for (PrivilegeType privilegeType : PrivilegeType.values()) {
         userPrivilegesList.add(privilegeType.toString());
       }
       permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, userPrivilegesList);
-      result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+      result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
       result.setPermissionInfo(permissionInfo);
       return result;
     } else {
@@ -255,7 +325,7 @@ public class AuthorInfo {
       }
       permissionInfo.put(IoTDBConstant.COLUMN_ROLE, rolePrivileges);
       permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, userPrivilegesList);
-      result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+      result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
       result.setPermissionInfo(permissionInfo);
       return result;
     }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index d942abf4d1..758a6369b3 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -44,6 +44,7 @@ import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.rpc.thrift.ConfigIService;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCheckUserPrivilegesReq;
 import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeLocationResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -300,6 +301,12 @@ public class ConfigNodeRPCServiceProcessor implements ConfigIService.Iface {
     return configManager.login(req.getUserrname(), req.getPassword());
   }
 
+  @Override
+  public TSStatus checkUserPrivileges(TCheckUserPrivilegesReq req) throws TException {
+    return configManager.checkUserPrivileges(
+        req.getUsername(), req.getPaths(), req.getPermission());
+  }
+
   public void handleClientExit() {}
 
   // TODO: Interfaces for data operations
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
index 7d60ec6671..39bd2a5b87 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
@@ -33,6 +33,7 @@ import org.apache.iotdb.confignode.persistence.DataNodeInfo;
 import org.apache.iotdb.confignode.persistence.PartitionInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCheckUserPrivilegesReq;
 import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeLocationResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -547,21 +548,30 @@ public class ConfigNodeRPCServiceProcessorTest {
     userList.add("root");
     userList.add("tempuser0");
     userList.add("tempuser1");
+
     List<String> roleList = new ArrayList<>();
     roleList.add("temprole0");
     roleList.add("temprole1");
+
     TAuthorizerReq authorizerReq;
     TAuthorizerResp authorizerResp;
+    TCheckUserPrivilegesReq checkUserPrivilegesReq;
+
     Set<Integer> privilegeList = new HashSet<>();
     privilegeList.add(PrivilegeType.DELETE_USER.ordinal());
     privilegeList.add(PrivilegeType.CREATE_USER.ordinal());
+
     Set<Integer> revokePrivilege = new HashSet<>();
     revokePrivilege.add(PrivilegeType.DELETE_USER.ordinal());
+
     Map<String, List<String>> permissionInfo;
     List<String> privilege = new ArrayList<>();
     privilege.add("root : CREATE_USER");
     privilege.add("root : CREATE_USER");
 
+    List<String> paths = new ArrayList<>();
+    paths.add("root.ln");
+
     cleanUserAndRole();
 
     // create user
@@ -580,6 +590,12 @@ public class ConfigNodeRPCServiceProcessorTest {
     status = processor.operatePermission(authorizerReq);
     Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
 
+    // check user privileges
+    checkUserPrivilegesReq =
+        new TCheckUserPrivilegesReq("tempuser0", paths, PrivilegeType.DELETE_USER.ordinal());
+    status = processor.checkUserPrivileges(checkUserPrivilegesReq);
+    Assert.assertEquals(TSStatusCode.NO_PERMISSION_ERROR.getStatusCode(), status.getCode());
+
     // drop user
     authorizerReq =
         new TAuthorizerReq(
@@ -670,6 +686,12 @@ public class ConfigNodeRPCServiceProcessorTest {
     status = processor.operatePermission(authorizerReq);
     Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
 
+    // check user privileges
+    checkUserPrivilegesReq =
+        new TCheckUserPrivilegesReq("tempuser0", paths, PrivilegeType.DELETE_USER.ordinal());
+    status = processor.checkUserPrivileges(checkUserPrivilegesReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
     // grant role
     authorizerReq =
         new TAuthorizerReq(
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 3749e87d58..4d25e159ca 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -18,17 +18,20 @@
  */
 package org.apache.iotdb.db.auth;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
-import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.AuthorizerManager;
 import org.apache.iotdb.db.auth.entity.PrivilegeType;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.metadata.path.PartialPath;
+import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class AuthorityChecker {
@@ -79,16 +82,58 @@ public class AuthorityChecker {
     return true;
   }
 
+  /**
+   * check permission(datanode to confignode).
+   *
+   * @param username username
+   * @param paths paths in List structure
+   * @param type Statement Type
+   * @param targetUser target user
+   * @return if permission-check is passed
+   */
+  public static boolean checkPermission(
+      String username, List<? extends PartialPath> paths, StatementType type, String targetUser) {
+    if (SUPER_USER.equals(username)) {
+      return true;
+    }
+
+    int permission = translateToPermissionId(type);
+    if (permission == -1) {
+      return false;
+    } else if (permission == PrivilegeType.MODIFY_PASSWORD.ordinal()
+        && username.equals(targetUser)) {
+      // a user can modify his own password
+      return true;
+    }
+
+    List<String> allPath = new ArrayList<>();
+    if (paths != null && !paths.isEmpty()) {
+      for (PartialPath path : paths) {
+        allPath.add(path == null ? IoTDBConstant.PATH_ROOT : path.getFullPath());
+      }
+    } else {
+      allPath.add(IoTDBConstant.PATH_ROOT);
+    }
+
+    TSStatus status = AuthorizerManager.getInstance().checkPath(username, allPath, permission);
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
   private static boolean checkOnePath(String username, PartialPath path, int permission)
       throws AuthException {
-    IAuthorizer authorizer = BasicAuthorizer.getInstance();
+    AuthorizerManager authorizerManager = AuthorizerManager.getInstance();
     try {
       String fullPath = path == null ? IoTDBConstant.PATH_ROOT : path.getFullPath();
-      if (authorizer.checkUserPrivileges(username, fullPath, permission)) {
+      if (authorizerManager.checkUserPrivileges(username, fullPath, permission)) {
         return true;
       }
     } catch (AuthException e) {
       logger.error("Error occurs when checking the seriesPath {} for user {}", path, username, e);
+      throw new AuthException(e);
     }
     return false;
   }
@@ -177,4 +222,89 @@ public class AuthorityChecker {
         return -1;
     }
   }
+
+  private static int translateToPermissionId(StatementType type) {
+    switch (type) {
+      case GRANT_ROLE_PRIVILEGE:
+        return PrivilegeType.GRANT_ROLE_PRIVILEGE.ordinal();
+      case CREATE_ROLE:
+        return PrivilegeType.CREATE_ROLE.ordinal();
+      case CREATE_USER:
+        return PrivilegeType.CREATE_USER.ordinal();
+      case MODIFY_PASSWORD:
+        return PrivilegeType.MODIFY_PASSWORD.ordinal();
+      case GRANT_USER_PRIVILEGE:
+        return PrivilegeType.GRANT_USER_PRIVILEGE.ordinal();
+      case REVOKE_ROLE_PRIVILEGE:
+        return PrivilegeType.REVOKE_ROLE_PRIVILEGE.ordinal();
+      case REVOKE_USER_PRIVILEGE:
+        return PrivilegeType.REVOKE_USER_PRIVILEGE.ordinal();
+      case GRANT_USER_ROLE:
+        return PrivilegeType.GRANT_USER_ROLE.ordinal();
+      case DELETE_USER:
+        return PrivilegeType.DELETE_USER.ordinal();
+      case DELETE_ROLE:
+        return PrivilegeType.DELETE_ROLE.ordinal();
+      case REVOKE_USER_ROLE:
+        return PrivilegeType.REVOKE_USER_ROLE.ordinal();
+      case SET_STORAGE_GROUP:
+        return PrivilegeType.SET_STORAGE_GROUP.ordinal();
+      case DELETE_STORAGE_GROUP:
+        return PrivilegeType.DELETE_STORAGE_GROUP.ordinal();
+      case CREATE_TIMESERIES:
+      case CREATE_ALIGNED_TIMESERIES:
+        return PrivilegeType.CREATE_TIMESERIES.ordinal();
+      case DELETE_TIMESERIES:
+      case DELETE:
+      case DROP_INDEX:
+        return PrivilegeType.DELETE_TIMESERIES.ordinal();
+      case SHOW:
+      case QUERY:
+      case GROUP_BY_TIME:
+      case QUERY_INDEX:
+      case AGGREGATION:
+      case UDAF:
+      case UDTF:
+      case LAST:
+      case FILL:
+      case GROUP_BY_FILL:
+      case SELECT_INTO:
+        return PrivilegeType.READ_TIMESERIES.ordinal();
+      case INSERT:
+      case LOAD_DATA:
+      case CREATE_INDEX:
+      case BATCH_INSERT:
+      case BATCH_INSERT_ONE_DEVICE:
+      case BATCH_INSERT_ROWS:
+      case MULTI_BATCH_INSERT:
+        return PrivilegeType.INSERT_TIMESERIES.ordinal();
+      case LIST_ROLE:
+      case LIST_ROLE_USERS:
+      case LIST_ROLE_PRIVILEGE:
+        return PrivilegeType.LIST_ROLE.ordinal();
+      case LIST_USER:
+      case LIST_USER_ROLES:
+      case LIST_USER_PRIVILEGE:
+        return PrivilegeType.LIST_USER.ordinal();
+      case CREATE_FUNCTION:
+        return PrivilegeType.CREATE_FUNCTION.ordinal();
+      case DROP_FUNCTION:
+        return PrivilegeType.DROP_FUNCTION.ordinal();
+      case CREATE_TRIGGER:
+        return PrivilegeType.CREATE_TRIGGER.ordinal();
+      case DROP_TRIGGER:
+        return PrivilegeType.DROP_TRIGGER.ordinal();
+      case START_TRIGGER:
+        return PrivilegeType.START_TRIGGER.ordinal();
+      case STOP_TRIGGER:
+        return PrivilegeType.STOP_TRIGGER.ordinal();
+      case CREATE_CONTINUOUS_QUERY:
+        return PrivilegeType.CREATE_CONTINUOUS_QUERY.ordinal();
+      case DROP_CONTINUOUS_QUERY:
+        return PrivilegeType.DROP_CONTINUOUS_QUERY.ordinal();
+      default:
+        logger.error("Unrecognizable operator type ({}) for AuthorityChecker.", type);
+        return -1;
+    }
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/AuthorizerManager.java b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/AuthorizerManager.java
index 37fc1a5c2b..4a6a3f07ff 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/AuthorizerManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/AuthorizerManager.java
@@ -22,14 +22,20 @@ package org.apache.iotdb.db.auth.authorizer;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
+import org.apache.iotdb.confignode.rpc.thrift.TCheckUserPrivilegesReq;
 import org.apache.iotdb.confignode.rpc.thrift.TLoginReq;
 import org.apache.iotdb.db.auth.AuthException;
+import org.apache.iotdb.db.auth.AuthorityChecker;
 import org.apache.iotdb.db.auth.entity.Role;
 import org.apache.iotdb.db.auth.entity.User;
+import org.apache.iotdb.db.conf.OperationType;
 import org.apache.iotdb.db.mpp.execution.config.ConfigTaskResult;
+import org.apache.iotdb.db.mpp.sql.statement.Statement;
+import org.apache.iotdb.db.mpp.sql.statement.sys.AuthorStatement;
 import org.apache.iotdb.db.query.control.SessionManager;
 import org.apache.iotdb.db.query.control.SessionTimeoutManager;
 import org.apache.iotdb.db.service.basic.BasicOpenSessionResp;
+import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.service.rpc.thrift.TSProtocolVersion;
 
@@ -42,6 +48,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static org.apache.iotdb.db.utils.ErrorHandlingUtils.onNPEOrUnexpectedException;
+
 public class AuthorizerManager implements IAuthorizer {
 
   private static final Logger logger = LoggerFactory.getLogger(AuthorizerManager.class);
@@ -254,4 +262,40 @@ public class AuthorizerManager implements IAuthorizer {
     SessionTimeoutManager.getInstance().register(sessionId);
     return openSessionResp.sessionId(sessionId);
   }
+
+  /** Check whether specific Session has the authorization to given plan. */
+  public TSStatus checkAuthority(Statement statement, long sessionId) {
+    try {
+      if (!checkAuthorization(statement, sessionManager.getUsername(sessionId))) {
+        return RpcUtils.getStatus(
+            TSStatusCode.NO_PERMISSION_ERROR,
+            "No permissions for this operation " + statement.getType());
+      }
+    } catch (AuthException e) {
+      logger.warn("meet error while checking authorization.", e);
+      return RpcUtils.getStatus(TSStatusCode.UNINITIALIZED_AUTH_ERROR, e.getMessage());
+    } catch (Exception e) {
+      return onNPEOrUnexpectedException(
+          e, OperationType.CHECK_AUTHORITY, TSStatusCode.EXECUTE_STATEMENT_ERROR);
+    }
+    return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
+  }
+
+  /** Check whether specific user has the authorization to given plan. */
+  public boolean checkAuthorization(Statement statement, String username) throws AuthException {
+    if (!statement.isAuthenticationRequired()) {
+      return true;
+    }
+    String targetUser = null;
+    if (statement instanceof AuthorStatement) {
+      targetUser = ((AuthorStatement) statement).getUserName();
+    }
+    return AuthorityChecker.checkPermission(
+        username, statement.getPaths(), statement.getType(), targetUser);
+  }
+
+  public TSStatus checkPath(String username, List<String> allPath, int permission) {
+    return clusterAuthorizer.checkUserPrivileges(
+        new TCheckUserPrivilegesReq(username, allPath, permission));
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/ClusterAuthorizer.java b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/ClusterAuthorizer.java
index 85ed49a992..183cc2f8d7 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/ClusterAuthorizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/ClusterAuthorizer.java
@@ -23,21 +23,29 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.BadNodeUrlException;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCheckUserPrivilegesReq;
 import org.apache.iotdb.confignode.rpc.thrift.TLoginReq;
 import org.apache.iotdb.db.client.ConfigNodeClient;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeader;
+import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
 import org.apache.iotdb.db.mpp.execution.config.ConfigTaskResult;
 import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
 import org.apache.iotdb.rpc.ConfigNodeConnectionException;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 import org.apache.iotdb.rpc.TSStatusCode;
-import org.apache.iotdb.tsfile.read.common.block.TsBlock;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.iotdb.tsfile.utils.Binary;
 
 import com.google.common.util.concurrent.SettableFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 public class ClusterAuthorizer {
 
@@ -78,7 +86,6 @@ public class ClusterAuthorizer {
   public SettableFuture<ConfigTaskResult> queryPermission(TAuthorizerReq authorizerReq) {
     SettableFuture<ConfigTaskResult> future = SettableFuture.create();
     ConfigNodeClient configNodeClient = null;
-    TsBlock tsBlock = null;
     TAuthorizerResp authorizerResp;
     try {
       configNodeClient = new ConfigNodeClient();
@@ -94,8 +101,34 @@ public class ClusterAuthorizer {
             authorizerResp.getStatus());
         future.setException(new StatementExecutionException(authorizerResp.getStatus()));
       } else {
-        // TODO: Construct result
-        future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS, tsBlock, null));
+        // build TSBlock
+        List<TSDataType> types = new ArrayList<>();
+        Map<String, List<String>> authorizerInfo = authorizerResp.getAuthorizerInfo();
+        for (int i = 0; i < authorizerInfo.size(); i++) {
+          types.add(TSDataType.TEXT);
+        }
+        TsBlockBuilder builder = new TsBlockBuilder(types);
+        List<ColumnHeader> headerList = new ArrayList<>();
+
+        for (String header : authorizerInfo.keySet()) {
+          headerList.add(new ColumnHeader(header, TSDataType.TEXT));
+        }
+        // The Time column will be ignored by the setting of ColumnHeader.
+        // So we can put a meaningless value here
+        for (String value : authorizerInfo.get(headerList.get(0).getColumnName())) {
+          builder.getTimeColumnBuilder().writeLong(0L);
+          builder.getColumnBuilder(0).writeBinary(new Binary(value));
+          builder.declarePosition();
+        }
+        for (int i = 1; i < headerList.size(); i++) {
+          for (String value : authorizerInfo.get(headerList.get(i).getColumnName())) {
+            builder.getColumnBuilder(i).writeBinary(new Binary(value));
+          }
+        }
+
+        DatasetHeader datasetHeader = new DatasetHeader(headerList, true);
+        future.set(
+            new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS, builder.build(), datasetHeader));
       }
     } catch (IoTDBConnectionException | BadNodeUrlException e) {
       LOGGER.error("Failed to connect to config node.");
@@ -129,4 +162,24 @@ public class ClusterAuthorizer {
     }
     return status;
   }
+
+  public TSStatus checkUserPrivileges(TCheckUserPrivilegesReq req) {
+    ConfigNodeClient configNodeClient = null;
+    TSStatus status = null;
+    try {
+      configNodeClient = new ConfigNodeClient();
+      // Send request to some API server
+      status = configNodeClient.checkUserPrivileges(req);
+    } catch (IoTDBConnectionException | BadNodeUrlException e) {
+      throw new ConfigNodeConnectionException("Couldn't connect config node");
+    } finally {
+      if (configNodeClient != null) {
+        configNodeClient.close();
+      }
+      if (status == null) {
+        status = new TSStatus();
+      }
+    }
+    return status;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
index 9069fe2d67..7464c0a48e 100644
--- a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
+++ b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.commons.utils.CommonUtils;
 import org.apache.iotdb.confignode.rpc.thrift.ConfigIService;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
 import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
+import org.apache.iotdb.confignode.rpc.thrift.TCheckUserPrivilegesReq;
 import org.apache.iotdb.confignode.rpc.thrift.TCountStorageGroupResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeLocationResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -365,4 +366,19 @@ public class ConfigNodeClient {
     }
     throw new IoTDBConnectionException(MSG_RECONNECTION_FAIL);
   }
+
+  public TSStatus checkUserPrivileges(TCheckUserPrivilegesReq req) throws IoTDBConnectionException {
+    for (int i = 0; i < RETRY_NUM; i++) {
+      try {
+        TSStatus status = client.checkUserPrivileges(req);
+        if (!updateConfigNodeLeader(status)) {
+          return status;
+        }
+      } catch (TException e) {
+        configLeader = null;
+      }
+      reconnect();
+    }
+    throw new IoTDBConnectionException(MSG_RECONNECTION_FAIL);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/Statement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/Statement.java
index fe3ee2a077..262430ecde 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/Statement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/Statement.java
@@ -19,9 +19,12 @@
 
 package org.apache.iotdb.db.mpp.sql.statement;
 
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.parser.ASTVisitor;
 
+import java.util.List;
+
 /**
  * This class is a superclass of all statements.
  *
@@ -55,4 +58,10 @@ public abstract class Statement extends StatementNode {
   public boolean isQuery() {
     return statementType == StatementType.QUERY;
   }
+
+  public boolean isAuthenticationRequired() {
+    return true;
+  }
+
+  public abstract List<? extends PartialPath> getPaths();
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/AggregationQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/AggregationQueryStatement.java
index 0e9f408636..8d370d42ee 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/AggregationQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/AggregationQueryStatement.java
@@ -80,6 +80,7 @@ public class AggregationQueryStatement extends QueryStatement {
     return deviceNameToAggregationsMap;
   }
 
+  @Override
   public DatasetHeader constructDatasetHeader() {
     List<ColumnHeader> columnHeaders = new ArrayList<>();
     // TODO: consider Aggregation
@@ -121,6 +122,7 @@ public class AggregationQueryStatement extends QueryStatement {
     }
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitAggregationQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/FillQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/FillQueryStatement.java
index da72b8e1d3..2662041ae9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/FillQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/FillQueryStatement.java
@@ -72,6 +72,7 @@ public class FillQueryStatement extends QueryStatement {
     }
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitFillQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByFillQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByFillQueryStatement.java
index b3d87aa5dd..c7a3c703f9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByFillQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByFillQueryStatement.java
@@ -42,6 +42,7 @@ public class GroupByFillQueryStatement extends GroupByQueryStatement {
     this.fillComponent = fillComponent;
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitGroupByFillQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByQueryStatement.java
index 5a3fbc937b..f7398a274a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/GroupByQueryStatement.java
@@ -47,12 +47,14 @@ public class GroupByQueryStatement extends AggregationQueryStatement {
     this.groupByTimeComponent = groupByTimeComponent;
   }
 
+  @Override
   public DatasetHeader constructDatasetHeader() {
     List<ColumnHeader> columnHeaders = new ArrayList<>();
     // TODO: consider GROUP BY
     return new DatasetHeader(columnHeaders, false);
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitGroupByQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertBaseStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertBaseStatement.java
index cd4e9ec890..38e4a05557 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertBaseStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertBaseStatement.java
@@ -22,6 +22,9 @@ import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
+import java.util.Collections;
+import java.util.List;
+
 public abstract class InsertBaseStatement extends Statement {
 
   /**
@@ -67,4 +70,9 @@ public abstract class InsertBaseStatement extends Statement {
   public void setAligned(boolean aligned) {
     isAligned = aligned;
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertMultiTabletsStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertMultiTabletsStatement.java
index 5b7aa98e9f..cb12ed1c57 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertMultiTabletsStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertMultiTabletsStatement.java
@@ -74,4 +74,13 @@ public class InsertMultiTabletsStatement extends InsertBaseStatement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitInsertMultiTablets(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> result = new ArrayList<>();
+    for (InsertTabletStatement insertTabletStatement : insertTabletStatementList) {
+      result.addAll(insertTabletStatement.getPaths());
+    }
+    return result;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowStatement.java
index 39f9a0ac56..ed06864b02 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowStatement.java
@@ -22,12 +22,14 @@ package org.apache.iotdb.db.mpp.sql.statement.crud;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.db.engine.StorageEngineV2;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -45,6 +47,16 @@ public class InsertRowStatement extends InsertBaseStatement {
     statementType = StatementType.INSERT;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> ret = new ArrayList<>();
+    for (String m : measurements) {
+      PartialPath fullPath = devicePath.concatNode(m);
+      ret.add(fullPath);
+    }
+    return ret;
+  }
+
   public long getTime() {
     return time;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsOfOneDeviceStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsOfOneDeviceStatement.java
index 71eccaa20d..1d8d610729 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsOfOneDeviceStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsOfOneDeviceStatement.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.mpp.sql.statement.crud;
 
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.db.engine.StorageEngineV2;
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
@@ -76,4 +77,14 @@ public class InsertRowsOfOneDeviceStatement extends InsertBaseStatement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitInsertRowsOfOneDevice(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> ret = new ArrayList<>();
+    for (String m : measurements) {
+      PartialPath fullPath = devicePath.concatNode(m);
+      ret.add(fullPath);
+    }
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsStatement.java
index d740a2290f..da5452fa2c 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertRowsStatement.java
@@ -74,4 +74,13 @@ public class InsertRowsStatement extends InsertBaseStatement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitInsertRows(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> result = new ArrayList<>();
+    for (InsertRowStatement insertRowStatement : insertRowStatementList) {
+      result.addAll(insertRowStatement.getPaths());
+    }
+    return result;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertStatement.java
index a85ebb8a32..db662cc1ca 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertStatement.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /** this class extends {@code Statement} and process insert statement. */
@@ -43,6 +44,16 @@ public class InsertStatement extends Statement {
     statementType = StatementType.INSERT;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> ret = new ArrayList<>();
+    for (String m : measurementList) {
+      PartialPath fullPath = device.concatNode(m);
+      ret.add(fullPath);
+    }
+    return ret;
+  }
+
   public PartialPath getDevice() {
     return device;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertTabletStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertTabletStatement.java
index 612d2f8463..a0d88e4d84 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertTabletStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/InsertTabletStatement.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.mpp.sql.statement.crud;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.db.engine.StorageEngine;
 import org.apache.iotdb.db.engine.StorageEngineV2;
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 import org.apache.iotdb.tsfile.utils.BitMap;
 
@@ -91,4 +92,14 @@ public class InsertTabletStatement extends InsertBaseStatement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitInsertTablet(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> ret = new ArrayList<>();
+    for (String m : measurements) {
+      PartialPath fullPath = devicePath.concatNode(m);
+      ret.add(fullPath);
+    }
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/LastQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/LastQueryStatement.java
index b62b8f296d..7829c9265d 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/LastQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/LastQueryStatement.java
@@ -40,6 +40,7 @@ public class LastQueryStatement extends QueryStatement {
     super(queryStatement);
   }
 
+  @Override
   public DatasetHeader constructDatasetHeader() {
     List<ColumnHeader> columnHeaders = new ArrayList<>();
     // TODO: consider LAST
@@ -66,6 +67,7 @@ public class LastQueryStatement extends QueryStatement {
     }
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitLastQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/QueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/QueryStatement.java
index b7626d1c07..3598218c5e 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/QueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/QueryStatement.java
@@ -103,6 +103,11 @@ public class QueryStatement extends Statement {
     this.statementType = StatementType.QUERY;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    return fromComponent.getPrefixPaths();
+  }
+
   public QueryStatement(QueryStatement another) {
     this.statementType = StatementType.QUERY;
     this.selectComponent = another.getSelectComponent();
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDAFQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDAFQueryStatement.java
index c8a31f588b..a9af777f96 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDAFQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDAFQueryStatement.java
@@ -90,6 +90,7 @@ public class UDAFQueryStatement extends QueryStatement {
     }
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitUDAFQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDTFQueryStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDTFQueryStatement.java
index b2fb9166ce..1dd39badb3 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDTFQueryStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/crud/UDTFQueryStatement.java
@@ -27,6 +27,7 @@ public class UDTFQueryStatement extends QueryStatement {
     super(queryStatement);
   }
 
+  @Override
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitUDTFQuery(this, context);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/AlterTimeSeriesStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/AlterTimeSeriesStatement.java
index 5a4386fe16..022fe48109 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/AlterTimeSeriesStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/AlterTimeSeriesStatement.java
@@ -24,6 +24,8 @@ import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -56,6 +58,11 @@ public class AlterTimeSeriesStatement extends Statement {
     statementType = StatementType.ALTER_TIMESERIES;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(path);
+  }
+
   public PartialPath getPath() {
     return path;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CountStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CountStatement.java
index 888dbed5f4..7191516cfd 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CountStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CountStatement.java
@@ -22,6 +22,9 @@ package org.apache.iotdb.db.mpp.sql.statement.metadata;
 import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * COUNT statement.
  *
@@ -44,4 +47,9 @@ public class CountStatement extends ShowStatement {
   public void setPartialPath(PartialPath partialPath) {
     this.partialPath = partialPath;
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(partialPath);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateAlignedTimeSeriesStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateAlignedTimeSeriesStatement.java
index 2ec0f1f2b4..25d5973791 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateAlignedTimeSeriesStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateAlignedTimeSeriesStatement.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.mpp.sql.statement.metadata;
 
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
 import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
@@ -27,6 +28,9 @@ import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -41,6 +45,9 @@ import java.util.Map;
  */
 public class CreateAlignedTimeSeriesStatement extends Statement {
 
+  private static final Logger logger =
+      LoggerFactory.getLogger(CreateAlignedTimeSeriesStatement.class);
+
   private PartialPath devicePath;
   private List<String> measurements = new ArrayList<>();
   private List<TSDataType> dataTypes = new ArrayList<>();
@@ -56,6 +63,19 @@ public class CreateAlignedTimeSeriesStatement extends Statement {
     statementType = StatementType.CREATE_ALIGNED_TIMESERIES;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    List<PartialPath> paths = new ArrayList<>();
+    for (String measurement : measurements) {
+      try {
+        paths.add(new PartialPath(devicePath.getFullPath(), measurement));
+      } catch (IllegalPathException e) {
+        logger.error("Failed to get paths of CreateAlignedTimeSeriesStatement. ", e);
+      }
+    }
+    return paths;
+  }
+
   public PartialPath getDevicePath() {
     return devicePath;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateTimeSeriesStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateTimeSeriesStatement.java
index c875262e17..2305814acf 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateTimeSeriesStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/CreateTimeSeriesStatement.java
@@ -27,6 +27,8 @@ import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -54,6 +56,11 @@ public class CreateTimeSeriesStatement extends Statement {
     statementType = StatementType.CREATE_TIMESERIES;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(path);
+  }
+
   public PartialPath getPath() {
     return path;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SchemaFetchStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SchemaFetchStatement.java
index dbe7ca53f3..71e5a2716a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SchemaFetchStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SchemaFetchStatement.java
@@ -20,11 +20,14 @@
 package org.apache.iotdb.db.mpp.sql.statement.metadata;
 
 import org.apache.iotdb.commons.partition.SchemaPartition;
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.List;
+
 public class SchemaFetchStatement extends Statement {
 
   private PathPatternTree patternTree;
@@ -53,4 +56,9 @@ public class SchemaFetchStatement extends Statement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitSchemaFetch(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return patternTree.splitToPathList();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SetStorageGroupStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SetStorageGroupStatement.java
index f05d70b59c..c99e40b67a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SetStorageGroupStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/SetStorageGroupStatement.java
@@ -26,6 +26,9 @@ import org.apache.iotdb.db.mpp.sql.statement.IConfigStatement;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.Collections;
+import java.util.List;
+
 public class SetStorageGroupStatement extends Statement implements IConfigStatement {
   private PartialPath storageGroupPath;
 
@@ -51,4 +54,11 @@ public class SetStorageGroupStatement extends Statement implements IConfigStatem
   public QueryType getQueryType() {
     return QueryType.WRITE;
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return storageGroupPath != null
+        ? Collections.singletonList(storageGroupPath)
+        : Collections.emptyList();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowDevicesStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowDevicesStatement.java
index 74a861e36e..909458101f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowDevicesStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowDevicesStatement.java
@@ -22,6 +22,9 @@ package org.apache.iotdb.db.mpp.sql.statement.metadata;
 import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * SHOW DEVICES statement.
  *
@@ -55,4 +58,9 @@ public class ShowDevicesStatement extends ShowStatement {
   public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
     return visitor.visitShowDevices(this, context);
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(pathPattern);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStatement.java
index 6baad7ad00..71030bcbdb 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStatement.java
@@ -19,9 +19,13 @@
 
 package org.apache.iotdb.db.mpp.sql.statement.metadata;
 
+import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.sql.constant.StatementType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 
+import java.util.Collections;
+import java.util.List;
+
 public class ShowStatement extends Statement {
 
   int limit = 0;
@@ -34,6 +38,11 @@ public class ShowStatement extends Statement {
     statementType = StatementType.SHOW;
   }
 
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
+
   public int getLimit() {
     return limit;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStorageGroupStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStorageGroupStatement.java
index efb57c57a1..30df19639f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStorageGroupStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/metadata/ShowStorageGroupStatement.java
@@ -24,6 +24,9 @@ import org.apache.iotdb.db.mpp.sql.analyze.QueryType;
 import org.apache.iotdb.db.mpp.sql.statement.IConfigStatement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * SHOW STORAGE GROUP statement
  *
@@ -53,4 +56,9 @@ public class ShowStorageGroupStatement extends ShowStatement implements IConfigS
   public QueryType getQueryType() {
     return QueryType.READ;
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(pathPattern);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/sys/AuthorStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/sys/AuthorStatement.java
index 671f36717c..7d000b6599 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/sys/AuthorStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/statement/sys/AuthorStatement.java
@@ -26,6 +26,9 @@ import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.StatementVisitor;
 import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
 
+import java.util.Collections;
+import java.util.List;
+
 public class AuthorStatement extends Statement implements IConfigStatement {
 
   private final AuthorOperator.AuthorType authorType;
@@ -44,7 +47,60 @@ public class AuthorStatement extends Statement implements IConfigStatement {
   public AuthorStatement(AuthorOperator.AuthorType type) {
     super();
     authorType = type;
-    statementType = StatementType.AUTHOR;
+    switch (authorType) {
+      case DROP_ROLE:
+        this.setType(StatementType.DELETE_ROLE);
+        break;
+      case DROP_USER:
+        this.setType(StatementType.DELETE_USER);
+        break;
+      case GRANT_ROLE:
+        this.setType(StatementType.GRANT_ROLE_PRIVILEGE);
+        break;
+      case GRANT_USER:
+        this.setType(StatementType.GRANT_USER_PRIVILEGE);
+        break;
+      case CREATE_ROLE:
+        this.setType(StatementType.CREATE_ROLE);
+        break;
+      case CREATE_USER:
+        this.setType(StatementType.CREATE_USER);
+        break;
+      case REVOKE_ROLE:
+        this.setType(StatementType.REVOKE_ROLE_PRIVILEGE);
+        break;
+      case REVOKE_USER:
+        this.setType(StatementType.REVOKE_USER_PRIVILEGE);
+        break;
+      case UPDATE_USER:
+        this.setType(StatementType.MODIFY_PASSWORD);
+        break;
+      case GRANT_ROLE_TO_USER:
+        this.setType(StatementType.GRANT_ROLE_PRIVILEGE);
+        break;
+      case REVOKE_ROLE_FROM_USER:
+        this.setType(StatementType.REVOKE_USER_ROLE);
+        break;
+      case LIST_USER_PRIVILEGE:
+        this.setType(StatementType.LIST_USER_PRIVILEGE);
+        break;
+      case LIST_ROLE_PRIVILEGE:
+        this.setType(StatementType.LIST_ROLE_PRIVILEGE);
+        break;
+      case LIST_USER_ROLES:
+        this.setType(StatementType.LIST_USER_ROLES);
+        break;
+      case LIST_ROLE_USERS:
+        this.setType(StatementType.LIST_ROLE_USERS);
+        break;
+      case LIST_USER:
+        this.setType(StatementType.LIST_USER);
+        break;
+      case LIST_ROLE:
+        this.setType(StatementType.LIST_ROLE);
+        break;
+      default:
+    }
   }
 
   /**
@@ -145,4 +201,9 @@ public class AuthorStatement extends Statement implements IConfigStatement {
     }
     return queryType;
   }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return nodeName != null ? Collections.singletonList(nodeName) : Collections.emptyList();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
index 47647e05cf..75a1eb67db 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
@@ -270,6 +270,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
         StatementGenerator.createStatement(
             statement, SESSION_MANAGER.getZoneId(req.getSessionId()));
 
+    // permission check
+    TSStatus status = AuthorizerManager.getInstance().checkAuthority(s, req.sessionId);
+    if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      return RpcUtils.getTSExecuteStatementResp(status);
+    }
+
     QUERY_FREQUENCY_RECORDER.incrementAndGet();
     AUDIT_LOGGER.debug("Session {} execute Query: {}", req.sessionId, statement);
 
@@ -377,6 +383,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -388,9 +400,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -420,6 +429,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       InsertRowsOfOneDeviceStatement statement =
           (InsertRowsOfOneDeviceStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -431,9 +446,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -463,6 +475,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       InsertRowsOfOneDeviceStatement statement =
           (InsertRowsOfOneDeviceStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -474,9 +492,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -502,6 +517,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -513,9 +534,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = SESSION_MANAGER.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -536,6 +554,13 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertMultiTabletsStatement statement =
           (InsertMultiTabletsStatement) StatementGenerator.createStatement(req);
+
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -547,9 +572,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -571,6 +593,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       InsertTabletStatement statement =
           (InsertTabletStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -582,9 +610,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = SESSION_MANAGER.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -612,6 +637,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
 
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
           COORDINATOR.execute(
@@ -622,9 +653,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
@@ -747,6 +775,12 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
 
+      // permission check
+      TSStatus status = AuthorizerManager.getInstance().checkAuthority(statement, req.sessionId);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return status;
+      }
+
       // Step 2: call the coordinator
       long queryId = SESSION_MANAGER.requestQueryId(false);
       ExecutionResult result =
@@ -758,9 +792,6 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
               PARTITION_FETCHER,
               SCHEMA_FETCHER);
 
-      // TODO(INSERT) do this check in analyze
-      //      TSStatus status = serviceProvider.checkAuthority(insertTabletPlan,
-      // req.getSessionId());
       return result.status;
     } catch (Exception e) {
       return onNPEOrUnexpectedException(
diff --git a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index 78791a74bc..2466ddfdb3 100644
--- a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -98,6 +98,9 @@ public enum TSStatusCode {
   NOT_LOGIN_ERROR(601),
   NO_PERMISSION_ERROR(602),
   UNINITIALIZED_AUTH_ERROR(603),
+  EXECUTE_PERMISSION_EXCEPTION_ERROR(604),
+  USER_NOT_EXIST_ERROR(605),
+  ROLE_NOT_EXIST_ERROR(606),
 
   // cluster-related errors
   PARTITION_NOT_READY(700),
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift b/thrift-confignode/src/main/thrift/confignode.thrift
index 72055f34df..6442efa245 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -143,6 +143,12 @@ struct TLoginReq {
     2: required string password
 }
 
+struct TCheckUserPrivilegesReq{
+    1: required string username;
+    2: required list<string> paths
+    3: required i32 permission
+}
+
 service ConfigIService {
 
   /* DataNode */
@@ -188,4 +194,6 @@ service ConfigIService {
   TAuthorizerResp queryPermission(TAuthorizerReq req)
 
   common.TSStatus login(TLoginReq req)
+
+  common.TSStatus checkUserPrivileges(TCheckUserPrivilegesReq req)
 }
\ No newline at end of file