This is an automated email from the ASF dual-hosted git repository. haonan pushed a commit to branch rc/1.3.1 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 3a6dcc64be755934284f38939b3719e4aa729123 Author: Colin Li <[email protected]> AuthorDate: Wed Feb 28 08:37:54 2024 +0800 fix.root privileges lost and grant role --- .../org/apache/iotdb/db/it/auth/IoTDBAuthIT.java | 2 ++ .../org/apache/iotdb/db/auth/entity/RoleTest.java | 31 ++++++++++++++++------ .../commons/auth/authorizer/BasicAuthorizer.java | 10 +++++++ .../org/apache/iotdb/commons/auth/entity/Role.java | 14 +++++++++- .../iotdb/commons/auth/user/BasicUserManager.java | 15 ++++++++++- 5 files changed, 62 insertions(+), 10 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 95e3e6dcf1f..25e1b6833f9 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 @@ -906,6 +906,8 @@ public class IoTDBAuthIT { adminStatement.execute("CREATE USER user02 'pass1234'"); adminStatement.execute("CREATE ROLE manager"); adminStatement.execute("GRANT MANAGE_ROLE on root.** TO USER user01"); + Assert.assertThrows( + SQLException.class, () -> adminStatement.execute("GRANT role manager to `root`")); } try (Connection userCon = EnvFactory.getEnv().getConnection("user01", "pass1234"); diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java index 114a84d1304..8b527eb235e 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/entity/RoleTest.java @@ -19,9 +19,10 @@ package org.apache.iotdb.db.auth.entity; 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.conf.IoTDBConstant; import org.apache.iotdb.commons.exception.IllegalPathException; -import org.apache.iotdb.commons.exception.IllegalPrivilegeException; import org.apache.iotdb.commons.path.PartialPath; import org.junit.Assert; @@ -48,13 +49,27 @@ public class RoleTest { "Role{name='role', pathPrivilegeList=[root.ln : " + "WRITE_DATA READ_SCHEMA_with_grant_option], systemPrivilegeSet=[]}", role1.toString()); - } - @Test - public void TestRole_GrantAndRevoke() throws IllegalPrivilegeException, IllegalPathException { - Role role = new Role("role"); - PathPrivilege pathPrivilege = new PathPrivilege(new PartialPath("root.ln")); - role.setPrivilegeList(Collections.singletonList(pathPrivilege)); - // role. + Role admin = new Role("root"); + PartialPath rootPath = new PartialPath(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); + Assert.assertEquals( + "Role{name='root', pathPrivilegeList=[root.** : READ_DAT" + + "A_with_grant_option WRITE_DATA_with_grant_option READ_SCHEMA_with" + + "_grant_option WRITE_SCHEMA_with_grant_option], systemPrivilegeSet=[MANAGE_ROLE" + + "_with_grant_option , USE_UDF_with_grant_option , USE_CQ_with_grant_option , USE" + + "_PIPE_with_grant_option , USE_TRIGGER_with_grant_option , MANAGE_DATABASE_with_g" + + "rant_option , MANAGE_USER_with_grant_option , MAINTAIN_with_grant_option , EXTEND" + + "_TEMPLATE_with_grant_option , USE_MODEL_with_grant_option ]}", + admin.toString()); } } diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java index e61982ff65b..7ccc17e33c6 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java @@ -230,6 +230,11 @@ public abstract class BasicAuthorizer implements IAuthorizer, IService { @Override public void grantRoleToUser(String roleName, String username) throws AuthException { + if (isAdmin(username)) { + throw new AuthException( + TSStatusCode.NO_PERMISSION, "Invalid operation, cannot grant role to administrator "); + } + Role role = roleManager.getRole(roleName); if (role == null) { throw new AuthException( @@ -252,6 +257,11 @@ public abstract class BasicAuthorizer implements IAuthorizer, IService { @Override public void revokeRoleFromUser(String roleName, String username) throws AuthException { + if (isAdmin(username)) { + throw new AuthException( + TSStatusCode.NO_PERMISSION, "Invalid operation, cannot revoke role from administrator "); + } + Role role = roleManager.getRole(roleName); if (role == null) { throw new AuthException( 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 b644ecc369c..2fbd4914af0 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 @@ -311,7 +311,19 @@ public class Role { + ", pathPrivilegeList=" + pathPrivilegeList + ", systemPrivilegeSet=" - + sysPrivilegeSet + + sysPriToString() + '}'; } + + private Set<String> sysPriToString() { + Set<String> priSet = new HashSet<>(); + for (Integer pri : sysPrivilegeSet) { + StringBuilder str = new StringBuilder(String.valueOf(PrivilegeType.values()[pri].toString())); + if (sysPriGrantOpt.contains(pri)) { + str.append("_with_grant_option "); + } + priSet.add(str.toString()); + } + return priSet; + } } 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 b40417cb534..774cfe5a1e8 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 @@ -82,7 +82,7 @@ public abstract class BasicUserManager implements IUserManager { this.accessor = accessor; this.lock = new HashLock(); - reset(); + init(); } /** @@ -119,7 +119,9 @@ public abstract class BasicUserManager implements IUserManager { pathPri.grantPrivilege(item.ordinal(), true); } } + admin.getPathPrivilegeList().clear(); admin.getPathPrivilegeList().add(pathPri); + admin.setServiceReady(true); } catch (IllegalPathException e) { // This error only leads to a lack of permissions for list. LOGGER.warn("Got a wrong path for root to init"); @@ -311,6 +313,17 @@ public abstract class BasicUserManager implements IUserManager { } } + // If system.users is empty, it means we are init our system, so init an admin user. + // If system.user is not empty when we start system, it means we will boost our system with + // snapshot data, + // init admin when we load snapshot. + private void init() throws AuthException { + this.accessor.reset(); + if (accessor.listAllUsers().isEmpty()) { + initAdmin(); + } + } + @Override public void reset() throws AuthException { accessor.reset();
