mirror of https://github.com/milvus-io/milvus.git
enhance: RBAC built in privilege groups (#37720)
issue: #37031 Signed-off-by: shaoting-huang <shaoting.huang@zilliz.com>pull/37786/head
parent
16e206167c
commit
2d72ad33f2
|
@ -814,6 +814,30 @@ common:
|
|||
# like the old password verification when updating the credential
|
||||
superUsers:
|
||||
defaultRootPassword: Milvus # default password for root user
|
||||
rbac:
|
||||
overrideBuiltInPrivilgeGroups:
|
||||
enabled: false # Whether to override build-in privilege groups
|
||||
cluster:
|
||||
readonly:
|
||||
privileges: ListDatabases,SelectOwnership,SelectUser,DescribeResourceGroup,ListResourceGroups # Cluster level readonly privileges
|
||||
readwrite:
|
||||
privileges: ListDatabases,SelectOwnership,SelectUser,DescribeResourceGroup,ListResourceGroups,FlushAll,TransferNode,TransferReplica,UpdateResourceGroups # Cluster level readwrite privileges
|
||||
admin:
|
||||
privileges: ListDatabases,SelectOwnership,SelectUser,DescribeResourceGroup,ListResourceGroups,FlushAll,TransferNode,TransferReplica,UpdateResourceGroups,BackupRBAC,RestoreRBAC,CreateDatabase,DropDatabase,CreateOwnership,DropOwnership,ManageOwnership,CreateResourceGroup,DropResourceGroup,UpdateUser # Cluster level admin privileges
|
||||
database:
|
||||
readonly:
|
||||
privileges: ShowCollections,DescribeDatabase # Database level readonly privileges
|
||||
readwrite:
|
||||
privileges: ShowCollections,DescribeDatabase,AlterDatabase # Database level readwrite privileges
|
||||
admin:
|
||||
privileges: ShowCollections,DescribeDatabase,AlterDatabase,CreateCollection,DropCollection # Database level admin privileges
|
||||
collection:
|
||||
readonly:
|
||||
privileges: Query,Search,IndexDetail,GetFlushState,GetLoadState,GetLoadingProgress,HasPartition,ShowPartitions,DescribeCollection,DescribeAlias,GetStatistics,ListAliases # Collection level readonly privileges
|
||||
readwrite:
|
||||
privileges: Query,Search,IndexDetail,GetFlushState,GetLoadState,GetLoadingProgress,HasPartition,ShowPartitions,DescribeCollection,DescribeAlias,GetStatistics,ListAliases,Load,Release,Insert,Delete,Upsert,Import,Flush,Compaction,LoadBalance,RenameCollection,CreateIndex,DropIndex,CreatePartition,DropPartition # Collection level readwrite privileges
|
||||
admin:
|
||||
privileges: Query,Search,IndexDetail,GetFlushState,GetLoadState,GetLoadingProgress,HasPartition,ShowPartitions,DescribeCollection,DescribeAlias,GetStatistics,ListAliases,Load,Release,Insert,Delete,Upsert,Import,Flush,Compaction,LoadBalance,RenameCollection,CreateIndex,DropIndex,CreatePartition,DropPartition,CreateAlias,DropAlias # Collection level admin privileges
|
||||
tlsMode: 0
|
||||
session:
|
||||
ttl: 30 # ttl value when session granting a lease to register service
|
||||
|
|
2
go.mod
2
go.mod
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/klauspost/compress v1.17.9
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c
|
||||
github.com/minio/minio-go/v7 v7.0.73
|
||||
github.com/pingcap/log v1.1.1-0.20221015072633-39906604fb81
|
||||
github.com/prometheus/client_golang v1.14.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -628,8 +628,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119 h1:9VXijWu
|
|||
github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f h1:yLxT8NH0ixUOJMqJuk0xvGf0cKsr+N2xibyTat256PI=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c h1:Ay5w6sTE1QxCydCqqW5N44EcJrMqaqbL5zcp2vclkOw=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/pulsar-client-go v0.12.1 h1:O2JZp1tsYiO7C0MQ4hrUY/aJXnn2Gry6hpm7UodghmE=
|
||||
github.com/milvus-io/pulsar-client-go v0.12.1/go.mod h1:dkutuH4oS2pXiGm+Ti7fQZ4MRjrMPZ8IJeEGAWMeckk=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
|
||||
|
|
|
@ -624,6 +624,50 @@ 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 {
|
||||
rolePrivilegesMap := Params.RoleCfg.Roles.GetAsRoleDetails()
|
||||
for role, privilegesJSON := range rolePrivilegesMap {
|
||||
|
@ -2583,24 +2627,24 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
|
|||
return merr.StatusWithErrorCode(err, commonpb.ErrorCode_OperatePrivilegeFailure), nil
|
||||
}
|
||||
|
||||
// set up privilege name for metastore
|
||||
privName := in.Entity.Grantor.Privilege.Name
|
||||
ctxLog.Debug("before PrivilegeNameForMetastore", zap.String("privilege", privName))
|
||||
if !util.IsAnyWord(privName) {
|
||||
dbPrivName, err := c.getMetastorePrivilegeName(privName)
|
||||
if err != nil {
|
||||
return merr.StatusWithErrorCode(err, commonpb.ErrorCode_OperatePrivilegeFailure), nil
|
||||
}
|
||||
in.Entity.Grantor.Privilege.Name = dbPrivName
|
||||
}
|
||||
ctxLog.Debug("after PrivilegeNameForMetastore", zap.String("privilege", privName))
|
||||
|
||||
// set up object name if it is global object type
|
||||
if in.Entity.Object.Name == commonpb.ObjectType_Global.String() {
|
||||
in.Entity.ObjectName = util.AnyWord
|
||||
}
|
||||
|
||||
privName := in.Entity.Grantor.Privilege.Name
|
||||
|
||||
redoTask := newBaseRedoTask(c.stepExecutor)
|
||||
redoTask.AddSyncStep(NewSimpleStep("operate privilege meta data", func(ctx context.Context) ([]nestedStep, error) {
|
||||
if !util.IsAnyWord(privName) {
|
||||
// set up privilege name for metastore
|
||||
dbPrivName, err := c.getMetastorePrivilegeName(privName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
in.Entity.Grantor.Privilege.Name = dbPrivName
|
||||
}
|
||||
|
||||
err := c.meta.OperatePrivilege(util.DefaultTenant, in.Entity, in.Type)
|
||||
if err != nil && !common.IsIgnorableError(err) {
|
||||
log.Warn("fail to operate the privilege", zap.Any("in", in), zap.Error(err))
|
||||
|
@ -2609,6 +2653,8 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
|
|||
return nil, nil
|
||||
}))
|
||||
redoTask.AddAsyncStep(NewSimpleStep("operate privilege cache", func(ctx context.Context) ([]nestedStep, error) {
|
||||
// set back to expand privilege group
|
||||
in.Entity.Grantor.Privilege.Name = privName
|
||||
var opType int32
|
||||
switch in.Type {
|
||||
case milvuspb.OperatePrivilegeType_Grant:
|
||||
|
@ -2619,9 +2665,23 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
|
|||
log.Warn("invalid operate type for the OperatePrivilege api", zap.Any("in", in))
|
||||
return nil, nil
|
||||
}
|
||||
grants := []*milvuspb.GrantEntity{in.Entity}
|
||||
|
||||
allGroups, err := c.meta.ListPrivilegeGroups()
|
||||
allGroups = append(allGroups, c.initBuiltinPrivilegeGroups()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groups := lo.SliceToMap(allGroups, func(group *milvuspb.PrivilegeGroupInfo) (string, []*milvuspb.PrivilegeEntity) {
|
||||
return group.GroupName, group.Privileges
|
||||
})
|
||||
expandGrants, err := c.expandPrivilegeGroups(grants, groups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.proxyClientManager.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
|
||||
OpType: opType,
|
||||
OpKey: funcutil.PolicyForPrivilege(in.Entity.Role.Name, in.Entity.Object.Name, in.Entity.ObjectName, in.Entity.Grantor.Privilege.Name, in.Entity.DbName),
|
||||
OpKey: funcutil.PolicyForPrivileges(expandGrants),
|
||||
}); err != nil {
|
||||
log.Warn("fail to refresh policy info cache", zap.Any("in", in), zap.Error(err))
|
||||
return nil, err
|
||||
|
@ -3110,8 +3170,14 @@ func (c *Core) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePr
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currGrants := c.expandPrivilegeGroups(grants, currGroups)
|
||||
newGrants := c.expandPrivilegeGroups(grants, newGroups)
|
||||
currGrants, err := c.expandPrivilegeGroups(grants, currGroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newGrants, err := c.expandPrivilegeGroups(grants, newGroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toRevoke := lo.Filter(currGrants, func(item *milvuspb.GrantEntity, _ int) bool {
|
||||
return !lo.ContainsBy(newGrants, func(newItem *milvuspb.GrantEntity) bool {
|
||||
|
@ -3175,20 +3241,42 @@ func (c *Core) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePr
|
|||
return merr.Success(), nil
|
||||
}
|
||||
|
||||
func (c *Core) expandPrivilegeGroups(grants []*milvuspb.GrantEntity, groups map[string][]*milvuspb.PrivilegeEntity) []*milvuspb.GrantEntity {
|
||||
func (c *Core) expandPrivilegeGroups(grants []*milvuspb.GrantEntity, groups map[string][]*milvuspb.PrivilegeEntity) ([]*milvuspb.GrantEntity, error) {
|
||||
newGrants := []*milvuspb.GrantEntity{}
|
||||
for _, grant := range grants {
|
||||
if groups[grant.Grantor.Privilege.Name] == nil {
|
||||
newGrants = append(newGrants, grant)
|
||||
privName := grant.Grantor.Privilege.Name
|
||||
if privGroup, exists := groups[privName]; !exists {
|
||||
metaName, err := c.getMetastorePrivilegeName(privName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newGrants = append(newGrants, &milvuspb.GrantEntity{
|
||||
Role: grant.Role,
|
||||
Object: grant.Object,
|
||||
ObjectName: grant.ObjectName,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: grant.Grantor.User,
|
||||
Privilege: &milvuspb.PrivilegeEntity{
|
||||
Name: metaName,
|
||||
},
|
||||
},
|
||||
DbName: grant.DbName,
|
||||
})
|
||||
} else {
|
||||
for _, priv := range groups[grant.Grantor.Privilege.Name] {
|
||||
for _, priv := range privGroup {
|
||||
metaName, err := c.getMetastorePrivilegeName(priv.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newGrants = append(newGrants, &milvuspb.GrantEntity{
|
||||
Role: grant.Role,
|
||||
Object: grant.Object,
|
||||
ObjectName: grant.ObjectName,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: grant.Grantor.User,
|
||||
Privilege: priv,
|
||||
User: grant.Grantor.User,
|
||||
Privilege: &milvuspb.PrivilegeEntity{
|
||||
Name: metaName,
|
||||
},
|
||||
},
|
||||
DbName: grant.DbName,
|
||||
})
|
||||
|
@ -3198,5 +3286,5 @@ func (c *Core) expandPrivilegeGroups(grants []*milvuspb.GrantEntity, groups map[
|
|||
// uniq by role + object + object name + grantor user + privilege name + db name
|
||||
return lo.UniqBy(newGrants, func(g *milvuspb.GrantEntity) string {
|
||||
return fmt.Sprintf("%s-%s-%s-%s-%s-%s", g.Role, g.Object, g.ObjectName, g.Grantor.User, g.Grantor.Privilege.Name, g.DbName)
|
||||
})
|
||||
}), nil
|
||||
}
|
||||
|
|
|
@ -2009,6 +2009,29 @@ 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) {
|
||||
|
|
|
@ -14,7 +14,7 @@ require (
|
|||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/klauspost/compress v1.17.7
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c
|
||||
github.com/nats-io/nats-server/v2 v2.10.12
|
||||
github.com/nats-io/nats.go v1.34.1
|
||||
github.com/panjf2000/ants/v2 v2.7.2
|
||||
|
|
|
@ -488,8 +488,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119 h1:9VXijWu
|
|||
github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f h1:yLxT8NH0ixUOJMqJuk0xvGf0cKsr+N2xibyTat256PI=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241111062829-6de3d96f664f/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c h1:Ay5w6sTE1QxCydCqqW5N44EcJrMqaqbL5zcp2vclkOw=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241114133823-d3506c6f465c/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/pulsar-client-go v0.12.1 h1:O2JZp1tsYiO7C0MQ4hrUY/aJXnn2Gry6hpm7UodghmE=
|
||||
github.com/milvus-io/pulsar-client-go v0.12.1/go.mod h1:dkutuH4oS2pXiGm+Ti7fQZ4MRjrMPZ8IJeEGAWMeckk=
|
||||
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
||||
|
|
|
@ -160,6 +160,15 @@ var (
|
|||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListPrivilegeGroups.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeOperatePrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadOnly.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterReadWrite.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupClusterAdmin.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadOnly.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseReadWrite.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupDatabaseAdmin.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadOnly.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionReadWrite.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupCollectionAdmin.String()),
|
||||
},
|
||||
commonpb.ObjectType_User.String(): {
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()),
|
||||
|
@ -283,6 +292,97 @@ 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_PrivilegeRenameCollection.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()),
|
||||
}
|
||||
|
||||
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()),
|
||||
)
|
||||
)
|
||||
|
||||
// StringSet convert array to map for conveniently check if the array contains an element
|
||||
|
@ -344,6 +444,12 @@ func IsPrivilegeNameDefined(name string) bool {
|
|||
return PrivilegeNameForMetastore(name) != ""
|
||||
}
|
||||
|
||||
func IsBuiltinPrivilegeGroup(name string) bool {
|
||||
dbPrivilege := PrivilegeGroupWord + name
|
||||
_, ok := commonpb.ObjectPrivilege_value[dbPrivilege]
|
||||
return ok
|
||||
}
|
||||
|
||||
func PrivilegeGroupNameForMetastore(name string) string {
|
||||
return PrivilegeGroupWord + name
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ type ComponentParam struct {
|
|||
HTTPCfg httpConfig
|
||||
LogCfg logConfig
|
||||
RoleCfg roleConfig
|
||||
RbacConfig rbacConfig
|
||||
StreamingCfg streamingConfig
|
||||
|
||||
RootCoordGrpcServerCfg GrpcServerConfig
|
||||
|
@ -134,6 +135,7 @@ func (p *ComponentParam) init(bt *BaseTable) {
|
|||
p.HTTPCfg.init(bt)
|
||||
p.LogCfg.init(bt)
|
||||
p.RoleCfg.init(bt)
|
||||
p.RbacConfig.init(bt)
|
||||
p.GpuConfig.init(bt)
|
||||
p.KnowhereConfig.init(bt)
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// 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 paramtable
|
||||
|
||||
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 := ¶ms.RbacConfig
|
||||
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"])
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package paramtable
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/milvus-io/milvus/pkg/util"
|
||||
)
|
||||
|
||||
type rbacConfig struct {
|
||||
Enabled ParamItem `refreshable:"false"`
|
||||
ClusterReadOnlyPrivileges ParamItem `refreshable:"false"`
|
||||
ClusterReadWritePrivileges ParamItem `refreshable:"false"`
|
||||
ClusterAdminPrivileges ParamItem `refreshable:"false"`
|
||||
|
||||
DBReadOnlyPrivileges ParamItem `refreshable:"false"`
|
||||
DBReadWritePrivileges ParamItem `refreshable:"false"`
|
||||
DBAdminPrivileges ParamItem `refreshable:"false"`
|
||||
|
||||
CollectionReadOnlyPrivileges ParamItem `refreshable:"false"`
|
||||
CollectionReadWritePrivileges ParamItem `refreshable:"false"`
|
||||
CollectionAdminPrivileges ParamItem `refreshable:"false"`
|
||||
}
|
||||
|
||||
func (p *rbacConfig) init(base *BaseTable) {
|
||||
p.Enabled = ParamItem{
|
||||
Key: "common.security.rbac.overrideBuiltInPrivilgeGroups.enabled",
|
||||
DefaultValue: "false",
|
||||
Version: "2.4.16",
|
||||
Doc: "Whether to override build-in privilege groups",
|
||||
Export: true,
|
||||
}
|
||||
p.Enabled.Init(base.mgr)
|
||||
|
||||
p.ClusterReadOnlyPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.cluster.readonly.privileges",
|
||||
DefaultValue: strings.Join(util.ClusterReadOnlyPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Cluster level readonly privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.ClusterReadOnlyPrivileges.Init(base.mgr)
|
||||
|
||||
p.ClusterReadWritePrivileges = ParamItem{
|
||||
Key: "common.security.rbac.cluster.readwrite.privileges",
|
||||
DefaultValue: strings.Join(util.ClusterReadWritePrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Cluster level readwrite privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.ClusterReadWritePrivileges.Init(base.mgr)
|
||||
|
||||
p.ClusterAdminPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.cluster.admin.privileges",
|
||||
DefaultValue: strings.Join(util.ClusterAdminPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Cluster level admin privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.ClusterAdminPrivileges.Init(base.mgr)
|
||||
|
||||
p.DBReadOnlyPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.database.readonly.privileges",
|
||||
DefaultValue: strings.Join(util.DatabaseReadOnlyPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Database level readonly privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.DBReadOnlyPrivileges.Init(base.mgr)
|
||||
|
||||
p.DBReadWritePrivileges = ParamItem{
|
||||
Key: "common.security.rbac.database.readwrite.privileges",
|
||||
DefaultValue: strings.Join(util.DatabaseReadWritePrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Database level readwrite privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.DBReadWritePrivileges.Init(base.mgr)
|
||||
|
||||
p.DBAdminPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.database.admin.privileges",
|
||||
DefaultValue: strings.Join(util.DatabaseAdminPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Database level admin privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.DBAdminPrivileges.Init(base.mgr)
|
||||
|
||||
p.CollectionReadOnlyPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.collection.readonly.privileges",
|
||||
DefaultValue: strings.Join(util.CollectionReadOnlyPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Collection level readonly privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.CollectionReadOnlyPrivileges.Init(base.mgr)
|
||||
|
||||
p.CollectionReadWritePrivileges = ParamItem{
|
||||
Key: "common.security.rbac.collection.readwrite.privileges",
|
||||
DefaultValue: strings.Join(util.CollectionReadWritePrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Collection level readwrite privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.CollectionReadWritePrivileges.Init(base.mgr)
|
||||
|
||||
p.CollectionAdminPrivileges = ParamItem{
|
||||
Key: "common.security.rbac.collection.admin.privileges",
|
||||
DefaultValue: strings.Join(util.CollectionAdminPrivilegeGroup, ","),
|
||||
Version: "2.4.16",
|
||||
Doc: "Collection level admin privileges",
|
||||
Export: true,
|
||||
}
|
||||
p.CollectionAdminPrivileges.Init(base.mgr)
|
||||
}
|
|
@ -63,7 +63,17 @@ func (s *PrivilegeGroupTestSuite) TestBuiltinPrivilegeGroup() {
|
|||
s.operatePrivilege(ctx, roleName, "ReadWrite", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "Admin", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
|
||||
s.validateGrants(ctx, roleName, commonpb.ObjectType_Global.String(), 1)
|
||||
s.operatePrivilege(ctx, roleName, "ClusterReadOnly", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "ClusterReadWrite", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "ClusterAdmin", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "DatabaseReadOnly", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "DatabaseReadWrite", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "DatabaseAdmin", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "CollectionReadOnly", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "CollectionReadWrite", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.operatePrivilege(ctx, roleName, "CollectionAdmin", commonpb.ObjectType_Global.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
|
||||
s.validateGrants(ctx, roleName, commonpb.ObjectType_Global.String(), 10)
|
||||
s.validateGrants(ctx, roleName, commonpb.ObjectType_Collection.String(), 2)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue