From a689ea3228b77a13de6e34726f61f81ac72c6dc1 Mon Sep 17 00:00:00 2001 From: "zhenshan.cao" Date: Fri, 12 Jan 2024 23:36:52 +0800 Subject: [PATCH] feat: Add RBAC functionality to alias (#29885) (#29947) issue: https://github.com/milvus-io/milvus/issues/29781 issue: https://github.com/milvus-io/milvus-proto/issues/237 pr : https://github.com/milvus-io/milvus/pull/29885 Signed-off-by: zhenshan.cao --- pkg/util/constant.go | 5 ++ pkg/util/funcutil/policy_test.go | 2 +- tests/python_client/testcases/test_utility.py | 62 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/pkg/util/constant.go b/pkg/util/constant.go index 525ce2ffd7064..95011d8aca7fa 100644 --- a/pkg/util/constant.go +++ b/pkg/util/constant.go @@ -131,6 +131,11 @@ var ( MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateDatabase.String()), MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropDatabase.String()), MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListDatabases.String()), + + MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateAlias.String()), + MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropAlias.String()), + MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeAlias.String()), + MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListAliases.String()), }, commonpb.ObjectType_User.String(): { MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()), diff --git a/pkg/util/funcutil/policy_test.go b/pkg/util/funcutil/policy_test.go index 93395768accf6..8659b82205561 100644 --- a/pkg/util/funcutil/policy_test.go +++ b/pkg/util/funcutil/policy_test.go @@ -20,7 +20,7 @@ func Test_GetPrivilegeExtObj(t *testing.T) { assert.Equal(t, commonpb.ObjectPrivilege_PrivilegeLoad, privilegeExt.ObjectPrivilege) assert.Equal(t, int32(3), privilegeExt.ObjectNameIndex) - request2 := &milvuspb.GetPartitionStatisticsRequest{} + request2 := &milvuspb.GetPersistentSegmentInfoRequest{} _, err = GetPrivilegeExtObj(request2) assert.Error(t, err) } diff --git a/tests/python_client/testcases/test_utility.py b/tests/python_client/testcases/test_utility.py index 094c3900fd5f5..0cd605eb99062 100644 --- a/tests/python_client/testcases/test_utility.py +++ b/tests/python_client/testcases/test_utility.py @@ -4295,6 +4295,67 @@ def test_grant_connect(self, host, port): self.utility_wrap.describe_resource_group(name=ct.default_resource_group_name, check_task=CheckTasks.check_permission_deny) + @pytest.mark.tags(CaseLabel.RBAC) + def test_alias_rbac(self, host, port): + """ + target: test rbac related to alias interfaces + method: Create a role and grant privileges related to aliases. + Verify if a user can execute the corresponding alias interface + based on whether the user possesses the role. + expected: Users with the assigned role can access the alias interface, + while those without the role cannot. + """ + + self.connection_wrap.connect(host=host, port=port, user=ct.default_user, + password=ct.default_password, check_task=ct.CheckTasks.ccr) + user = cf.gen_unique_str(prefix) + password = cf.gen_unique_str(prefix) + r_name = cf.gen_unique_str(prefix) + c_name = cf.gen_unique_str(prefix) + alias_name = cf.gen_unique_str(prefix) + u, _ = self.utility_wrap.create_user(user=user, password=password) + user2 = cf.gen_unique_str(prefix) + u2, _ = self.utility_wrap.create_user(user=user2, password=password) + + + self.utility_wrap.init_role(r_name) + self.utility_wrap.create_role() + self.utility_wrap.role_add_user(user) + + db_kwargs = {} + # grant user privilege + self.utility_wrap.init_role(r_name) + alias_privileges = [ + {"object": "Global", "object_name": "*", "privilege": "CreateAlias"}, + {"object": "Global", "object_name": "*", "privilege": "DropAlias"}, + {"object": "Global", "object_name": "*", "privilege": "DescribeAlias"}, + {"object": "Global", "object_name": "*", "privilege": "ListAliases"}, + ] + + for grant_item in alias_privileges: + self.utility_wrap.role_grant(grant_item["object"], grant_item["object_name"], grant_item["privilege"], + **db_kwargs) + + self.init_collection_wrap(name=c_name) + self.connection_wrap.disconnect(alias=DefaultConfig.DEFAULT_USING) + + self.connection_wrap.connect(host=host, port=port, user=user, + password=password, check_task=ct.CheckTasks.ccr, **db_kwargs) + + self.utility_wrap.create_alias(c_name, alias_name) + self.utility_wrap.drop_alias(alias_name) + + self.connection_wrap.disconnect(alias=DefaultConfig.DEFAULT_USING) + self.connection_wrap.connect(host=host, port=port, user=user2, + password=password, check_task=ct.CheckTasks.ccr, **db_kwargs) + + + # user2 can not create or drop alias + self.utility_wrap.create_alias(c_name, alias_name, + check_task=CheckTasks.check_permission_deny) + + self.utility_wrap.drop_alias(alias_name, + check_task=CheckTasks.check_permission_deny) class TestUtilityNegativeRbac(TestcaseBase): @@ -4942,6 +5003,7 @@ def test_create_over_max_roles(self, host, port): self.utility_wrap.create_role(check_task=CheckTasks.err_res, check_items=error) + @pytest.mark.tags(CaseLabel.L3) class TestUtilityFlushAll(TestcaseBase):