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/18 05:22:02 UTC

[iotdb] branch master updated: [IOTDB-2892] add PermissionInfoDataSet and test (#5492)

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 83ffc19622 [IOTDB-2892] add PermissionInfoDataSet and test (#5492)
83ffc19622 is described below

commit 83ffc19622e9748cea1c4eb19228d7e295b25aee
Author: 任宇华 <79...@users.noreply.github.com>
AuthorDate: Mon Apr 18 13:21:56 2022 +0800

    [IOTDB-2892] add PermissionInfoDataSet and test (#5492)
    
    * add PermissionInfoDataSet and PermissionQuery
    
    Co-authored-by: renyuhua <ry...@163.com>
---
 .../consensus/response/PermissionInfoDataSet.java  |  32 +-
 .../iotdb/confignode/manager/ConfigManager.java    |  19 +-
 .../apache/iotdb/confignode/manager/Manager.java   |  14 +-
 .../confignode/manager/PermissionManager.java      |   5 +
 .../persistence/AuthorInfoPersistence.java         | 129 ++++++-
 .../confignode/service/executor/PlanExecutor.java  |   4 +-
 .../server/ConfigNodeRPCServerProcessor.java       |  36 +-
 .../apache/iotdb/confignode/auth/AuthorTest.java   |  44 ---
 .../server/ConfigNodeRPCServerProcessorTest.java   | 375 +++++++++++++++++++++
 .../mpp/execution/config/AuthorizerConfigTask.java |  95 ++++++
 .../db/mpp/execution/config/ConfigExecution.java   |   3 +
 .../plan/node/metedata/write/AuthorNode.java       |   2 +-
 .../src/main/thrift/confignode.thrift              |   7 +
 13 files changed, 699 insertions(+), 66 deletions(-)

diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/PermissionInfoDataSet.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/PermissionInfoDataSet.java
index a60a2377fb..093f959c5f 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/PermissionInfoDataSet.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/response/PermissionInfoDataSet.java
@@ -19,8 +19,38 @@
 
 package org.apache.iotdb.confignode.consensus.response;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.consensus.common.DataSet;
 
+import java.util.List;
+import java.util.Map;
+
 public class PermissionInfoDataSet implements DataSet {
-  // TODO: Store the returned result
+
+  private TSStatus status;
+
+  private Map<String, List<String>> permissionInfo;
+
+  public PermissionInfoDataSet() {}
+
+  public PermissionInfoDataSet(TSStatus status, Map<String, List<String>> permissionInfo) {
+    this.status = status;
+    this.permissionInfo = permissionInfo;
+  }
+
+  public Map<String, List<String>> getPermissionInfo() {
+    return permissionInfo;
+  }
+
+  public void setPermissionInfo(Map<String, List<String>> permissionInfo) {
+    this.permissionInfo = permissionInfo;
+  }
+
+  public TSStatus getStatus() {
+    return status;
+  }
+
+  public void setStatus(TSStatus status) {
+    this.status = status;
+  }
 }
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 c605d418b5..43db8e07eb 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
@@ -24,6 +24,7 @@ import org.apache.iotdb.commons.partition.SeriesPartitionSlot;
 import org.apache.iotdb.confignode.consensus.response.DataNodeConfigurationDataSet;
 import org.apache.iotdb.confignode.consensus.response.DataNodesInfoDataSet;
 import org.apache.iotdb.confignode.consensus.response.DataPartitionDataSet;
+import org.apache.iotdb.confignode.consensus.response.PermissionInfoDataSet;
 import org.apache.iotdb.confignode.consensus.response.SchemaPartitionDataSet;
 import org.apache.iotdb.confignode.consensus.response.StorageGroupSchemaDataSet;
 import org.apache.iotdb.confignode.physical.PhysicalPlan;
@@ -276,9 +277,23 @@ public class ConfigManager implements Manager {
 
   @Override
   public TSStatus operatePermission(PhysicalPlan physicalPlan) {
-    if (physicalPlan instanceof AuthorPlan) {
+    TSStatus status = confirmLeader();
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       return permissionManager.operatePermission((AuthorPlan) physicalPlan);
+    } else {
+      return status;
+    }
+  }
+
+  @Override
+  public DataSet queryPermission(PhysicalPlan physicalPlan) {
+    TSStatus status = confirmLeader();
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      return permissionManager.queryPermission((AuthorPlan) physicalPlan);
+    } else {
+      PermissionInfoDataSet dataSet = new PermissionInfoDataSet();
+      dataSet.setStatus(status);
+      return dataSet;
     }
-    return ERROR_TSSTATUS;
   }
 }
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 291713002a..cae13c395e 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
@@ -126,10 +126,18 @@ public interface Manager {
   DataSet getOrCreateDataPartition(PhysicalPlan physicalPlan);
 
   /**
-   * operate permission
+   * Operate Permission
    *
-   * @param physicalPlan
-   * @return
+   * @param physicalPlan AuthorPlan
+   * @return status
    */
   TSStatus operatePermission(PhysicalPlan physicalPlan);
+
+  /**
+   * Query Permission
+   *
+   * @param physicalPlan AuthorPlan
+   * @return PermissionInfoDataSet
+   */
+  DataSet queryPermission(PhysicalPlan physicalPlan);
 }
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 9a9f8185e9..5e8f37f55a 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
@@ -20,6 +20,7 @@
 package org.apache.iotdb.confignode.manager;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.confignode.consensus.response.PermissionInfoDataSet;
 import org.apache.iotdb.confignode.physical.sys.AuthorPlan;
 
 public class PermissionManager {
@@ -34,6 +35,10 @@ public class PermissionManager {
     return getConsensusManager().write(authorPlan).getStatus();
   }
 
+  public PermissionInfoDataSet queryPermission(AuthorPlan authorPlan) {
+    return (PermissionInfoDataSet) getConsensusManager().read(authorPlan).getDataset();
+  }
+
   private ConsensusManager getConsensusManager() {
     return configNodeManager.getConsensusManager();
   }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfoPersistence.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfoPersistence.java
index 27677ec68e..77d4e2a926 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfoPersistence.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfoPersistence.java
@@ -19,17 +19,27 @@
 package org.apache.iotdb.confignode.persistence;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.confignode.consensus.response.PermissionInfoDataSet;
 import org.apache.iotdb.confignode.physical.PhysicalPlanType;
 import org.apache.iotdb.confignode.physical.sys.AuthorPlan;
 import org.apache.iotdb.db.auth.AuthException;
 import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
 import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
+import org.apache.iotdb.db.auth.entity.PathPrivilege;
+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.TSStatusCode;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class AuthorInfoPersistence {
@@ -42,7 +52,7 @@ public class AuthorInfoPersistence {
     try {
       authorizer = BasicAuthorizer.getInstance();
     } catch (AuthException e) {
-      logger.error("get user or role info failed", e);
+      logger.error("get user or role permissionInfo failed", e);
     }
   }
 
@@ -106,29 +116,128 @@ public class AuthorInfoPersistence {
     return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
   }
 
-  /** TODO: Construct the query result as a DataSet and return it */
-  public PermissionInfoDataSet executeListRole(AuthorPlan plan) throws AuthException {
-    return null;
+  public PermissionInfoDataSet executeListRole() throws AuthException {
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    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.setPermissionInfo(permissionInfo);
+    return result;
   }
 
-  public PermissionInfoDataSet executeListUser(AuthorPlan plan) throws AuthException {
-    return null;
+  public PermissionInfoDataSet executeListUser() throws AuthException {
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    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.setPermissionInfo(permissionInfo);
+    return result;
   }
 
   public PermissionInfoDataSet executeListRoleUsers(AuthorPlan plan) throws AuthException {
-    return null;
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    Role role = authorizer.getRole(plan.getRoleName());
+    if (role == null) {
+      throw new AuthException("No such role : " + plan.getRoleName());
+    }
+    List<String> roleUsersList = new ArrayList<>();
+    List<String> userList = authorizer.listAllUsers();
+    for (String userN : userList) {
+      User userObj = authorizer.getUser(userN);
+      if (userObj != null && userObj.hasRole(plan.getRoleName())) {
+        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.setPermissionInfo(permissionInfo);
+    return result;
   }
 
   public PermissionInfoDataSet executeListUserRoles(AuthorPlan plan) throws AuthException {
-    return null;
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    User user = authorizer.getUser(plan.getUserName());
+    if (user == null) {
+      throw new AuthException("No such user : " + plan.getUserName());
+    }
+    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.setPermissionInfo(permissionInfo);
+    return result;
   }
 
   public PermissionInfoDataSet executeListRolePrivileges(AuthorPlan plan) throws AuthException {
-    return null;
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    Role role = authorizer.getRole(plan.getRoleName());
+    if (role == null) {
+      throw new AuthException("No such role : " + plan.getRoleName());
+    }
+    List<String> rolePrivilegesList = new ArrayList<>();
+    for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
+      if (plan.getNodeName().equals("")
+          || AuthUtils.pathBelongsTo(plan.getNodeName(), pathPrivilege.getPath())) {
+        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.setPermissionInfo(permissionInfo);
+    return result;
   }
 
   public PermissionInfoDataSet executeListUserPrivileges(AuthorPlan plan) throws AuthException {
-    return null;
+    PermissionInfoDataSet result = new PermissionInfoDataSet();
+    User user = authorizer.getUser(plan.getUserName());
+    if (user == null) {
+      throw new AuthException("No such user : " + plan.getUserName());
+    }
+    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.setPermissionInfo(permissionInfo);
+      return result;
+    } else {
+      List<String> rolePrivileges = new ArrayList<>();
+      for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
+        if (plan.getNodeName().equals("")
+            || AuthUtils.pathBelongsTo(plan.getNodeName(), pathPrivilege.getPath())) {
+          rolePrivileges.add("");
+          userPrivilegesList.add(pathPrivilege.toString());
+        }
+      }
+      for (String roleN : user.getRoleList()) {
+        Role role = authorizer.getRole(roleN);
+        if (roleN == null) {
+          continue;
+        }
+        for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
+          if (plan.getNodeName().equals("")
+              || AuthUtils.pathBelongsTo(plan.getNodeName(), pathPrivilege.getPath())) {
+            rolePrivileges.add(roleN);
+            userPrivilegesList.add(pathPrivilege.toString());
+          }
+        }
+      }
+      permissionInfo.put(IoTDBConstant.COLUMN_ROLE, rolePrivileges);
+      permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, userPrivilegesList);
+      result.setStatus(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
+      result.setPermissionInfo(permissionInfo);
+      return result;
+    }
   }
 
   private static class AuthorInfoPersistenceHolder {
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/executor/PlanExecutor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/executor/PlanExecutor.java
index 85d11bfa14..8e5a34d47c 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/executor/PlanExecutor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/executor/PlanExecutor.java
@@ -68,9 +68,9 @@ public class PlanExecutor {
       case GetOrCreateSchemaPartition:
         return partitionInfoPersistence.getSchemaPartition((GetOrCreateSchemaPartitionPlan) plan);
       case LIST_USER:
-        return authorInfoPersistence.executeListUser((AuthorPlan) plan);
+        return authorInfoPersistence.executeListUser();
       case LIST_ROLE:
-        return authorInfoPersistence.executeListRole((AuthorPlan) plan);
+        return authorInfoPersistence.executeListRole();
       case LIST_USER_PRIVILEGE:
         return authorInfoPersistence.executeListUserPrivileges((AuthorPlan) plan);
       case LIST_ROLE_PRIVILEGE:
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessor.java
index 15ef51437f..af6647c3b7 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessor.java
@@ -25,6 +25,7 @@ import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
 import org.apache.iotdb.confignode.consensus.response.DataNodeConfigurationDataSet;
 import org.apache.iotdb.confignode.consensus.response.DataNodesInfoDataSet;
 import org.apache.iotdb.confignode.consensus.response.DataPartitionDataSet;
+import org.apache.iotdb.confignode.consensus.response.PermissionInfoDataSet;
 import org.apache.iotdb.confignode.consensus.response.SchemaPartitionDataSet;
 import org.apache.iotdb.confignode.consensus.response.StorageGroupSchemaDataSet;
 import org.apache.iotdb.confignode.manager.ConfigManager;
@@ -37,6 +38,7 @@ import org.apache.iotdb.confignode.physical.sys.RegisterDataNodePlan;
 import org.apache.iotdb.confignode.physical.sys.SetStorageGroupPlan;
 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.TDataNodeMessageResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterResp;
@@ -50,6 +52,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TSetTTLReq;
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchemaResp;
 import org.apache.iotdb.db.auth.AuthException;
 import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
+import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
 
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
@@ -184,14 +187,16 @@ public class ConfigNodeRPCServerProcessor implements ConfigIService.Iface {
 
   @Override
   public TSStatus operatePermission(TAuthorizerReq req) throws TException {
-    if (req.getAuthorType() < 0 || req.getAuthorType() >= PhysicalPlanType.values().length) {
-      throw new IndexOutOfBoundsException("Invalid ordinal");
+    if (req.getAuthorType() < 0
+        || req.getAuthorType() >= AuthorOperator.AuthorType.values().length) {
+      throw new IndexOutOfBoundsException("Invalid Author Type ordinal");
     }
     AuthorPlan plan = null;
     try {
       plan =
           new AuthorPlan(
-              PhysicalPlanType.values()[req.getAuthorType()],
+              PhysicalPlanType.values()[
+                  req.getAuthorType() + PhysicalPlanType.AUTHOR.ordinal() + 1],
               req.getUserName(),
               req.getRoleName(),
               req.getPassword(),
@@ -204,6 +209,31 @@ public class ConfigNodeRPCServerProcessor implements ConfigIService.Iface {
     return configManager.operatePermission(plan);
   }
 
+  @Override
+  public TAuthorizerResp queryPermission(TAuthorizerReq req) throws TException {
+    if (req.getAuthorType() < 0
+        || req.getAuthorType() >= AuthorOperator.AuthorType.values().length) {
+      throw new IndexOutOfBoundsException("Invalid Author Type ordinal");
+    }
+    AuthorPlan plan = null;
+    try {
+      plan =
+          new AuthorPlan(
+              PhysicalPlanType.values()[
+                  req.getAuthorType() + PhysicalPlanType.AUTHOR.ordinal() + 1],
+              req.getUserName(),
+              req.getRoleName(),
+              req.getPassword(),
+              req.getNewPassword(),
+              req.getPermissions(),
+              req.getNodeName());
+    } catch (AuthException e) {
+      LOGGER.error(e.getMessage());
+    }
+    PermissionInfoDataSet dataSet = (PermissionInfoDataSet) configManager.queryPermission(plan);
+    return new TAuthorizerResp(dataSet.getStatus(), dataSet.getPermissionInfo());
+  }
+
   public void handleClientExit() {}
 
   // TODO: Interfaces for data operations
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/auth/AuthorTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/auth/AuthorTest.java
deleted file mode 100644
index 7d86edfabd..0000000000
--- a/confignode/src/test/java/org/apache/iotdb/confignode/auth/AuthorTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.iotdb.confignode.auth;
-
-import org.apache.iotdb.confignode.utils.ConfigNodeEnvironmentUtils;
-import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-
-import org.junit.After;
-import org.junit.Before;
-
-public class AuthorTest {
-
-  IAuthorizer authorizer;
-
-  @Before
-  public void setUp() throws Exception {
-    ConfigNodeEnvironmentUtils.envSetUp();
-    authorizer = BasicAuthorizer.getInstance();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    ConfigNodeEnvironmentUtils.cleanEnv();
-  }
-
-  // TODO: ADD TEST
-}
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessorTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessorTest.java
index 0aa164ccd0..939458a6fe 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessorTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/server/ConfigNodeRPCServerProcessorTest.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
+import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.commons.consensus.SchemaRegionId;
@@ -30,6 +31,8 @@ import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
 import org.apache.iotdb.confignode.persistence.DataNodeInfoPersistence;
 import org.apache.iotdb.confignode.persistence.PartitionInfoPersistence;
 import org.apache.iotdb.confignode.persistence.RegionInfoPersistence;
+import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
+import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeMessage;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeMessageResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRegisterReq;
@@ -42,9 +45,11 @@ import org.apache.iotdb.confignode.rpc.thrift.TSchemaPartitionResp;
 import org.apache.iotdb.confignode.rpc.thrift.TSetStorageGroupReq;
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchemaResp;
+import org.apache.iotdb.db.auth.entity.PrivilegeType;
 import org.apache.iotdb.db.exception.metadata.IllegalPathException;
 import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
+import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.PublicBAOS;
 
@@ -61,8 +66,10 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 public class ConfigNodeRPCServerProcessorTest {
@@ -489,4 +496,372 @@ public class ConfigNodeRPCServerProcessorTest {
         timePartitionSlotNum,
         dataPartitionResp.getDataPartitionMap());
   }
+
+  @Test
+  public void permissionTest() throws TException {
+    TSStatus status;
+
+    List<String> userList = new ArrayList<>();
+    userList.add("root");
+    userList.add("tempuser0");
+    userList.add("tempuser1");
+    List<String> roleList = new ArrayList<>();
+    roleList.add("temprole0");
+    roleList.add("temprole1");
+    TAuthorizerReq authorizerReq;
+    TAuthorizerResp authorizerResp;
+    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");
+
+    cleanUserAndRole();
+
+    // create user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.CREATE_USER.ordinal(),
+            "tempuser0",
+            "",
+            "passwd",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    authorizerReq.setUserName("tempuser1");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // drop user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.DROP_USER.ordinal(),
+            "tempuser1",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // list user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER.ordinal(), "", "", "", "", new HashSet<>(), "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    userList.remove("tempuser1");
+    Assert.assertEquals(
+        userList, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_USER));
+
+    // create role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.CREATE_ROLE.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    authorizerReq.setRoleName("temprole1");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // drop role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.DROP_ROLE.ordinal(),
+            "",
+            "temprole1",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // list role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_ROLE.ordinal(), "", "", "", "", new HashSet<>(), "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    roleList.remove("temprole1");
+    Assert.assertEquals(
+        roleList, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_ROLE));
+
+    // alter user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.UPDATE_USER.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "newpwd",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // grant user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.GRANT_USER.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "",
+            privilegeList,
+            "root.ln");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // grant role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.GRANT_ROLE.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            privilegeList,
+            "root.ln");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // grant role to user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.GRANT_ROLE_TO_USER.ordinal(),
+            "tempuser0",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // revoke user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.REVOKE_USER.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "",
+            revokePrivilege,
+            "root.ln");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // revoke role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.REVOKE_ROLE.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            revokePrivilege,
+            "root.ln");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // list privileges user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER_PRIVILEGE.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            "root.ln");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    Assert.assertEquals(
+        privilege, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_PRIVILEGE));
+
+    // list user privileges
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER_PRIVILEGE.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    Assert.assertEquals(
+        privilege, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_PRIVILEGE));
+
+    // list privileges role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "root.ln");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    privilege.remove(0);
+    Assert.assertEquals(
+        privilege, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_PRIVILEGE));
+
+    // list role privileges
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    Assert.assertEquals(
+        privilege, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_PRIVILEGE));
+
+    // list all role of user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER_ROLES.ordinal(),
+            "tempuser0",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    roleList.remove("temprole1");
+    Assert.assertEquals(
+        roleList, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_ROLE));
+
+    // list all user of role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_ROLE_USERS.ordinal(),
+            "",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    userList.remove("tempuser1");
+    userList.remove("root");
+    Assert.assertEquals(
+        userList, authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_USER));
+
+    // revoke role from user
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.REVOKE_ROLE_FROM_USER.ordinal(),
+            "tempuser0",
+            "temprole0",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    status = processor.operatePermission(authorizerReq);
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    // list root privileges
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER_PRIVILEGE.ordinal(),
+            "root",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    for (int i = 0; i < PrivilegeType.values().length; i++) {
+      Assert.assertEquals(
+          PrivilegeType.values()[i].toString(),
+          authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_PRIVILEGE).get(i));
+    }
+  }
+
+  private void cleanUserAndRole() throws TException {
+    TSStatus status;
+
+    // clean user
+    TAuthorizerReq authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_USER.ordinal(), "", "", "", "", new HashSet<>(), "");
+    TAuthorizerResp authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    List<String> allUsers = authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_USER);
+    for (String user : allUsers) {
+      if (!user.equals("root")) {
+        authorizerReq =
+            new TAuthorizerReq(
+                AuthorOperator.AuthorType.DROP_USER.ordinal(),
+                user,
+                "",
+                "",
+                "",
+                new HashSet<>(),
+                "");
+        status = processor.operatePermission(authorizerReq);
+        Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+      }
+    }
+
+    // clean role
+    authorizerReq =
+        new TAuthorizerReq(
+            AuthorOperator.AuthorType.LIST_ROLE.ordinal(), "", "", "", "", new HashSet<>(), "");
+    authorizerResp = processor.queryPermission(authorizerReq);
+    status = authorizerResp.getStatus();
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+
+    List<String> roleList = authorizerResp.getAuthorizerInfo().get(IoTDBConstant.COLUMN_ROLE);
+    for (String roleN : roleList) {
+      authorizerReq =
+          new TAuthorizerReq(
+              AuthorOperator.AuthorType.DROP_ROLE.ordinal(),
+              "",
+              roleN,
+              "",
+              "",
+              new HashSet<>(),
+              "");
+      status = processor.operatePermission(authorizerReq);
+      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
+    }
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/AuthorizerConfigTask.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/AuthorizerConfigTask.java
new file mode 100644
index 0000000000..9b27ad3b9d
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/AuthorizerConfigTask.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.execution.config;
+
+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.db.auth.AuthException;
+import org.apache.iotdb.db.client.ConfigNodeClient;
+import org.apache.iotdb.db.mpp.sql.planner.plan.node.metedata.write.AuthorNode;
+import org.apache.iotdb.db.mpp.sql.statement.sys.AuthorStatement;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.StatementExecutionException;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Locale;
+
+public class AuthorizerConfigTask implements IConfigTask {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizerConfigTask.class);
+
+  private AuthorStatement authorStatement;
+
+  public AuthorizerConfigTask(AuthorStatement authorStatement) {
+    this.authorStatement = authorStatement;
+  }
+
+  @Override
+  public ListenableFuture<Void> execute() {
+    SettableFuture<Void> future = SettableFuture.create();
+    ConfigNodeClient configNodeClient = null;
+    try {
+      // Construct request using statement
+      TAuthorizerReq req =
+          new TAuthorizerReq(
+              authorStatement.getAuthorType().ordinal(),
+              authorStatement.getUserName() == null ? "" : authorStatement.getUserName(),
+              authorStatement.getRoleName() == null ? "" : authorStatement.getRoleName(),
+              authorStatement.getPassWord() == null ? "" : authorStatement.getPassWord(),
+              authorStatement.getNewPassword() == null ? "" : authorStatement.getNewPassword(),
+              AuthorNode.strToPermissions(authorStatement.getPrivilegeList()),
+              authorStatement.getNodeName() == null
+                  ? ""
+                  : authorStatement.getNodeName().getFullPath());
+      configNodeClient = new ConfigNodeClient();
+      // Send request to some API server
+      TSStatus tsStatus = configNodeClient.operatePermission(req);
+      // Get response or throw exception
+      if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != tsStatus.getCode()) {
+        LOGGER.error(
+            "Failed to execute {} in config node, status is {}.",
+            authorStatement.getAuthorType().toString().toLowerCase(Locale.ROOT),
+            tsStatus);
+        future.setException(new StatementExecutionException(tsStatus));
+      } else {
+        future.set(null);
+      }
+    } catch (IoTDBConnectionException | BadNodeUrlException e) {
+      LOGGER.error("Failed to connect to config node.");
+      future.setException(e);
+    } catch (AuthException e) {
+      LOGGER.error("No such privilege {}.", authorStatement.getAuthorType());
+      future.setException(e);
+    } finally {
+      if (configNodeClient != null) {
+        configNodeClient.close();
+      }
+    }
+    // If the action is executed successfully, return the Future.
+    // If your operation is async, you can return the corresponding future directly.
+    return future;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/ConfigExecution.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/ConfigExecution.java
index 21afde5d29..7ceb542cef 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/ConfigExecution.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/config/ConfigExecution.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.db.mpp.execution.QueryStateMachine;
 import org.apache.iotdb.db.mpp.sql.analyze.QueryType;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 import org.apache.iotdb.db.mpp.sql.statement.metadata.SetStorageGroupStatement;
