mirror of https://github.com/milvus-io/milvus.git
				
				
				
			fix: Fix privilege group hasn't been register for validate (#35937)
issue: #35471 --------- Signed-off-by: Wei Liu <wei.liu@zilliz.com>pull/36004/head
							parent
							
								
									7b21032d19
								
							
						
					
					
						commit
						32e55a02ea
					
				| 
						 | 
				
			
			@ -41,7 +41,7 @@ p = sub, obj, act
 | 
			
		|||
e = some(where (p.eft == allow))
 | 
			
		||||
 | 
			
		||||
[matchers]
 | 
			
		||||
m = r.sub == p.sub && globMatch(r.obj, p.obj) && globMatch(r.act, p.act) || r.sub == "admin" || (r.sub == p.sub && dbMatch(r.obj, p.obj) && privilegeGroupContains(r.act, p.act))
 | 
			
		||||
m = r.sub == p.sub && globMatch(r.obj, p.obj) && globMatch(r.act, p.act) || r.sub == "admin" || (r.sub == p.sub && dbMatch(r.obj, p.obj) && privilegeGroupContains(r.act, p.act, r.obj, p.obj))
 | 
			
		||||
`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -248,20 +248,38 @@ func DBMatchFunc(args ...interface{}) (interface{}, error) {
 | 
			
		|||
	return db1 == db2, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func collMatch(requestObj, policyObj string) bool {
 | 
			
		||||
	_, coll1 := funcutil.SplitObjectName(requestObj[strings.Index(requestObj, "-")+1:])
 | 
			
		||||
	_, coll2 := funcutil.SplitObjectName(policyObj[strings.Index(policyObj, "-")+1:])
 | 
			
		||||
 | 
			
		||||
	return coll2 == util.AnyWord || coll1 == coll2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PrivilegeGroupContains(args ...interface{}) (interface{}, error) {
 | 
			
		||||
	requestPrivilege := args[0].(string)
 | 
			
		||||
	policyPrivilege := args[1].(string)
 | 
			
		||||
	requestObj := args[2].(string)
 | 
			
		||||
	policyObj := args[3].(string)
 | 
			
		||||
 | 
			
		||||
	switch policyPrivilege {
 | 
			
		||||
	case commonpb.ObjectPrivilege_PrivilegeAll.String():
 | 
			
		||||
		return true, nil
 | 
			
		||||
	case commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String():
 | 
			
		||||
		// read only belong to collection object
 | 
			
		||||
		if !collMatch(requestObj, policyObj) {
 | 
			
		||||
			return false, nil
 | 
			
		||||
		}
 | 
			
		||||
		_, ok := roPrivileges[requestPrivilege]
 | 
			
		||||
		return ok, nil
 | 
			
		||||
	case commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String():
 | 
			
		||||
		// read write belong to collection object
 | 
			
		||||
		if !collMatch(requestObj, policyObj) {
 | 
			
		||||
			return false, nil
 | 
			
		||||
		}
 | 
			
		||||
		_, ok := rwPrivileges[requestPrivilege]
 | 
			
		||||
		return ok, nil
 | 
			
		||||
	case commonpb.ObjectPrivilege_PrivilegeGroupAdmin.String():
 | 
			
		||||
		// admin belong to global object
 | 
			
		||||
		_, ok := adminPrivileges[requestPrivilege]
 | 
			
		||||
		return ok, nil
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -235,8 +235,9 @@ func TestResourceGroupPrivilege(t *testing.T) {
 | 
			
		|||
func TestPrivilegeGroup(t *testing.T) {
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	t.Run("Read Only", func(t *testing.T) {
 | 
			
		||||
	t.Run("grant ReadOnly to single collection", func(t *testing.T) {
 | 
			
		||||
		paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
		initPrivilegeGroups()
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		ctx = GetContext(context.Background(), "fooo:123456")
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +249,7 @@ func TestPrivilegeGroup(t *testing.T) {
 | 
			
		|||
			return &internalpb.ListPolicyResponse{
 | 
			
		||||
				Status: merr.Success(),
 | 
			
		||||
				PolicyInfos: []string{
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String(), "default"),
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "coll1", commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String(), "default"),
 | 
			
		||||
				},
 | 
			
		||||
				UserRoles: []string{
 | 
			
		||||
					funcutil.EncodeUserRoleCache("fooo", "role1"),
 | 
			
		||||
| 
						 | 
				
			
			@ -258,18 +259,169 @@ func TestPrivilegeGroup(t *testing.T) {
 | 
			
		|||
		InitMetaCache(ctx, client, queryCoord, mgr)
 | 
			
		||||
		defer CleanPrivilegeCache()
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ShowCollectionsRequest{})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("grant ReadOnly to all collection", func(t *testing.T) {
 | 
			
		||||
		paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
		initPrivilegeGroups()
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		ctx = GetContext(context.Background(), "fooo:123456")
 | 
			
		||||
		client := &MockRootCoordClientInterface{}
 | 
			
		||||
		queryCoord := &mocks.MockQueryCoordClient{}
 | 
			
		||||
		mgr := newShardClientMgr()
 | 
			
		||||
 | 
			
		||||
		client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
 | 
			
		||||
			return &internalpb.ListPolicyResponse{
 | 
			
		||||
				Status: merr.Success(),
 | 
			
		||||
				PolicyInfos: []string{
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "*", commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String(), "default"),
 | 
			
		||||
				},
 | 
			
		||||
				UserRoles: []string{
 | 
			
		||||
					funcutil.EncodeUserRoleCache("fooo", "role1"),
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
		InitMetaCache(ctx, client, queryCoord, mgr)
 | 
			
		||||
		defer CleanPrivilegeCache()
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ShowCollectionsRequest{})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("grant ReadWrite to single collection", func(t *testing.T) {
 | 
			
		||||
		paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
		initPrivilegeGroups()
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		ctx = GetContext(context.Background(), "fooo:123456")
 | 
			
		||||
		client := &MockRootCoordClientInterface{}
 | 
			
		||||
		queryCoord := &mocks.MockQueryCoordClient{}
 | 
			
		||||
		mgr := newShardClientMgr()
 | 
			
		||||
 | 
			
		||||
		client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
 | 
			
		||||
			return &internalpb.ListPolicyResponse{
 | 
			
		||||
				Status: merr.Success(),
 | 
			
		||||
				PolicyInfos: []string{
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "coll1", commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String(), "default"),
 | 
			
		||||
				},
 | 
			
		||||
				UserRoles: []string{
 | 
			
		||||
					funcutil.EncodeUserRoleCache("fooo", "role1"),
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
		InitMetaCache(ctx, client, queryCoord, mgr)
 | 
			
		||||
		defer CleanPrivilegeCache()
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateResourceGroupRequest{})
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Read Write", func(t *testing.T) {
 | 
			
		||||
	t.Run("grant ReadWrite to all collection", func(t *testing.T) {
 | 
			
		||||
		paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
		initPrivilegeGroups()
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		ctx = GetContext(context.Background(), "fooo:123456")
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +433,7 @@ func TestPrivilegeGroup(t *testing.T) {
 | 
			
		|||
			return &internalpb.ListPolicyResponse{
 | 
			
		||||
				Status: merr.Success(),
 | 
			
		||||
				PolicyInfos: []string{
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String(), "default"),
 | 
			
		||||
					funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "*", commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String(), "default"),
 | 
			
		||||
				},
 | 
			
		||||
				UserRoles: []string{
 | 
			
		||||
					funcutil.EncodeUserRoleCache("fooo", "role1"),
 | 
			
		||||
| 
						 | 
				
			
			@ -291,16 +443,44 @@ func TestPrivilegeGroup(t *testing.T) {
 | 
			
		|||
		InitMetaCache(ctx, client, queryCoord, mgr)
 | 
			
		||||
		defer CleanPrivilegeCache()
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{})
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{
 | 
			
		||||
			CollectionName: "coll1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{
 | 
			
		||||
			CollectionName: "coll2",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateResourceGroupRequest{})
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +489,7 @@ func TestPrivilegeGroup(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	t.Run("Admin", func(t *testing.T) {
 | 
			
		||||
		paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
		initPrivilegeGroups()
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		ctx = GetContext(context.Background(), "fooo:123456")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2524,7 +2524,7 @@ func (c *Core) isValidGrantor(entity *milvuspb.GrantorEntity, object string) err
 | 
			
		|||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Errorf("not found the privilege name[%s]", entity.Privilege.Name)
 | 
			
		||||
	return fmt.Errorf("not found the privilege name[%s] in object[%s]", entity.Privilege.Name, object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OperatePrivilege operate the privilege, including grant and revoke
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,8 +57,9 @@ const (
 | 
			
		|||
	NonDBID             = int64(0)
 | 
			
		||||
	InvalidDBID         = int64(-1)
 | 
			
		||||
 | 
			
		||||
	PrivilegeWord = "Privilege"
 | 
			
		||||
	AnyWord       = "*"
 | 
			
		||||
	PrivilegeWord      = "Privilege"
 | 
			
		||||
	PrivilegeGroupWord = "PrivilegeGroup"
 | 
			
		||||
	AnyWord            = "*"
 | 
			
		||||
 | 
			
		||||
	IdentifierKey = "identifier"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +111,8 @@ var (
 | 
			
		|||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeShowPartitions.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeHasPartition.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetFlushState.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String()),
 | 
			
		||||
		},
 | 
			
		||||
		commonpb.ObjectType_Global.String(): {
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeAll.String()),
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +149,7 @@ var (
 | 
			
		|||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropAlias.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeAlias.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListAliases.String()),
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupAdmin.String()),
 | 
			
		||||
		},
 | 
			
		||||
		commonpb.ObjectType_User.String(): {
 | 
			
		||||
			MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()),
 | 
			
		||||
| 
						 | 
				
			
			@ -198,8 +202,6 @@ var (
 | 
			
		|||
		commonpb.ObjectPrivilege_PrivilegeGetStatistics.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeCreateIndex.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeDropIndex.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeCreateCollection.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeDropCollection.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeCreatePartition.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeDropPartition.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeLoad.String(),
 | 
			
		||||
| 
						 | 
				
			
			@ -216,6 +218,8 @@ var (
 | 
			
		|||
		commonpb.ObjectPrivilege_PrivilegeDropAlias.String(),
 | 
			
		||||
	}
 | 
			
		||||
	AdminPrivilegeGroup = []string{
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeCreateCollection.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeDropCollection.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeQuery.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeSearch.String(),
 | 
			
		||||
		commonpb.ObjectPrivilege_PrivilegeIndexDetail.String(),
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +295,11 @@ func StringList(stringMap map[string]struct{}) []string {
 | 
			
		|||
// MetaStore2API convert meta-store's privilege name to api's
 | 
			
		||||
// example: PrivilegeAll -> All
 | 
			
		||||
func MetaStore2API(name string) string {
 | 
			
		||||
	return name[strings.Index(name, PrivilegeWord)+len(PrivilegeWord):]
 | 
			
		||||
	prefix := PrivilegeWord
 | 
			
		||||
	if strings.Contains(name, PrivilegeGroupWord) {
 | 
			
		||||
		prefix = PrivilegeGroupWord
 | 
			
		||||
	}
 | 
			
		||||
	return name[strings.Index(name, prefix)+len(prefix):]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PrivilegeNameForAPI(name string) string {
 | 
			
		||||
| 
						 | 
				
			
			@ -303,10 +311,17 @@ func PrivilegeNameForAPI(name string) string {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func PrivilegeNameForMetastore(name string) string {
 | 
			
		||||
	// check if name is single privilege
 | 
			
		||||
	dbPrivilege := PrivilegeWord + name
 | 
			
		||||
	_, ok := commonpb.ObjectPrivilege_value[dbPrivilege]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return ""
 | 
			
		||||
		// check if name is privilege group
 | 
			
		||||
		dbPrivilege := PrivilegeGroupWord + name
 | 
			
		||||
		_, ok := commonpb.ObjectPrivilege_value[dbPrivilege]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
		return dbPrivilege
 | 
			
		||||
	}
 | 
			
		||||
	return dbPrivilege
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,137 @@
 | 
			
		|||
// Licensed to the LF AI & Data foundation 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 rbac
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
 | 
			
		||||
	"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
 | 
			
		||||
	"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
 | 
			
		||||
	"github.com/milvus-io/milvus/pkg/util"
 | 
			
		||||
	"github.com/milvus-io/milvus/pkg/util/merr"
 | 
			
		||||
	"github.com/milvus-io/milvus/pkg/util/paramtable"
 | 
			
		||||
	"github.com/milvus-io/milvus/tests/integration"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PrivilegeGroupTestSuite struct {
 | 
			
		||||
	integration.MiniClusterSuite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *PrivilegeGroupTestSuite) SetupSuite() {
 | 
			
		||||
	paramtable.Init()
 | 
			
		||||
	paramtable.Get().Save(paramtable.Get().QueryCoordCfg.BalanceCheckInterval.Key, "1000")
 | 
			
		||||
	paramtable.Get().Save(paramtable.Get().QueryNodeCfg.GracefulStopTimeout.Key, "1")
 | 
			
		||||
	paramtable.Get().Save(paramtable.Get().CommonCfg.AuthorizationEnabled.Key, "true")
 | 
			
		||||
 | 
			
		||||
	s.Require().NoError(s.SetupEmbedEtcd())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *PrivilegeGroupTestSuite) TestPrivilegeGroup() {
 | 
			
		||||
	ctx := GetContext(context.Background(), "root:123456")
 | 
			
		||||
	// test empty rbac content
 | 
			
		||||
	resp, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp.GetStatus()))
 | 
			
		||||
	s.Equal("", resp.GetRBACMeta().String())
 | 
			
		||||
 | 
			
		||||
	// generate some rbac content
 | 
			
		||||
	roleName := "test_role"
 | 
			
		||||
	resp1, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
 | 
			
		||||
		Entity: &milvuspb.RoleEntity{
 | 
			
		||||
			Name: roleName,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp1))
 | 
			
		||||
	resp2, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
 | 
			
		||||
		Type: milvuspb.OperatePrivilegeType_Grant,
 | 
			
		||||
		Entity: &milvuspb.GrantEntity{
 | 
			
		||||
			Role:       &milvuspb.RoleEntity{Name: roleName},
 | 
			
		||||
			Object:     &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
 | 
			
		||||
			ObjectName: util.AnyWord,
 | 
			
		||||
			DbName:     util.AnyWord,
 | 
			
		||||
			Grantor: &milvuspb.GrantorEntity{
 | 
			
		||||
				User:      &milvuspb.UserEntity{Name: util.UserRoot},
 | 
			
		||||
				Privilege: &milvuspb.PrivilegeEntity{Name: "ReadOnly"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp2))
 | 
			
		||||
 | 
			
		||||
	resp3, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
 | 
			
		||||
		Type: milvuspb.OperatePrivilegeType_Grant,
 | 
			
		||||
		Entity: &milvuspb.GrantEntity{
 | 
			
		||||
			Role:       &milvuspb.RoleEntity{Name: roleName},
 | 
			
		||||
			Object:     &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
 | 
			
		||||
			ObjectName: util.AnyWord,
 | 
			
		||||
			DbName:     util.AnyWord,
 | 
			
		||||
			Grantor: &milvuspb.GrantorEntity{
 | 
			
		||||
				User:      &milvuspb.UserEntity{Name: util.UserRoot},
 | 
			
		||||
				Privilege: &milvuspb.PrivilegeEntity{Name: "ReadWrite"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp3))
 | 
			
		||||
 | 
			
		||||
	resp4, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
 | 
			
		||||
		Type: milvuspb.OperatePrivilegeType_Grant,
 | 
			
		||||
		Entity: &milvuspb.GrantEntity{
 | 
			
		||||
			Role:       &milvuspb.RoleEntity{Name: roleName},
 | 
			
		||||
			Object:     &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
 | 
			
		||||
			ObjectName: util.AnyWord,
 | 
			
		||||
			DbName:     util.AnyWord,
 | 
			
		||||
			Grantor: &milvuspb.GrantorEntity{
 | 
			
		||||
				User:      &milvuspb.UserEntity{Name: util.UserRoot},
 | 
			
		||||
				Privilege: &milvuspb.PrivilegeEntity{Name: "Admin"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp4))
 | 
			
		||||
 | 
			
		||||
	resp5, err := s.Cluster.Proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
 | 
			
		||||
		Entity: &milvuspb.GrantEntity{
 | 
			
		||||
			Role:       &milvuspb.RoleEntity{Name: roleName},
 | 
			
		||||
			Object:     &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
 | 
			
		||||
			ObjectName: util.AnyWord,
 | 
			
		||||
			DbName:     util.AnyWord,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp5.GetStatus()))
 | 
			
		||||
	s.Len(resp5.GetEntities(), 1)
 | 
			
		||||
 | 
			
		||||
	resp6, err := s.Cluster.Proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
 | 
			
		||||
		Entity: &milvuspb.GrantEntity{
 | 
			
		||||
			Role:       &milvuspb.RoleEntity{Name: roleName},
 | 
			
		||||
			Object:     &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
 | 
			
		||||
			ObjectName: util.AnyWord,
 | 
			
		||||
			DbName:     util.AnyWord,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	s.NoError(err)
 | 
			
		||||
	s.True(merr.Ok(resp6.GetStatus()))
 | 
			
		||||
	s.Len(resp6.GetEntities(), 2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPrivilegeGroup(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(PrivilegeGroupTestSuite))
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue