mirror of
https://gitee.com/milvus-io/milvus.git
synced 2025-12-07 01:28:27 +08:00
Related to #44761 This commit refactors the privilege management system in the proxy component by: 1. **Separation of Concerns**: Extracts privilege-related functionality from MetaCache into a dedicated `internal/proxy/privilege` package, improving code organization and maintainability. 2. **New Package Structure**: Creates `internal/proxy/privilege/` with: - `cache.go`: Core privilege cache implementation (PrivilegeCache) - `result_cache.go`: Privilege enforcement result caching - `model.go`: Casbin model and policy enforcement functions - `meta_cache_adapter.go`: Casbin adapter for MetaCache integration - Corresponding test files and mock implementations 3. **MetaCache Simplification**: Removes privilege and credential management methods from MetaCache interface and implementation: - Removed: GetCredentialInfo, RemoveCredential, UpdateCredential - Removed: GetPrivilegeInfo, GetUserRole, RefreshPolicyInfo, InitPolicyInfo - Deleted: meta_cache_adapter.go, privilege_cache.go and their tests 4. **Updated References**: Updates all callsites to use the new privilegeCache global: - Authentication interceptor now uses privilegeCache for password verification - Credential cache operations (InvalidateCredentialCache, UpdateCredentialCache, UpdateCredential) now use privilegeCache - Policy refresh operations (RefreshPolicyInfoCache) now use privilegeCache - Privilege interceptor uses new privilege.GetEnforcer() and privilege result cache 5. **Improved API**: Renames cache functions for clarity: - GetPrivilegeCache → GetResultCache - SetPrivilegeCache → SetResultCache - CleanPrivilegeCache → CleanResultCache This refactoring makes the codebase more modular, separates privilege management concerns from general metadata caching, and provides a clearer API for privilege enforcement operations. --------- Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>
634 lines
23 KiB
Go
634 lines
23 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"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/internal/proxy/privilege"
|
|
"github.com/milvus-io/milvus/pkg/v2/proto/internalpb"
|
|
"github.com/milvus-io/milvus/pkg/v2/util"
|
|
"github.com/milvus-io/milvus/pkg/v2/util/funcutil"
|
|
"github.com/milvus-io/milvus/pkg/v2/util/merr"
|
|
"github.com/milvus-io/milvus/pkg/v2/util/paramtable"
|
|
)
|
|
|
|
func TestUnaryServerInterceptor(t *testing.T) {
|
|
interceptor := UnaryServerInterceptor(PrivilegeInterceptor)
|
|
assert.NotNil(t, interceptor)
|
|
}
|
|
|
|
func TestPrivilegeInterceptor(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("Authorization Disabled", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "false")
|
|
_, err := PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Authorization Enabled", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
|
|
_, err := PrivilegeInterceptor(ctx, &milvuspb.HasCollectionRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
|
|
ctx = GetContext(context.Background(), "alice:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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(), "col1", commonpb.ObjectPrivilege_PrivilegeLoad.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "col1", commonpb.ObjectPrivilege_PrivilegeGetLoadState.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "col1", commonpb.ObjectPrivilege_PrivilegeGetLoadingProgress.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "col1", commonpb.ObjectPrivilege_PrivilegeFlush.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role2", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeAll.String(), "default"),
|
|
},
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("alice", "role1"),
|
|
funcutil.EncodeUserRoleCache("fooo", "role2"),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "foo:123456"), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "root:123456"), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
err = InitMetaCache(ctx, client, mgr)
|
|
assert.NoError(t, err)
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.HasCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.GetLoadingProgressRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.GetLoadStateRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
fooCtx := GetContext(context.Background(), "foo:123456")
|
|
_, err = PrivilegeInterceptor(fooCtx, &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
{
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "foo:"+util.PasswordHolder), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
assert.True(t, strings.Contains(err.Error(), "apikey user"))
|
|
}
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.InsertRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.UpsertRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
_, err = PrivilegeInterceptor(fooCtx, &milvuspb.GetLoadingProgressRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
_, err = PrivilegeInterceptor(fooCtx, &milvuspb.GetLoadStateRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(ctx, &milvuspb.FlushRequest{
|
|
DbName: "db_test",
|
|
CollectionNames: []string{"col1"},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContextWithDB(context.Background(), "fooo:123456", "foo"), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NotNil(t, err)
|
|
|
|
g := sync.WaitGroup{}
|
|
for i := 0; i < 20; i++ {
|
|
g.Add(1)
|
|
go func() {
|
|
defer g.Done()
|
|
assert.NotPanics(t, func() {
|
|
PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.LoadCollectionRequest{
|
|
DbName: "db_test",
|
|
CollectionName: "col1",
|
|
})
|
|
})
|
|
}()
|
|
}
|
|
g.Wait()
|
|
|
|
assert.Panics(t, func() {
|
|
privilege.GetPolicyModel("foo")
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestRootShouldBindRole(t *testing.T) {
|
|
paramtable.Init()
|
|
Params.Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
defer Params.Reset(Params.CommonCfg.AuthorizationEnabled.Key)
|
|
rootCtx := GetContext(context.Background(), "root:Milvus")
|
|
t.Run("not bind role", func(t *testing.T) {
|
|
Params.Save(Params.CommonCfg.RootShouldBindRole.Key, "false")
|
|
defer Params.Reset(Params.CommonCfg.RootShouldBindRole.Key)
|
|
|
|
InitEmptyGlobalCache()
|
|
_, err := PrivilegeInterceptor(rootCtx, &milvuspb.LoadCollectionRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("bind role", func(t *testing.T) {
|
|
Params.Save(Params.CommonCfg.RootShouldBindRole.Key, "true")
|
|
defer Params.Reset(Params.CommonCfg.RootShouldBindRole.Key)
|
|
|
|
InitEmptyGlobalCache()
|
|
_, err := PrivilegeInterceptor(rootCtx, &milvuspb.LoadCollectionRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.Error(t, err)
|
|
|
|
AddRootUserToAdminRole()
|
|
_, err = PrivilegeInterceptor(rootCtx, &milvuspb.LoadCollectionRequest{
|
|
CollectionName: "col1",
|
|
})
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestResourceGroupPrivilege(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("Resource Group Privilege", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
|
|
_, err := PrivilegeInterceptor(ctx, &milvuspb.ListResourceGroupsRequest{})
|
|
assert.Error(t, err)
|
|
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeCreateResourceGroup.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeDropResourceGroup.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeDescribeResourceGroup.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeListResourceGroups.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeTransferNode.String(), "default"),
|
|
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeTransferReplica.String(), "default"),
|
|
},
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("fooo", "role1"),
|
|
},
|
|
}, nil
|
|
}
|
|
InitMetaCache(ctx, client, mgr)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateResourceGroupRequest{
|
|
ResourceGroup: "rg",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DropResourceGroupRequest{
|
|
ResourceGroup: "rg",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DescribeResourceGroupRequest{
|
|
ResourceGroup: "rg",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ListResourceGroupsRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.TransferNodeRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.TransferReplicaRequest{})
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestPrivilegeGroup(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("grant ReadOnly to single collection", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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_PrivilegeGroupReadOnly.String(), "default"),
|
|
},
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("fooo", "role1"),
|
|
},
|
|
}, nil
|
|
}
|
|
InitMetaCache(ctx, client, mgr)
|
|
defer privilege.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.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")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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, mgr)
|
|
defer privilege.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")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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, mgr)
|
|
defer privilege.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)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateAliasRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DropAliasRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DescribeAliasRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateDatabaseRequest{})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DropDatabaseRequest{})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ListDatabasesRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateCollectionRequest{})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DropCollectionRequest{})
|
|
assert.Error(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DescribeCollectionRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ShowCollectionsRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.RenameCollectionRequest{
|
|
OldName: "coll1",
|
|
NewName: "newName",
|
|
})
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("grant ReadWrite to all collection", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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_PrivilegeGroupReadWrite.String(), "default"),
|
|
},
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("fooo", "role1"),
|
|
},
|
|
}, nil
|
|
}
|
|
InitMetaCache(ctx, client, mgr)
|
|
defer privilege.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.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{})
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Admin", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx = GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
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_Global.String(), "*", commonpb.ObjectPrivilege_PrivilegeGroupAdmin.String(), "default"),
|
|
},
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("fooo", "role1"),
|
|
},
|
|
}, nil
|
|
}
|
|
InitMetaCache(ctx, client, mgr)
|
|
defer privilege.CleanPrivilegeCache()
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.QueryRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SearchRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.InsertRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DeleteRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateResourceGroupRequest{})
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestBuiltinPrivilegeGroup(t *testing.T) {
|
|
t.Run("ClusterAdmin", func(t *testing.T) {
|
|
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
|
privilege.InitPrivilegeGroups()
|
|
|
|
var err error
|
|
ctx := GetContext(context.Background(), "fooo:123456")
|
|
client := &MockMixCoordClientInterface{}
|
|
mgr := newShardClientMgr()
|
|
|
|
policies := []string{}
|
|
for _, priv := range Params.RbacConfig.GetDefaultPrivilegeGroup("ClusterReadOnly").Privileges {
|
|
objectType := util.GetObjectType(priv.Name)
|
|
policies = append(policies, funcutil.PolicyForPrivilege("role1", objectType, "*", util.PrivilegeNameForMetastore(priv.Name), "default"))
|
|
}
|
|
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
|
|
return &internalpb.ListPolicyResponse{
|
|
Status: merr.Success(),
|
|
PolicyInfos: policies,
|
|
UserRoles: []string{
|
|
funcutil.EncodeUserRoleCache("fooo", "role1"),
|
|
},
|
|
}, nil
|
|
}
|
|
InitMetaCache(ctx, client, mgr)
|
|
defer privilege.CleanPrivilegeCache()
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.SelectUserRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.DescribeResourceGroupRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.ListResourceGroupsRequest{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = PrivilegeInterceptor(GetContext(context.Background(), "fooo:123456"), &milvuspb.CreateResourceGroupRequest{})
|
|
assert.Error(t, err)
|
|
})
|
|
}
|