+import org.apache.iotdb.db.mpp.sql.statement.sys.AuthorStatement;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.exception.NotImplementedException;
@@ -149,6 +150,8 @@ public class ConfigExecution implements IQueryExecution {
       switch (statement.getType()) {
         case SET_STORAGE_GROUP:
           return new SetStorageGroupTask((SetStorageGroupStatement) statement);
+        case AUTHOR:
+          return new AuthorizerConfigTask((AuthorStatement) statement);
         default:
           throw new NotImplementedException();
       }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/metedata/write/AuthorNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/metedata/write/AuthorNode.java
index e50454c4b2..adcd0cfc06 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/metedata/write/AuthorNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/metedata/write/AuthorNode.java
@@ -248,7 +248,7 @@ public class AuthorNode extends PlanNode {
     throw new NotImplementedException("serializeAttributes of AuthorNode is not implemented");
   }
 
-  public Set<Integer> strToPermissions(String[] privilegeList) throws AuthException {
+  public static Set<Integer> strToPermissions(String[] privilegeList) throws AuthException {
     Set<Integer> result = new HashSet<>();
     if (privilegeList == null) {
       return result;
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift b/thrift-confignode/src/main/thrift/confignode.thrift
index a10709b414..5441b7f571 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -117,6 +117,11 @@ struct TAuthorizerReq {
   7: required string nodeName
 }
 
+struct TAuthorizerResp {
+    1: required common.TSStatus status
+    2: required map<string, list<string>> authorizerInfo
+}
+
 service ConfigIService {
 
   /* DataNode */
@@ -148,6 +153,8 @@ service ConfigIService {
   TDataPartitionResp getOrCreateDataPartition(TDataPartitionReq req)
 
   /* Authorize */
+
   common.TSStatus operatePermission(TAuthorizerReq req)
 
+  TAuthorizerResp queryPermission(TAuthorizerReq req)
 }
\ No newline at end of file