fix: [2.5] fix privilege group list and list collections ()

cherry-pick from: https://github.com/milvus-io/milvus/pull/38684
related: https://github.com/milvus-io/milvus/issues/37031

Signed-off-by: shaoting-huang <shaoting.huang@zilliz.com>
pull/38752/head
sthuang 2024-12-25 18:06:50 +08:00 committed by GitHub
parent f441ccdbe9
commit a4901ef7ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 265 additions and 212 deletions

View File

@ -399,11 +399,11 @@ func TestRoleRBAC(t *testing.T) {
suite.Run(t, new(RoleSuite))
}
type PrivilgeGroupSuite struct {
type PrivilegeGroupSuite struct {
MockSuiteBase
}
func (s *PrivilgeGroupSuite) TestGrantV2() {
func (s *PrivilegeGroupSuite) TestGrantV2() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -433,7 +433,7 @@ func (s *PrivilgeGroupSuite) TestGrantV2() {
})
}
func (s *PrivilgeGroupSuite) TestRevokeV2() {
func (s *PrivilegeGroupSuite) TestRevokeV2() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -463,7 +463,7 @@ func (s *PrivilgeGroupSuite) TestRevokeV2() {
})
}
func (s *PrivilgeGroupSuite) TestCreatePrivilegeGroup() {
func (s *PrivilegeGroupSuite) TestCreatePrivilegeGroup() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -487,7 +487,7 @@ func (s *PrivilgeGroupSuite) TestCreatePrivilegeGroup() {
})
}
func (s *PrivilgeGroupSuite) TestDropPrivilegeGroup() {
func (s *PrivilegeGroupSuite) TestDropPrivilegeGroup() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -511,7 +511,7 @@ func (s *PrivilgeGroupSuite) TestDropPrivilegeGroup() {
})
}
func (s *PrivilgeGroupSuite) TestListPrivilegeGroups() {
func (s *PrivilegeGroupSuite) TestListPrivilegeGroups() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -548,7 +548,7 @@ func (s *PrivilgeGroupSuite) TestListPrivilegeGroups() {
})
}
func (s *PrivilgeGroupSuite) TestOperatePrivilegeGroup() {
func (s *PrivilegeGroupSuite) TestOperatePrivilegeGroup() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@ -575,5 +575,5 @@ func (s *PrivilgeGroupSuite) TestOperatePrivilegeGroup() {
}
func TestPrivilegeGroup(t *testing.T) {
suite.Run(t, new(PrivilgeGroupSuite))
suite.Run(t, new(PrivilegeGroupSuite))
}

View File

@ -829,7 +829,7 @@ common:
superUsers:
defaultRootPassword: "Milvus" # default password for root user. The maximum length is 72 characters, and double quotes are required.
rbac:
overrideBuiltInPrivilgeGroups:
overrideBuiltInPrivilegeGroups:
enabled: false # Whether to override build-in privilege groups
cluster:
readonly:

View File

@ -576,9 +576,9 @@ func TestBuiltinPrivilegeGroup(t *testing.T) {
mgr := newShardClientMgr()
policies := []string{}
for _, priv := range util.BuiltinPrivilegeGroups["ClusterReadOnly"] {
objectType := util.GetObjectType(priv)
policies = append(policies, funcutil.PolicyForPrivilege("role1", objectType, "*", util.PrivilegeNameForMetastore(priv), "default"))
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{

View File

@ -638,50 +638,6 @@ func (c *Core) initPublicRolePrivilege() error {
return nil
}
func (c *Core) initBuiltinPrivilegeGroups() []*milvuspb.PrivilegeGroupInfo {
// init built in privilege groups, override by config if rbac config enabled
builtinGroups := make([]*milvuspb.PrivilegeGroupInfo, 0)
for groupName, privileges := range util.BuiltinPrivilegeGroups {
if Params.RbacConfig.Enabled.GetAsBool() {
var confPrivs []string
switch groupName {
case "ClusterReadOnly":
confPrivs = Params.RbacConfig.ClusterReadOnlyPrivileges.GetAsStrings()
case "ClusterReadWrite":
confPrivs = Params.RbacConfig.ClusterReadWritePrivileges.GetAsStrings()
case "ClusterAdmin":
confPrivs = Params.RbacConfig.ClusterAdminPrivileges.GetAsStrings()
case "DatabaseReadOnly":
confPrivs = Params.RbacConfig.DBReadOnlyPrivileges.GetAsStrings()
case "DatabaseReadWrite":
confPrivs = Params.RbacConfig.DBReadWritePrivileges.GetAsStrings()
case "DatabaseAdmin":
confPrivs = Params.RbacConfig.DBAdminPrivileges.GetAsStrings()
case "CollectionReadOnly":
confPrivs = Params.RbacConfig.CollectionReadOnlyPrivileges.GetAsStrings()
case "CollectionReadWrite":
confPrivs = Params.RbacConfig.CollectionReadWritePrivileges.GetAsStrings()
case "CollectionAdmin":
confPrivs = Params.RbacConfig.CollectionAdminPrivileges.GetAsStrings()
default:
return nil
}
if len(confPrivs) > 0 {
privileges = confPrivs
}
}
privs := lo.Map(privileges, func(name string, _ int) *milvuspb.PrivilegeEntity {
return &milvuspb.PrivilegeEntity{Name: name}
})
builtinGroups = append(builtinGroups, &milvuspb.PrivilegeGroupInfo{
GroupName: groupName,
Privileges: privs,
})
}
return builtinGroups
}
func (c *Core) initBuiltinRoles() error {
log := log.Ctx(c.ctx)
rolePrivilegesMap := Params.RoleCfg.Roles.GetAsRoleDetails()
@ -2648,7 +2604,7 @@ func (c *Core) isValidPrivilege(ctx context.Context, privilegeName string, objec
if customPrivGroup {
return fmt.Errorf("can not operate the custom privilege group [%s]", privilegeName)
}
if lo.Contains(lo.Keys(util.BuiltinPrivilegeGroups), privilegeName) {
if lo.Contains(Params.RbacConfig.GetDefaultPrivilegeGroupNames(), privilegeName) {
return fmt.Errorf("can not operate the built-in privilege group [%s]", privilegeName)
}
// check object privileges for built-in privileges
@ -2757,7 +2713,7 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
grants := []*milvuspb.GrantEntity{in.Entity}
allGroups, err := c.meta.ListPrivilegeGroups(ctx)
allGroups = append(allGroups, c.initBuiltinPrivilegeGroups()...)
allGroups = append(allGroups, Params.RbacConfig.GetDefaultPrivilegeGroups()...)
if err != nil {
return nil, err
}
@ -3243,16 +3199,7 @@ func (c *Core) ListPrivilegeGroups(ctx context.Context, in *milvuspb.ListPrivile
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
// append built in privilege groups
for groupName, privileges := range util.BuiltinPrivilegeGroups {
privGroups = append(privGroups, &milvuspb.PrivilegeGroupInfo{
GroupName: groupName,
Privileges: lo.Map(privileges, func(p string, _ int) *milvuspb.PrivilegeEntity {
return &milvuspb.PrivilegeEntity{
Name: p,
}
}),
})
}
privGroups = append(privGroups, Params.RbacConfig.GetDefaultPrivilegeGroups()...)
return &milvuspb.ListPrivilegeGroupsResponse{
Status: merr.Success(),
PrivilegeGroups: privGroups,

View File

@ -2037,29 +2037,6 @@ func TestCore_InitRBAC(t *testing.T) {
err := c.initRbac()
assert.NoError(t, err)
})
t.Run("init default privilege groups", func(t *testing.T) {
clusterReadWrite := `SelectOwnership,SelectUser,DescribeResourceGroup`
meta := mockrootcoord.NewIMetaTable(t)
c := newTestCore(withHealthyCode(), withMeta(meta))
Params.Save(Params.RbacConfig.Enabled.Key, "true")
Params.Save(Params.RbacConfig.ClusterReadWritePrivileges.Key, clusterReadWrite)
defer func() {
Params.Reset(Params.RbacConfig.Enabled.Key)
Params.Reset(Params.RbacConfig.ClusterReadWritePrivileges.Key)
}()
builtinGroups := c.initBuiltinPrivilegeGroups()
fmt.Println(builtinGroups)
assert.Equal(t, len(util.BuiltinPrivilegeGroups), len(builtinGroups))
for _, group := range builtinGroups {
if group.GroupName == "ClusterReadWrite" {
assert.Equal(t, len(group.Privileges), 3)
}
}
})
}
func TestCore_BackupRBAC(t *testing.T) {

View File

@ -88,12 +88,15 @@ func (t *showCollectionTask) Execute(ctx context.Context) error {
}
for _, entity := range entities {
objectType := entity.GetObject().GetName()
priv := entity.GetGrantor().GetPrivilege().GetName()
if objectType == commonpb.ObjectType_Global.String() &&
entity.GetGrantor().GetPrivilege().GetName() == util.PrivilegeNameForAPI(commonpb.ObjectPrivilege_PrivilegeAll.String()) {
priv == util.PrivilegeNameForAPI(commonpb.ObjectPrivilege_PrivilegeAll.String()) {
privilegeColls.Insert(util.AnyWord)
return privilegeColls, nil
}
if objectType != commonpb.ObjectType_Collection.String() {
// should list collection level built-in privilege group objects
if objectType != commonpb.ObjectType_Collection.String() &&
!Params.RbacConfig.IsCollectionPrivilegeGroup(priv) {
continue
}
collectionName := entity.GetObjectName()

View File

@ -325,6 +325,57 @@ func TestShowCollectionsAuth(t *testing.T) {
assert.Equal(t, "foo", task.Rsp.GetCollectionNames()[0])
})
t.Run("collection level privilege group", func(t *testing.T) {
Params.Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
defer Params.Reset(Params.CommonCfg.AuthorizationEnabled.Key)
meta := mockrootcoord.NewIMetaTable(t)
core := newTestCore(withMeta(meta))
meta.EXPECT().SelectUser(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return([]*milvuspb.UserResult{
{
User: &milvuspb.UserEntity{
Name: "foo",
},
Roles: []*milvuspb.RoleEntity{
{
Name: "hoooo",
},
},
},
}, nil).Once()
meta.EXPECT().SelectGrant(mock.Anything, mock.Anything, mock.Anything).Return([]*milvuspb.GrantEntity{
{
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
Grantor: &milvuspb.GrantorEntity{
Privilege: &milvuspb.PrivilegeEntity{
Name: util.PrivilegeNameForAPI(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadOnly.String()),
},
},
ObjectName: util.AnyWord,
},
}, nil).Once()
meta.EXPECT().ListCollections(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]*model.Collection{
{
DBID: 1,
CollectionID: 100,
Name: "foo",
CreateTime: tsoutil.GetCurrentTime(),
},
}, nil).Once()
task := &showCollectionTask{
baseTask: newBaseTask(context.Background(), core),
Req: &milvuspb.ShowCollectionsRequest{DbName: "default"},
Rsp: &milvuspb.ShowCollectionsResponse{},
}
ctx := GetContext(context.Background(), "foo:root")
err := task.Execute(ctx)
assert.NoError(t, err)
assert.Equal(t, 1, len(task.Rsp.GetCollectionNames()))
assert.Equal(t, "foo", task.Rsp.GetCollectionNames()[0])
})
t.Run("all collection", func(t *testing.T) {
Params.Save(Params.CommonCfg.AuthorizationEnabled.Key, "true")
defer Params.Reset(Params.CommonCfg.AuthorizationEnabled.Key)

View File

@ -290,101 +290,6 @@ var (
commonpb.ObjectPrivilege_PrivilegeAlterDatabase.String(),
commonpb.ObjectPrivilege_PrivilegeFlush.String(),
}
BuiltinPrivilegeGroups = map[string][]string{
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadOnly.String()): CollectionReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadWrite.String()): CollectionReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionAdmin.String()): CollectionAdminPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadOnly.String()): DatabaseReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadWrite.String()): DatabaseReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseAdmin.String()): DatabaseAdminPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadOnly.String()): ClusterReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadWrite.String()): ClusterReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterAdmin.String()): ClusterAdminPrivilegeGroup,
}
CollectionReadOnlyPrivilegeGroup = []string{
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeQuery.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSearch.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeIndexDetail.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetFlushState.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetLoadState.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetLoadingProgress.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeHasPartition.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeShowPartitions.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeCollection.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeAlias.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetStatistics.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListAliases.String()),
}
CollectionReadWritePrivilegeGroup = append(CollectionReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeLoad.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRelease.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeInsert.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDelete.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpsert.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeImport.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeFlush.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCompaction.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeLoadBalance.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateIndex.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropIndex.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePartition.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPartition.String()),
)
CollectionAdminPrivilegeGroup = append(CollectionReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateAlias.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropAlias.String()),
)
DatabaseReadOnlyPrivilegeGroup = []string{
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeShowCollections.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeDatabase.String()),
}
DatabaseReadWritePrivilegeGroup = append(DatabaseReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeAlterDatabase.String()),
)
DatabaseAdminPrivilegeGroup = append(DatabaseReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateCollection.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropCollection.String()),
)
ClusterReadOnlyPrivilegeGroup = []string{
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListDatabases.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSelectOwnership.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSelectUser.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeResourceGroup.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListResourceGroups.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListPrivilegeGroups.String()),
}
ClusterReadWritePrivilegeGroup = append(ClusterReadOnlyPrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeFlushAll.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeTransferNode.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeTransferReplica.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateResourceGroups.String()),
)
ClusterAdminPrivilegeGroup = append(ClusterReadWritePrivilegeGroup,
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeBackupRBAC.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRestoreRBAC.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateDatabase.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropDatabase.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateOwnership.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropOwnership.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeManageOwnership.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateResourceGroup.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropResourceGroup.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRenameCollection.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePrivilegeGroup.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPrivilegeGroup.String()),
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeOperatePrivilegeGroup.String()),
)
)
// StringSet convert array to map for conveniently check if the array contains an element

