This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch auth
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/auth by this push:
new 878bb06ae18 Cl auth it (#11064)
878bb06ae18 is described below
commit 878bb06ae18c0975f44bc8b39d7d465371758f9b
Author: Colin Li <[email protected]>
AuthorDate: Wed Sep 6 22:20:38 2023 +0800
Cl auth it (#11064)
---
.../org/apache/iotdb/db/it/auth/IoTDBAuthIT.java | 250 +++++++++++++++++----
.../iotdb/confignode/persistence/AuthorInfo.java | 2 +-
.../org/apache/iotdb/db/auth/AuthorityChecker.java | 15 +-
.../iotdb/db/auth/ClusterAuthorityFetcher.java | 9 +-
.../iotdb/db/auth/AuthorizerManagerTest.java | 113 ++++++++++
.../org/apache/iotdb/commons/auth/entity/Role.java | 3 +
.../iotdb/commons/auth/user/BasicUserManager.java | 21 ++
7 files changed, 353 insertions(+), 60 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBAuthIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBAuthIT.java
index 7aa31c79060..f6a7fa7cf62 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBAuthIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBAuthIT.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.it.auth;
+import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -488,32 +489,41 @@ public class IoTDBAuthIT {
adminStmt.execute("GRANT READ_SCHEMA ON root.a.b TO USER user1");
adminStmt.execute("CREATE ROLE role1");
adminStmt.execute("GRANT READ_SCHEMA,WRITE_DATA ON root.a.b.c TO ROLE
role1");
- adminStmt.execute("GRANT READ_SCHEMA,WRITE_DATA ON root.d.b.c TO ROLE
role1");
- adminStmt.execute("GRANT role1 TO user1");
+ adminStmt.execute(
+ "GRANT READ_SCHEMA,WRITE_DATA ON root.d.b.c TO ROLE role1 WITH GRANT
OPTION");
+ adminStmt.execute("GRANT ROLE role1 TO user1");
- ResultSet resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER
user1");
+ ResultSet resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF USER
user1");
String ans =
- ",root.a.b : READ_SCHEMA"
- + ",\n"
- + "role1,root.a.b.c : WRITE_DATA READ_SCHEMA"
- + ",\n"
- + "role1,root.d.b.c : WRITE_DATA READ_SCHEMA"
- + ",\n";
+ ",root.a.b,READ_SCHEMA,false,\n"
+ + "role1,root.a.b.c,WRITE_DATA,false,\n"
+ + "role1,root.a.b.c,READ_SCHEMA,false,\n"
+ + "role1,root.d.b.c,READ_SCHEMA,true,\n"
+ + "role1,root.d.b.c,WRITE_DATA,true,\n";
try {
validateResultSet(resultSet, ans);
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER user1 ON
root.a.b.c");
- ans = "role1,root.a.b.c : WRITE_DATA READ_SCHEMA,\n";
- validateResultSet(resultSet, ans);
-
- adminStmt.execute("REVOKE role1 from user1");
+ adminStmt.execute("REVOKE ROLE role1 from user1");
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER user1");
- ans = ",root.a.b : READ_SCHEMA,\n";
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF USER user1");
+ ans = ",root.a.b,READ_SCHEMA,false,\n";
validateResultSet(resultSet, ans);
-
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER user1 ON
root.a.**");
- ans = ",root.a.b : READ_SCHEMA,\n";
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF USER root");
+ ans =
+ ",,MANAGE_USER,true,\n"
+ + ",,MANAGE_ROLE,true,\n"
+ + ",,USE_TRIGGER,true,\n"
+ + ",,USE_UDF,true,\n"
+ + ",,USE_CQ,true,\n"
+ + ",,USE_PIPE,true,\n"
+ + ",,EXTEND_TEMPLATE,true,\n"
+ + ",,MANAGE_DATABASE,true,\n"
+ + ",,MAINTAIN,true,\n"
+ + ",,AUDIT,true,\n"
+ + ",root.**,READ_DATA,true,\n"
+ + ",root.**,WRITE_DATA,true,\n"
+ + ",root.**,READ_SCHEMA,true,\n"
+ + ",root.**,WRITE_SCHEMA,true,\n";
validateResultSet(resultSet, ans);
} finally {
resultSet.close();
@@ -531,30 +541,24 @@ public class IoTDBAuthIT {
try {
adminStmt.execute("CREATE ROLE role1");
- ResultSet resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE
role1");
+ ResultSet resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF ROLE
role1");
String ans = "";
try {
// not granted list role privilege, should return empty
validateResultSet(resultSet, ans);
- adminStmt.execute("GRANT ROLE role1 PRIVILEGES READ_SCHEMA,WRITE_DATA
ON root.a.b.c");
- adminStmt.execute("GRANT ROLE role1 PRIVILEGES READ_SCHEMA,WRITE_DATA
ON root.d.b.c");
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1");
- ans = "root.a.b.c : WRITE_DATA READ_SCHEMA,\n" + "root.d.b.c :
WRITE_DATA READ_SCHEMA,\n";
- validateResultSet(resultSet, ans);
-
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1 ON
root.a.b.c");
- ans = "root.a.b.c : WRITE_DATA READ_SCHEMA,\n";
+ adminStmt.execute("GRANT READ_SCHEMA,WRITE_DATA ON root.a.b.c TO ROLE
role1");
+ adminStmt.execute(
+ "GRANT READ_SCHEMA,WRITE_DATA ON root.d.b.c TO ROLE role1 WITH
GRANT OPTION");
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF ROLE role1");
+ ans =
+
"role1,root.a.b.c,WRITE_DATA,false,\nrole1,root.a.b.c,READ_SCHEMA,false,\nrole1,root.d.b.c,READ_SCHEMA,true,\nrole1,root.d.b.c,WRITE_DATA,true,\n";
validateResultSet(resultSet, ans);
- adminStmt.execute("REVOKE ROLE role1 PRIVILEGES READ_SCHEMA,WRITE_DATA
ON root.a.b.c");
-
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1");
- ans = "root.d.b.c : WRITE_DATA READ_SCHEMA,\n";
- validateResultSet(resultSet, ans);
+ adminStmt.execute("REVOKE READ_SCHEMA,WRITE_DATA ON root.a.b.c FROM
ROLE role1");
- resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1 ON
root.a.b.c");
- ans = "";
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF ROLE role1");
+ ans = "role1,root.d.b.c,WRITE_DATA,true,\n" +
"role1,root.d.b.c,READ_SCHEMA,true,\n";
validateResultSet(resultSet, ans);
} finally {
resultSet.close();
@@ -579,19 +583,19 @@ public class IoTDBAuthIT {
adminStmt.execute("CREATE ROLE zhazha");
adminStmt.execute("CREATE ROLE hakase");
- adminStmt.execute("GRANT xijing TO chenduxiu");
- adminStmt.execute("GRANT dalao TO chenduxiu");
- adminStmt.execute("GRANT shenshi TO chenduxiu");
- adminStmt.execute("GRANT zhazha TO chenduxiu");
- adminStmt.execute("GRANT hakase TO chenduxiu");
+ adminStmt.execute("GRANT ROLE xijing TO chenduxiu");
+ adminStmt.execute("GRANT ROLE dalao TO chenduxiu");
+ adminStmt.execute("GRANT ROLE shenshi TO chenduxiu");
+ adminStmt.execute("GRANT ROLE zhazha TO chenduxiu");
+ adminStmt.execute("GRANT ROLE hakase TO chenduxiu");
ResultSet resultSet = adminStmt.executeQuery("LIST ROLE OF USER
chenduxiu");
String ans = "xijing,\n" + "dalao,\n" + "shenshi,\n" + "zhazha,\n" +
"hakase,\n";
try {
validateResultSet(resultSet, ans);
- adminStmt.execute("REVOKE dalao FROM chenduxiu");
- adminStmt.execute("REVOKE hakase FROM chenduxiu");
+ adminStmt.execute("REVOKE ROLE dalao FROM chenduxiu");
+ adminStmt.execute("REVOKE ROLE hakase FROM chenduxiu");
resultSet = adminStmt.executeQuery("LIST ROLE OF USER chenduxiu");
ans = "xijing,\n" + "shenshi,\n" + "zhazha,\n";
@@ -634,10 +638,10 @@ public class IoTDBAuthIT {
for (int i = 0; i < members.length - 1; i++) {
adminStmt.execute("CREATE USER " + members[i] + " 'a666666'");
- adminStmt.execute("GRANT dalao TO " + members[i]);
+ adminStmt.execute("GRANT ROLE dalao TO " + members[i]);
}
adminStmt.execute("CREATE USER RiverSky 'a2333333'");
- adminStmt.execute("GRANT zhazha TO RiverSky");
+ adminStmt.execute("GRANT ROLE zhazha TO RiverSky");
ResultSet resultSet = adminStmt.executeQuery("LIST USER OF ROLE dalao");
String ans =
@@ -662,7 +666,7 @@ public class IoTDBAuthIT {
ans = "RiverSky,\n";
validateResultSet(resultSet, ans);
- adminStmt.execute("REVOKE zhazha from RiverSky");
+ adminStmt.execute("REVOKE ROLE zhazha from RiverSky");
resultSet = adminStmt.executeQuery("LIST USER OF ROLE zhazha");
ans = "";
validateResultSet(resultSet, ans);
@@ -716,7 +720,7 @@ public class IoTDBAuthIT {
try {
Assert.assertThrows(SQLException.class, () -> userStmt.execute("LIST
USER"));
// with list user privilege
- adminStmt.execute("GRANT USER tempuser PRIVILEGES MANAGE_USER on
root.**");
+ adminStmt.execute("GRANT MANAGE_USER on root.** TO USER tempuser");
ResultSet resultSet = userStmt.executeQuery("LIST USER");
String ans =
"root,\n"
@@ -832,4 +836,158 @@ public class IoTDBAuthIT {
}
}
}
+
+ @Test
+ public void testGrantAndGrantOpt() throws SQLException {
+ // 1. CREATE USER1. USER2. USER3
+ Connection adminCon = EnvFactory.getEnv().getConnection();
+ Statement adminStmt = adminCon.createStatement();
+ adminStmt.execute("CREATE USER user1 'password'");
+ adminStmt.execute("CREATE USER user2 'password'");
+ adminStmt.execute("CREATE USER user3 'password'");
+ adminStmt.execute("CREATE ROLE testRole");
+ adminStmt.execute("GRANT MANAGE_DATABASE ON root.** TO ROLE testRole WITH
GRANT OPTION");
+ adminStmt.execute("GRANT READ_DATA ON root.t1.** TO ROLE testRole");
+ adminStmt.execute("GRANT READ_SCHEMA ON root.t3.t2.** TO ROLE testRole
WITH GRANT OPTION");
+
+ // 2. USER1 has all privileges on root.**
+ for (PrivilegeType item : PrivilegeType.values()) {
+ String sql = "GRANT %s on root.** to USER user1";
+ adminStmt.execute(String.format(sql, item.toString()));
+ }
+ // 3.admin lists privileges of user1
+ ResultSet resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF USER
user1");
+ String ans =
+ ",,MANAGE_USER,false,\n"
+ + ",,MANAGE_ROLE,false,\n"
+ + ",,USE_TRIGGER,false,\n"
+ + ",,USE_UDF,false,\n"
+ + ",,USE_CQ,false,\n"
+ + ",,USE_PIPE,false,\n"
+ + ",,EXTEND_TEMPLATE,false,\n"
+ + ",,MANAGE_DATABASE,false,\n"
+ + ",,MAINTAIN,false,\n"
+ + ",,AUDIT,false,\n"
+ + ",root.**,READ_DATA,false,\n"
+ + ",root.**,WRITE_DATA,false,\n"
+ + ",root.**,READ_SCHEMA,false,\n"
+ + ",root.**,WRITE_SCHEMA,false,\n";
+ validateResultSet(resultSet, ans);
+
+ // 4. USER2 has all privilegs on root.** with grant option;
+ for (PrivilegeType item : PrivilegeType.values()) {
+ String sql = "GRANT %s on root.** to USER user2 with grant option";
+ adminStmt.execute(String.format(sql, item.toString()));
+ }
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES OF USER user2");
+ ans =
+ ",,MANAGE_USER,true,\n"
+ + ",,MANAGE_ROLE,true,\n"
+ + ",,USE_TRIGGER,true,\n"
+ + ",,USE_UDF,true,\n"
+ + ",,USE_CQ,true,\n"
+ + ",,USE_PIPE,true,\n"
+ + ",,EXTEND_TEMPLATE,true,\n"
+ + ",,MANAGE_DATABASE,true,\n"
+ + ",,MAINTAIN,true,\n"
+ + ",,AUDIT,true,\n"
+ + ",root.**,READ_DATA,true,\n"
+ + ",root.**,WRITE_DATA,true,\n"
+ + ",root.**,READ_SCHEMA,true,\n"
+ + ",root.**,WRITE_SCHEMA,true,\n";
+ validateResultSet(resultSet, ans);
+
+ // now user1 has all privileges, user2 has all privileges with grant
option, user3 doesn't have
+ // privileges
+
+ // 5. Login user1 to list user2 privileges will success
+ // user1 cannot grant any privilegs to user3
+ try (Connection userCon = EnvFactory.getEnv().getConnection("user1",
"password");
+ Statement userStmt = userCon.createStatement()) {
+ try {
+ resultSet = userStmt.executeQuery("LIST PRIVILEGES OF USER user1");
+ ans =
+ ",,MANAGE_USER,false,\n"
+ + ",,MANAGE_ROLE,false,\n"
+ + ",,USE_TRIGGER,false,\n"
+ + ",,USE_UDF,false,\n"
+ + ",,USE_CQ,false,\n"
+ + ",,USE_PIPE,false,\n"
+ + ",,EXTEND_TEMPLATE,false,\n"
+ + ",,MANAGE_DATABASE,false,\n"
+ + ",,MAINTAIN,false,\n"
+ + ",,AUDIT,false,\n"
+ + ",root.**,READ_DATA,false,\n"
+ + ",root.**,WRITE_DATA,false,\n"
+ + ",root.**,READ_SCHEMA,false,\n"
+ + ",root.**,WRITE_SCHEMA,false,\n";
+ validateResultSet(resultSet, ans);
+ Assert.assertThrows(
+ SQLException.class,
+ () -> userStmt.execute("GRANT MANAGE_ROLE ON root.** TO USER
user3"));
+ Assert.assertThrows(
+ SQLException.class,
+ () -> userStmt.execute("REVOKE MANAGE_ROLE ON root.** FROM USER
user2"));
+ } finally {
+ userStmt.close();
+ }
+ }
+ // 6.Login user2 grant and revoke will success.
+ try (Connection userCon = EnvFactory.getEnv().getConnection("user2",
"password");
+ Statement userStmt = userCon.createStatement()) {
+ try {
+ resultSet = userStmt.executeQuery("LIST PRIVILEGES OF USER user1");
+ validateResultSet(resultSet, ans);
+ userStmt.execute("GRANT MANAGE_ROLE ON root.** TO USER user3");
+ resultSet = userStmt.executeQuery("LIST PRIVILEGES OF USER user3");
+ ans = ",,MANAGE_ROLE,false,\n";
+ validateResultSet(resultSet, ans);
+
+ userStmt.execute("REVOKE MANAGE_ROLE ON root.** FROM USER user1");
+ resultSet = userStmt.executeQuery("LIST PRIVILEGES OF USER user1");
+ ans =
+ ",,MANAGE_USER,false,\n"
+ + ",,USE_TRIGGER,false,\n"
+ + ",,USE_UDF,false,\n"
+ + ",,USE_CQ,false,\n"
+ + ",,USE_PIPE,false,\n"
+ + ",,EXTEND_TEMPLATE,false,\n"
+ + ",,MANAGE_DATABASE,false,\n"
+ + ",,MAINTAIN,false,\n"
+ + ",,AUDIT,false,\n"
+ + ",root.**,READ_DATA,false,\n"
+ + ",root.**,WRITE_DATA,false,\n"
+ + ",root.**,READ_SCHEMA,false,\n"
+ + ",root.**,WRITE_SCHEMA,false,\n";
+ validateResultSet(resultSet, ans);
+ } finally {
+ userStmt.close();
+ }
+ }
+ adminStmt.execute("GRANT ROLE testRole TO user3");
+ // now user has:
+ // 1. MANAGE_ROLE
+ // 2. MANAGE_DATABASE with grant option
+ // 3. READ_DATA on root.t1.**
+ // 4. READ_SCHEMA on root.t3.t2.**
+
+ try (Connection userCon = EnvFactory.getEnv().getConnection("user3",
"password");
+ Statement userStmt = userCon.createStatement()) {
+ try {
+ // because role's privilege
+ userStmt.execute("GRANT MANAGE_DATABASE ON root.** TO USER user1");
+ Assert.assertThrows(
+ SQLException.class,
+ () -> userStmt.execute("GRANT READ_DATA ON root.t1.** TO USER
user1"));
+ userStmt.execute("GRANT READ_SCHEMA ON root.t3.t2.t3 TO USER user1");
+ Assert.assertThrows(
+ SQLException.class,
+ () -> userStmt.execute("GRANT READ_DATA ON root.t1.t2.t3 TO USER
user1"));
+ } finally {
+ userStmt.close();
+ }
+ }
+
+ adminStmt.close();
+ }
}
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
index 2b4d533112e..ada2b0d21a0 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
@@ -115,7 +115,7 @@ public class AuthorInfo implements SnapshotProcessor {
return result;
}
- // if All paths fail, return No permission;
+ // if All paths fail, return No permission
// if some paths fail, return SUCCESS and failed index list
// if all path success, return success and empty index list
public TPermissionInfoResp checkUserPrivileges(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 39680c183d2..da7836dd039 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -204,29 +204,26 @@ public class AuthorityChecker {
boolean listRoleUser = false;
if (authResp.tag.equals(IoTDBConstant.COLUMN_ROLE)
|| authResp.tag.equals(IoTDBConstant.COLUMN_USER)) {
- // if list role/user, just return 1 column.
listRoleUser = true;
- types.add(TSDataType.TEXT);
- } else {
- // if list privilege, return : rolename, path, privilege, grant option
- types.add(TSDataType.TEXT);
- types.add(TSDataType.TEXT);
- types.add(TSDataType.TEXT);
- types.add(TSDataType.BOOLEAN);
}
- TsBlockBuilder builder = new TsBlockBuilder(types);
List<ColumnHeader> headerList = new ArrayList<>();
if (listRoleUser) {
headerList.add(new ColumnHeader(authResp.getTag(), TSDataType.TEXT));
+ types.add(TSDataType.TEXT);
} else {
headerList.add(new ColumnHeader(new String("ROLE"), TSDataType.TEXT));
+ types.add(TSDataType.TEXT);
headerList.add(new ColumnHeader(new String("PATH"), TSDataType.TEXT));
+ types.add(TSDataType.TEXT);
headerList.add(new ColumnHeader(new String("PRIVILEGES"),
TSDataType.TEXT));
+ types.add(TSDataType.TEXT);
headerList.add(new ColumnHeader(new String("GRANT OPTION"),
TSDataType.BOOLEAN));
+ types.add(TSDataType.BOOLEAN);
}
+ TsBlockBuilder builder = new TsBlockBuilder(types);
if (listRoleUser) {
for (String name : authResp.getMemberInfo()) {
builder.getTimeColumnBuilder().writeLong(0L);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
index 410347e9c9b..3f5cfa34573 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.db.auth;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.commons.auth.AuthException;
import org.apache.iotdb.commons.auth.entity.PathPrivilege;
+import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.auth.entity.Role;
import org.apache.iotdb.commons.auth.entity.User;
import org.apache.iotdb.commons.client.IClientManager;
@@ -127,7 +128,7 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
boolean grantOpt;
if (user != null) {
if (!user.isOpenIdUser()) {
- if (!paths.isEmpty()) {
+ if (PrivilegeType.values()[permission].isPathRelevant()) {
for (PartialPath path : paths) {
grantOpt = user.checkPathPrivilegeGrantOpt(path, permission);
if (!grantOpt) {
@@ -152,9 +153,7 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
}
return true;
} else {
- grantOpt =
- user.getSysPrivilege().contains(permission)
- && user.getSysPriGrantOpt().contains(permission);
+ grantOpt = user.checkSysPriGrantOpt(permission);
if (!grantOpt) {
for (String roleName : user.getRoleList()) {
Role role = iAuthorCache.getRoleCache(roleName);
@@ -169,6 +168,7 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
return checkUserPrivilegeGrantOptFromConfigNode(username,
paths, permission);
}
}
+ return false;
} else {
return true;
}
@@ -363,6 +363,7 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
return iAuthorCache;
}
+ @Override
public void refreshToken() {
long currentTime = System.currentTimeMillis();
if (heartBeatTimeStamp == 0) {
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java
index 4542956d9d0..fea562a9489 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java
@@ -187,4 +187,117 @@ public class AuthorizerManagerTest {
Assert.assertNull(user1);
Assert.assertNull(role1);
}
+
+ @Test
+ public void grantOptTest() throws IllegalPathException {
+ User user = new User();
+ Role role = new Role();
+
+ Set<Integer> sysPri = new HashSet<>();
+ sysPri.add(PrivilegeType.MANAGE_DATABASE.ordinal());
+ sysPri.add(PrivilegeType.USE_PIPE.ordinal());
+ user.setSysPrivilegeSet(sysPri);
+
+ Set<Integer> sysGrantOpt = new HashSet<>();
+ sysGrantOpt.add(PrivilegeType.USE_PIPE.ordinal());
+ user.setSysPriGrantOpt(sysGrantOpt);
+
+ List<PathPrivilege> pathList = new ArrayList<>();
+ PartialPath pathRoot = new PartialPath("root.**");
+ PartialPath path1 = new PartialPath("root.d1.**");
+ PathPrivilege priv1 = new PathPrivilege(path1);
+ priv1.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), false);
+ priv1.grantPrivilege(PrivilegeType.WRITE_SCHEMA.ordinal(), true);
+ pathList.add(priv1);
+
+ user.setPrivilegeList(pathList);
+
+ user.setName("user1");
+ user.setPassword("123456");
+
+ // user's priv:
+ // 1. MANAGE_DATABASE
+ // 2. USE_PIPE with grant option
+ // 3. READ_DATA root.d1.**
+ // 4. WRITE_SCHEMA root.d1.** with grant option
+
+ // role's priv:
+ // 1. USE_UDF
+ // 2. USE_CQ with grant option
+ // 3. READ_DATA root.t9.** with grant option
+
+ role.setName("role1");
+ Set<Integer> sysPriRole = new HashSet<>();
+ sysPriRole.add(PrivilegeType.USE_UDF.ordinal());
+ sysPriRole.add(PrivilegeType.USE_CQ.ordinal());
+ role.setSysPrivilegeSet(sysPriRole);
+
+ Set<Integer> sysGrantOptRole = new HashSet<>();
+ sysGrantOptRole.add(PrivilegeType.USE_CQ.ordinal());
+ role.setSysPriGrantOpt(sysGrantOptRole);
+
+ PathPrivilege privRole = new PathPrivilege(new PartialPath("root.t9.**"));
+ privRole.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), true);
+ role.setPrivilegeList(Collections.singletonList(privRole));
+ user.setRoleList(Collections.singletonList("role1"));
+
+ authorityFetcher.getAuthorCache().putUserCache("user1", user);
+ authorityFetcher.getAuthorCache().putRoleCache("role1", role);
+
+ // for system priv. we have USE_PIPE grant option.
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(pathRoot),
PrivilegeType.USE_PIPE.ordinal()));
+ Assert.assertFalse(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(pathRoot),
PrivilegeType.MANAGE_USER.ordinal()));
+
+ // for path priv. we have write_schema on root.d1.** with grant option.
+ // require root.d1.** with write_schema, return true
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(path1),
PrivilegeType.WRITE_SCHEMA.ordinal()));
+ // require root.** with write_schema, return false
+ Assert.assertFalse(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(pathRoot),
PrivilegeType.WRITE_SCHEMA.ordinal()));
+ // reuqire root.d1.d2 with write_schema, return true
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1",
+ Collections.singletonList(new PartialPath(new
String("root.d1.d2"))),
+ PrivilegeType.WRITE_SCHEMA.ordinal()));
+
+ // require root.d1.d2 with read_schema, return false
+ Assert.assertFalse(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1",
+ Collections.singletonList(new PartialPath(new
String("root.d1.d2"))),
+ PrivilegeType.READ_SCHEMA.ordinal()));
+
+ // role test
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1",
+ Collections.singletonList(new PartialPath(new
String("root.t9.**"))),
+ PrivilegeType.READ_DATA.ordinal()));
+
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1",
+ Collections.singletonList(new PartialPath(new
String("root.t9.t10"))),
+ PrivilegeType.READ_DATA.ordinal()));
+
+ Assert.assertFalse(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1",
+ Collections.singletonList(new PartialPath(new
String("root.t9.**"))),
+ PrivilegeType.WRITE_DATA.ordinal()));
+ Assert.assertFalse(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(pathRoot),
PrivilegeType.USE_TRIGGER.ordinal()));
+ Assert.assertTrue(
+ authorityFetcher.checkUserPrivilegeGrantOpt(
+ "user1", Collections.singletonList(pathRoot),
PrivilegeType.USE_CQ.ordinal()));
+ }
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
index 12e4e8e20a1..2be5feb3ab4 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
@@ -222,6 +222,9 @@ public class Role {
return sysPrivilegeSet.contains(privilegeId);
}
+ public boolean checkSysPriGrantOpt(int privilegeId) {
+ return sysPrivilegeSet.contains(privilegeId) &&
sysPriGrantOpt.contains(privilegeId);
+ }
/** ----------- misc --------------------* */
@Override
public boolean equals(Object o) {
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
index bd1a54e5b25..118df0265eb 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
@@ -19,9 +19,13 @@
package org.apache.iotdb.commons.auth.user;
import org.apache.iotdb.commons.auth.AuthException;
+import org.apache.iotdb.commons.auth.entity.PathPrivilege;
+import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.auth.entity.User;
import org.apache.iotdb.commons.concurrent.HashLock;
import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.AuthUtils;
import org.apache.iotdb.rpc.TSStatusCode;
@@ -84,6 +88,23 @@ public abstract class BasicUserManager implements
IUserManager {
true);
setUserUseWaterMark(CommonDescriptor.getInstance().getConfig().getAdminName(),
false);
}
+ admin = getUser(CommonDescriptor.getInstance().getConfig().getAdminName());
+ try {
+ PartialPath rootPath = new PartialPath(new
String(IoTDBConstant.PATH_ROOT + ".**"));
+ PathPrivilege pathPri = new PathPrivilege(rootPath);
+ for (PrivilegeType item : PrivilegeType.values()) {
+ if (!item.isPathRelevant()) {
+ admin.getSysPrivilege().add(item.ordinal());
+ admin.getSysPriGrantOpt().add(item.ordinal());
+ } else {
+ pathPri.grantPrivilege(item.ordinal(), true);
+ }
+ }
+ admin.getPathPrivilegeList().add(pathPri);
+ } catch (IllegalPathException e) {
+ // This error only results in a lack of permissions for list.
+ logger.warn("Got an wrong path for root to init");
+ }
logger.info("Admin initialized");
}