Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance: RBAC built in privilege groups #37720

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions configs/milvus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
132 changes: 110 additions & 22 deletions internal/rootcoord/root_coord.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,50 @@
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

Check warning on line 653 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L652-L653

Added lines #L652 - L653 were not covered by tests
}
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 {
Expand Down Expand Up @@ -2583,24 +2627,24 @@
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
}

Check warning on line 2644 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L2643-L2644

Added lines #L2643 - L2644 were not covered by tests
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))
Expand All @@ -2609,6 +2653,8 @@
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:
Expand All @@ -2619,9 +2665,23 @@
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
}

Check warning on line 2674 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L2673-L2674

Added lines #L2673 - L2674 were not covered by tests
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
Expand Down Expand Up @@ -3110,8 +3170,14 @@
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
}

Check warning on line 3176 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L3175-L3176

Added lines #L3175 - L3176 were not covered by tests
newGrants, err := c.expandPrivilegeGroups(grants, newGroups)
if err != nil {
return nil, err
}

Check warning on line 3180 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L3179-L3180

Added lines #L3179 - L3180 were not covered by tests

toRevoke := lo.Filter(currGrants, func(item *milvuspb.GrantEntity, _ int) bool {
return !lo.ContainsBy(newGrants, func(newItem *milvuspb.GrantEntity) bool {
Expand Down Expand Up @@ -3175,20 +3241,42 @@
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
}

Check warning on line 3270 in internal/rootcoord/root_coord.go

View check run for this annotation

Codecov / codecov/patch

internal/rootcoord/root_coord.go#L3269-L3270

Added lines #L3269 - L3270 were not covered by tests
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,
})
Expand All @@ -3198,5 +3286,5 @@
// 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
}
23 changes: 23 additions & 0 deletions internal/rootcoord/root_coord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pkg/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
Loading
Loading