View File

@ -20,22 +20,41 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/milvus-io/milvus/pkg/util"
)
func TestRbacConfig_Init(t *testing.T) {
params := ComponentParam{}
params.Init(NewBaseTable(SkipRemote(true)))
cfg := &params.RbacConfig
assert.Equal(t, len(cfg.GetDefaultPrivilegeGroupNames()), 9)
assert.True(t, cfg.IsCollectionPrivilegeGroup("CollectionReadOnly"))
assert.False(t, cfg.IsCollectionPrivilegeGroup("DatabaseReadOnly"))
assert.Equal(t, cfg.Enabled.GetAsBool(), false)
assert.Equal(t, cfg.ClusterReadOnlyPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["ClusterReadOnly"])
assert.Equal(t, cfg.ClusterReadWritePrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["ClusterReadWrite"])
assert.Equal(t, cfg.ClusterAdminPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["ClusterAdmin"])
assert.Equal(t, cfg.DBReadOnlyPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["DatabaseReadOnly"])
assert.Equal(t, cfg.DBReadWritePrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["DatabaseReadWrite"])
assert.Equal(t, cfg.DBAdminPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["DatabaseAdmin"])
assert.Equal(t, cfg.CollectionReadOnlyPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["CollectionReadOnly"])
assert.Equal(t, cfg.CollectionReadWritePrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["CollectionReadWrite"])
assert.Equal(t, cfg.CollectionAdminPrivileges.GetAsStrings(), util.BuiltinPrivilegeGroups["CollectionAdmin"])
assert.Equal(t, cfg.ClusterReadOnlyPrivileges.GetAsStrings(), builtinPrivilegeGroups["ClusterReadOnly"])
assert.Equal(t, cfg.ClusterReadWritePrivileges.GetAsStrings(), builtinPrivilegeGroups["ClusterReadWrite"])
assert.Equal(t, cfg.ClusterAdminPrivileges.GetAsStrings(), builtinPrivilegeGroups["ClusterAdmin"])
assert.Equal(t, cfg.DBReadOnlyPrivileges.GetAsStrings(), builtinPrivilegeGroups["DatabaseReadOnly"])
assert.Equal(t, cfg.DBReadWritePrivileges.GetAsStrings(), builtinPrivilegeGroups["DatabaseReadWrite"])
assert.Equal(t, cfg.DBAdminPrivileges.GetAsStrings(), builtinPrivilegeGroups["DatabaseAdmin"])
assert.Equal(t, cfg.CollectionReadOnlyPrivileges.GetAsStrings(), builtinPrivilegeGroups["CollectionReadOnly"])
assert.Equal(t, cfg.CollectionReadWritePrivileges.GetAsStrings(), builtinPrivilegeGroups["CollectionReadWrite"])
assert.Equal(t, cfg.CollectionAdminPrivileges.GetAsStrings(), builtinPrivilegeGroups["CollectionAdmin"])
}
func TestRbacConfig_Override(t *testing.T) {
params := ComponentParam{}
params.Init(NewBaseTable(SkipRemote(true)))
clusterReadWrite := `SelectOwnership,SelectUser,DescribeResourceGroup`
params.Save(params.RbacConfig.Enabled.Key, "true")
params.Save(params.RbacConfig.ClusterReadWritePrivileges.Key, clusterReadWrite)
defer func() {
params.Reset(params.RbacConfig.Enabled.Key)
params.Reset(params.RbacConfig.ClusterReadWritePrivileges.Key)
}()
group := params.RbacConfig.GetDefaultPrivilegeGroup("ClusterReadWrite")
assert.Equal(t, len(group.Privileges), 3)
}

View File

@ -3,9 +3,110 @@ package paramtable
import (
"strings"
"github.com/samber/lo"
"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"
)
var (
builtinPrivilegeGroups = map[string][]string{
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadOnly.String()): collectionReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadWrite.String()): collectionReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionAdmin.String()): collectionAdminPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadOnly.String()): databaseReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadWrite.String()): databaseReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseAdmin.String()): databaseAdminPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadOnly.String()): clusterReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadWrite.String()): clusterReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterAdmin.String()): clusterAdminPrivilegeGroup,
}
collectionReadOnlyPrivilegeGroup = []string{
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeQuery.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSearch.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeIndexDetail.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetFlushState.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetLoadState.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetLoadingProgress.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeHasPartition.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeShowPartitions.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeCollection.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeAlias.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetStatistics.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListAliases.String()),
}
collectionReadWritePrivilegeGroup = append(collectionReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeLoad.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRelease.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeInsert.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDelete.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpsert.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeImport.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeFlush.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCompaction.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeLoadBalance.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateIndex.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropIndex.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePartition.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPartition.String()),
)
collectionAdminPrivilegeGroup = append(collectionReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateAlias.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropAlias.String()),
)
databaseReadOnlyPrivilegeGroup = []string{
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeShowCollections.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeDatabase.String()),
}
databaseReadWritePrivilegeGroup = append(databaseReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeAlterDatabase.String()),
)
databaseAdminPrivilegeGroup = append(databaseReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateCollection.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropCollection.String()),
)
clusterReadOnlyPrivilegeGroup = []string{
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListDatabases.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSelectOwnership.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeSelectUser.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeResourceGroup.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListResourceGroups.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListPrivilegeGroups.String()),
}
clusterReadWritePrivilegeGroup = append(clusterReadOnlyPrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeFlushAll.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeTransferNode.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeTransferReplica.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateResourceGroups.String()),
)
clusterAdminPrivilegeGroup = append(clusterReadWritePrivilegeGroup,
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeBackupRBAC.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRestoreRBAC.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateDatabase.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropDatabase.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateOwnership.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropOwnership.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeManageOwnership.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreateResourceGroup.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropResourceGroup.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeRenameCollection.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePrivilegeGroup.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPrivilegeGroup.String()),
util.MetaStore2API(commonpb.ObjectPrivilege_PrivilegeOperatePrivilegeGroup.String()),
)
)
type rbacConfig struct {
Enabled ParamItem `refreshable:"false"`
ClusterReadOnlyPrivileges ParamItem `refreshable:"false"`
@ -23,7 +124,7 @@ type rbacConfig struct {
func (p *rbacConfig) init(base *BaseTable) {
p.Enabled = ParamItem{
Key: "common.security.rbac.overrideBuiltInPrivilgeGroups.enabled",
Key: "common.security.rbac.overrideBuiltInPrivilegeGroups.enabled",
DefaultValue: "false",
Version: "2.4.16",
Doc: "Whether to override build-in privilege groups",
@ -33,7 +134,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.ClusterReadOnlyPrivileges = ParamItem{
Key: "common.security.rbac.cluster.readonly.privileges",
DefaultValue: strings.Join(util.ClusterReadOnlyPrivilegeGroup, ","),
DefaultValue: strings.Join(clusterReadOnlyPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Cluster level readonly privileges",
Export: true,
@ -42,7 +143,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.ClusterReadWritePrivileges = ParamItem{
Key: "common.security.rbac.cluster.readwrite.privileges",
DefaultValue: strings.Join(util.ClusterReadWritePrivilegeGroup, ","),
DefaultValue: strings.Join(clusterReadWritePrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Cluster level readwrite privileges",
Export: true,
@ -51,7 +152,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.ClusterAdminPrivileges = ParamItem{
Key: "common.security.rbac.cluster.admin.privileges",
DefaultValue: strings.Join(util.ClusterAdminPrivilegeGroup, ","),
DefaultValue: strings.Join(clusterAdminPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Cluster level admin privileges",
Export: true,
@ -60,7 +161,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.DBReadOnlyPrivileges = ParamItem{
Key: "common.security.rbac.database.readonly.privileges",
DefaultValue: strings.Join(util.DatabaseReadOnlyPrivilegeGroup, ","),
DefaultValue: strings.Join(databaseReadOnlyPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Database level readonly privileges",
Export: true,
@ -69,7 +170,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.DBReadWritePrivileges = ParamItem{
Key: "common.security.rbac.database.readwrite.privileges",
DefaultValue: strings.Join(util.DatabaseReadWritePrivilegeGroup, ","),
DefaultValue: strings.Join(databaseReadWritePrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Database level readwrite privileges",
Export: true,
@ -78,7 +179,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.DBAdminPrivileges = ParamItem{
Key: "common.security.rbac.database.admin.privileges",
DefaultValue: strings.Join(util.DatabaseAdminPrivilegeGroup, ","),
DefaultValue: strings.Join(databaseAdminPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Database level admin privileges",
Export: true,
@ -87,7 +188,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.CollectionReadOnlyPrivileges = ParamItem{
Key: "common.security.rbac.collection.readonly.privileges",
DefaultValue: strings.Join(util.CollectionReadOnlyPrivilegeGroup, ","),
DefaultValue: strings.Join(collectionReadOnlyPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Collection level readonly privileges",
Export: true,
@ -96,7 +197,7 @@ func (p *rbacConfig) init(base *BaseTable) {
p.CollectionReadWritePrivileges = ParamItem{
Key: "common.security.rbac.collection.readwrite.privileges",
DefaultValue: strings.Join(util.CollectionReadWritePrivilegeGroup, ","),
DefaultValue: strings.Join(collectionReadWritePrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Collection level readwrite privileges",
Export: true,
@ -105,10 +206,60 @@ func (p *rbacConfig) init(base *BaseTable) {
p.CollectionAdminPrivileges = ParamItem{
Key: "common.security.rbac.collection.admin.privileges",
DefaultValue: strings.Join(util.CollectionAdminPrivilegeGroup, ","),
DefaultValue: strings.Join(collectionAdminPrivilegeGroup, ","),
Version: "2.4.16",
Doc: "Collection level admin privileges",
Export: true,
}
p.CollectionAdminPrivileges.Init(base.mgr)
}
func (p *rbacConfig) GetDefaultPrivilegeGroups() []*milvuspb.PrivilegeGroupInfo {
privilegeGroupConfigs := []struct {
GroupName string
Privileges func() []string
}{
{"ClusterReadOnly", p.ClusterReadOnlyPrivileges.GetAsStrings},
{"ClusterReadWrite", p.ClusterReadWritePrivileges.GetAsStrings},
{"ClusterAdmin", p.ClusterAdminPrivileges.GetAsStrings},
{"DatabaseReadOnly", p.DBReadOnlyPrivileges.GetAsStrings},
{"DatabaseReadWrite", p.DBReadWritePrivileges.GetAsStrings},
{"DatabaseAdmin", p.DBAdminPrivileges.GetAsStrings},
{"CollectionReadOnly", p.CollectionReadOnlyPrivileges.GetAsStrings},
{"CollectionReadWrite", p.CollectionReadWritePrivileges.GetAsStrings},
{"CollectionAdmin", p.CollectionAdminPrivileges.GetAsStrings},
}
builtinGroups := make([]*milvuspb.PrivilegeGroupInfo, 0, len(privilegeGroupConfigs))
for _, config := range privilegeGroupConfigs {
privileges := lo.Map(config.Privileges(), func(name string, _ int) *milvuspb.PrivilegeEntity {
return &milvuspb.PrivilegeEntity{Name: name}
})
builtinGroups = append(builtinGroups, &milvuspb.PrivilegeGroupInfo{
GroupName: config.GroupName,
Privileges: privileges,
})
}
return builtinGroups
}
func (p *rbacConfig) GetDefaultPrivilegeGroup(privName string) *milvuspb.PrivilegeGroupInfo {
for _, group := range p.GetDefaultPrivilegeGroups() {
if group.GroupName == privName {
return group
}
}
return nil
}
func (p *rbacConfig) GetDefaultPrivilegeGroupNames() []string {
return lo.Keys(builtinPrivilegeGroups)
}
func (p *rbacConfig) IsCollectionPrivilegeGroup(privName string) bool {
collectionPrivilegeGroups := lo.PickBy(builtinPrivilegeGroups, func(groupName string, _ []string) bool {
return strings.Contains(groupName, "Collection")
})
_, exists := collectionPrivilegeGroups[privName]
return exists
}

View File

@ -68,7 +68,7 @@ func (s *PrivilegeGroupTestSuite) TestBuiltinPrivilegeGroup() {
resp, _ = s.operatePrivilege(ctx, roleName, "Admin", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
s.True(merr.Ok(resp))
for _, builtinGroup := range lo.Keys(util.BuiltinPrivilegeGroups) {
for _, builtinGroup := range paramtable.Get().RbacConfig.GetDefaultPrivilegeGroupNames() {
resp, _ = s.operatePrivilege(ctx, roleName, builtinGroup, commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
s.False(merr.Ok(resp))
}
@ -157,7 +157,7 @@ func (s *PrivilegeGroupTestSuite) TestGrantV2BuiltinPrivilegeGroup() {
s.NoError(err)
s.True(merr.Ok(createRoleResp))
for _, builtinGroup := range lo.Keys(util.BuiltinPrivilegeGroups) {
for _, builtinGroup := range paramtable.Get().RbacConfig.GetDefaultPrivilegeGroupNames() {
resp, _ := s.operatePrivilegeV2(ctx, roleName, builtinGroup, util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Grant)
s.True(merr.Ok(resp))
}
@ -314,7 +314,7 @@ func (s *PrivilegeGroupTestSuite) TestGrantV2CustomPrivilegeGroup() {
// Validate the group was dropped
listResp, err := s.Cluster.Proxy.ListPrivilegeGroups(ctx, &milvuspb.ListPrivilegeGroupsRequest{})
s.NoError(err)
s.Equal(len(util.BuiltinPrivilegeGroups), len(listResp.PrivilegeGroups))
s.Equal(len(paramtable.Get().RbacConfig.GetDefaultPrivilegeGroupNames()), len(listResp.PrivilegeGroups))
// validate edge cases
resp, _ = s.operatePrivilegeV2(ctx, role, util.AnyWord, util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Grant)