mirror of https://github.com/milvus-io/milvus.git
enhance: Support custom privilege group for RBAC (#37087)
issue: #37031 --------- Signed-off-by: shaoting-huang <shaoting.huang@zilliz.com>pull/37558/head
parent
ff9bdf7029
commit
70605cf5b3
|
@ -13,7 +13,6 @@ require (
|
|||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tidwall/gjson v1.17.1
|
||||
go.uber.org/atomic v1.10.0
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
)
|
||||
|
@ -109,6 +108,7 @@ require (
|
|||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.20.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
|
|
3
go.mod
3
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.20241106083218-5de5d0cfb1c1
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620
|
||||
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
|
||||
|
@ -138,6 +138,7 @@ require (
|
|||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/flatbuffers v2.0.8+incompatible // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -363,8 +363,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -627,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.20241106083218-5de5d0cfb1c1 h1:GFS5AxKPcEstcfJgMGxRH+l/mKA0kK1sHDOxnOqMnoA=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241106083218-5de5d0cfb1c1/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620 h1:0IWUDtDloift7cQHalhdjuVkL/3qSeiXFqR7MofZBkg=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620/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=
|
||||
|
@ -1323,6 +1324,7 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
|
|
|
@ -686,6 +686,22 @@ func (m *mockRootCoordClient) ListPolicy(ctx context.Context, in *internalpb.Lis
|
|||
return &internalpb.ListPolicyResponse{Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}}, nil
|
||||
}
|
||||
|
||||
func (m *mockRootCoordClient) CreatePrivilegeGroup(ctx context.Context, req *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockRootCoordClient) DropPrivilegeGroup(ctx context.Context, req *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockRootCoordClient) ListPrivilegeGroups(ctx context.Context, req *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockRootCoordClient) OperatePrivilegeGroup(ctx context.Context, req *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
type mockHandler struct {
|
||||
meta *meta
|
||||
}
|
||||
|
|
|
@ -20,10 +20,9 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/milvus-io/milvus/pkg/config"
|
||||
"github.com/milvus-io/milvus/pkg/util/paramtable"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestResizePools(t *testing.T) {
|
||||
|
|
|
@ -9,14 +9,15 @@ import (
|
|||
// v2
|
||||
const (
|
||||
// --- category ---
|
||||
CollectionCategory = "/collections/"
|
||||
EntityCategory = "/entities/"
|
||||
PartitionCategory = "/partitions/"
|
||||
UserCategory = "/users/"
|
||||
RoleCategory = "/roles/"
|
||||
IndexCategory = "/indexes/"
|
||||
AliasCategory = "/aliases/"
|
||||
ImportJobCategory = "/jobs/import/"
|
||||
CollectionCategory = "/collections/"
|
||||
EntityCategory = "/entities/"
|
||||
PartitionCategory = "/partitions/"
|
||||
UserCategory = "/users/"
|
||||
RoleCategory = "/roles/"
|
||||
IndexCategory = "/indexes/"
|
||||
AliasCategory = "/aliases/"
|
||||
ImportJobCategory = "/jobs/import/"
|
||||
PrivilegeGroupCategory = "/privilege_groups/"
|
||||
|
||||
ListAction = "list"
|
||||
HasAction = "has"
|
||||
|
@ -37,13 +38,15 @@ const (
|
|||
AdvancedSearchAction = "advanced_search"
|
||||
HybridSearchAction = "hybrid_search"
|
||||
|
||||
UpdatePasswordAction = "update_password"
|
||||
GrantRoleAction = "grant_role"
|
||||
RevokeRoleAction = "revoke_role"
|
||||
GrantPrivilegeAction = "grant_privilege"
|
||||
RevokePrivilegeAction = "revoke_privilege"
|
||||
AlterAction = "alter"
|
||||
GetProgressAction = "get_progress" // deprecated, keep it for compatibility, use `/v2/vectordb/jobs/import/describe` instead
|
||||
UpdatePasswordAction = "update_password"
|
||||
GrantRoleAction = "grant_role"
|
||||
RevokeRoleAction = "revoke_role"
|
||||
GrantPrivilegeAction = "grant_privilege"
|
||||
RevokePrivilegeAction = "revoke_privilege"
|
||||
AlterAction = "alter"
|
||||
GetProgressAction = "get_progress" // deprecated, keep it for compatibility, use `/v2/vectordb/jobs/import/describe` instead
|
||||
AddPrivilegesToGroupAction = "add_privileges_to_group"
|
||||
RemovePrivilegesFromGroupAction = "remove_privileges_from_group"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -125,11 +128,14 @@ const (
|
|||
|
||||
HTTPReturnRowCount = "rowCount"
|
||||
|
||||
HTTPReturnObjectType = "objectType"
|
||||
HTTPReturnObjectName = "objectName"
|
||||
HTTPReturnPrivilege = "privilege"
|
||||
HTTPReturnGrantor = "grantor"
|
||||
HTTPReturnDbName = "dbName"
|
||||
HTTPReturnObjectType = "objectType"
|
||||
HTTPReturnObjectName = "objectName"
|
||||
HTTPReturnPrivilege = "privilege"
|
||||
HTTPReturnGrantor = "grantor"
|
||||
HTTPReturnDbName = "dbName"
|
||||
HTTPReturnPrivilegeGroupName = "privilegeGroupName"
|
||||
HTTPReturnPrivileges = "privileges"
|
||||
HTTPReturnPrivilegeGroups = "privilegeGroups"
|
||||
|
||||
DefaultMetricType = metric.COSINE
|
||||
DefaultPrimaryFieldName = "id"
|
||||
|
|
|
@ -132,6 +132,13 @@ func (h *HandlersV2) RegisterRoutesToV2(router gin.IRouter) {
|
|||
router.POST(RoleCategory+GrantPrivilegeAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.addPrivilegeToRole))))
|
||||
router.POST(RoleCategory+RevokePrivilegeAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.removePrivilegeFromRole))))
|
||||
|
||||
// privilege group
|
||||
router.POST(PrivilegeGroupCategory+CreateAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.createPrivilegeGroup))))
|
||||
router.POST(PrivilegeGroupCategory+DropAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.dropPrivilegeGroup))))
|
||||
router.POST(PrivilegeGroupCategory+ListAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.listPrivilegeGroups))))
|
||||
router.POST(PrivilegeGroupCategory+AddPrivilegesToGroupAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.addPrivilegesToGroup))))
|
||||
router.POST(PrivilegeGroupCategory+RemovePrivilegesFromGroupAction, timeoutMiddleware(wrapperPost(func() any { return &GrantReq{} }, wrapperTraceLog(h.removePrivilegesFromGroup))))
|
||||
|
||||
router.POST(IndexCategory+ListAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionNameReq{} }, wrapperTraceLog(h.wrapperCheckDatabase(h.listIndexes)))))
|
||||
router.POST(IndexCategory+DescribeAction, timeoutMiddleware(wrapperPost(func() any { return &IndexReq{} }, wrapperTraceLog(h.wrapperCheckDatabase(h.describeIndex)))))
|
||||
|
||||
|
@ -1786,6 +1793,83 @@ func (h *HandlersV2) removePrivilegeFromRole(ctx context.Context, c *gin.Context
|
|||
return h.operatePrivilegeToRole(ctx, c, anyReq.(*GrantReq), milvuspb.OperatePrivilegeType_Revoke, dbName)
|
||||
}
|
||||
|
||||
func (h *HandlersV2) createPrivilegeGroup(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
httpReq := anyReq.(*PrivilegeGroupReq)
|
||||
req := &milvuspb.CreatePrivilegeGroupRequest{
|
||||
GroupName: httpReq.PrivilegeGroupName,
|
||||
}
|
||||
resp, err := wrapperProxy(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/CreatePrivilegeGroup", func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.CreatePrivilegeGroup(reqCtx, req.(*milvuspb.CreatePrivilegeGroupRequest))
|
||||
})
|
||||
if err == nil {
|
||||
HTTPReturn(c, http.StatusOK, wrapperReturnDefault())
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (h *HandlersV2) dropPrivilegeGroup(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
httpReq := anyReq.(*PrivilegeGroupReq)
|
||||
req := &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: httpReq.PrivilegeGroupName,
|
||||
}
|
||||
resp, err := wrapperProxy(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/DropPrivilegeGroup", func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.DropPrivilegeGroup(reqCtx, req.(*milvuspb.DropPrivilegeGroupRequest))
|
||||
})
|
||||
if err == nil {
|
||||
HTTPReturn(c, http.StatusOK, wrapperReturnDefault())
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (h *HandlersV2) listPrivilegeGroups(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
req := &milvuspb.ListPrivilegeGroupsRequest{}
|
||||
resp, err := wrapperProxy(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/ListPrivilegeGroups", func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.ListPrivilegeGroups(reqCtx, req.(*milvuspb.ListPrivilegeGroupsRequest))
|
||||
})
|
||||
if err == nil {
|
||||
privGroups := make([]map[string]interface{}, 0)
|
||||
for _, group := range resp.(*milvuspb.ListPrivilegeGroupsResponse).PrivilegeGroups {
|
||||
privileges := make([]string, len(group.Privileges))
|
||||
for i, privilege := range group.Privileges {
|
||||
privileges[i] = privilege.Name
|
||||
}
|
||||
groupInfo := map[string]interface{}{
|
||||
HTTPReturnPrivilegeGroupName: group.GroupName,
|
||||
HTTPReturnPrivileges: strings.Join(privileges, ","),
|
||||
}
|
||||
privGroups = append(privGroups, groupInfo)
|
||||
}
|
||||
HTTPReturn(c, http.StatusOK, gin.H{HTTPReturnCode: merr.Code(nil), HTTPReturnData: gin.H{
|
||||
HTTPReturnPrivilegeGroups: privGroups,
|
||||
}})
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (h *HandlersV2) addPrivilegesToGroup(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
return h.operatePrivilegeGroup(ctx, c, anyReq, dbName, milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup)
|
||||
}
|
||||
|
||||
func (h *HandlersV2) removePrivilegesFromGroup(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
return h.operatePrivilegeGroup(ctx, c, anyReq, dbName, milvuspb.OperatePrivilegeGroupType_RemovePrivilegesFromGroup)
|
||||
}
|
||||
|
||||
func (h *HandlersV2) operatePrivilegeGroup(ctx context.Context, c *gin.Context, anyReq any, dbName string, operateType milvuspb.OperatePrivilegeGroupType) (interface{}, error) {
|
||||
httpReq := anyReq.(*PrivilegeGroupReq)
|
||||
req := &milvuspb.OperatePrivilegeGroupRequest{
|
||||
GroupName: httpReq.PrivilegeGroupName,
|
||||
Privileges: httpReq.Privileges,
|
||||
Type: operateType,
|
||||
}
|
||||
resp, err := wrapperProxy(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/OperatePrivilegeGroup", func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.OperatePrivilegeGroup(reqCtx, req.(*milvuspb.OperatePrivilegeGroupRequest))
|
||||
})
|
||||
if err == nil {
|
||||
HTTPReturn(c, http.StatusOK, wrapperReturnDefault())
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (h *HandlersV2) listIndexes(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) {
|
||||
collectionGetter, _ := anyReq.(requestutil.CollectionNameGetter)
|
||||
indexNames := []string{}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"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/merr"
|
||||
)
|
||||
|
||||
|
@ -273,6 +274,11 @@ func (req *RoleReq) GetRoleName() string {
|
|||
return req.RoleName
|
||||
}
|
||||
|
||||
type PrivilegeGroupReq struct {
|
||||
PrivilegeGroupName string `json:"privilegeGroupName" binding:"required"`
|
||||
Privileges []*milvuspb.PrivilegeEntity `json:"privileges"`
|
||||
}
|
||||
|
||||
type GrantReq struct {
|
||||
RoleName string `json:"roleName" binding:"required"`
|
||||
ObjectType string `json:"objectType" binding:"required"`
|
||||
|
|
|
@ -997,6 +997,22 @@ func (s *Server) RestoreRBAC(ctx context.Context, req *milvuspb.RestoreRBACMetaR
|
|||
return s.proxy.RestoreRBAC(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Server) CreatePrivilegeGroup(ctx context.Context, req *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.proxy.CreatePrivilegeGroup(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Server) DropPrivilegeGroup(ctx context.Context, req *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.proxy.DropPrivilegeGroup(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Server) ListPrivilegeGroups(ctx context.Context, req *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
return s.proxy.ListPrivilegeGroups(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Server) OperatePrivilegeGroup(ctx context.Context, req *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.proxy.OperatePrivilegeGroup(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Server) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
|
||||
return s.proxy.RefreshPolicyInfoCache(ctx, req)
|
||||
}
|
||||
|
|
|
@ -706,3 +706,51 @@ func (c *Client) RestoreRBAC(ctx context.Context, in *milvuspb.RestoreRBACMetaRe
|
|||
return client.RestoreRBAC(ctx, in)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) CreatePrivilegeGroup(ctx context.Context, in *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
in = typeutil.Clone(in)
|
||||
commonpbutil.UpdateMsgBase(
|
||||
in.GetBase(),
|
||||
commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.sess.ServerID)),
|
||||
)
|
||||
|
||||
return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*commonpb.Status, error) {
|
||||
return client.CreatePrivilegeGroup(ctx, in)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) DropPrivilegeGroup(ctx context.Context, in *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
in = typeutil.Clone(in)
|
||||
commonpbutil.UpdateMsgBase(
|
||||
in.GetBase(),
|
||||
commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.sess.ServerID)),
|
||||
)
|
||||
|
||||
return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*commonpb.Status, error) {
|
||||
return client.DropPrivilegeGroup(ctx, in)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) ListPrivilegeGroups(ctx context.Context, in *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
in = typeutil.Clone(in)
|
||||
commonpbutil.UpdateMsgBase(
|
||||
in.GetBase(),
|
||||
commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.sess.ServerID)),
|
||||
)
|
||||
|
||||
return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
return client.ListPrivilegeGroups(ctx, in)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
in = typeutil.Clone(in)
|
||||
commonpbutil.UpdateMsgBase(
|
||||
in.GetBase(),
|
||||
commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.sess.ServerID)),
|
||||
)
|
||||
|
||||
return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*commonpb.Status, error) {
|
||||
return client.OperatePrivilegeGroup(ctx, in)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -240,10 +240,38 @@ func Test_NewClient(t *testing.T) {
|
|||
r, err := client.ListDatabases(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.AlterCollection(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.AlterDatabase(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.BackupRBAC(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.RestoreRBAC(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.CreatePrivilegeGroup(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.DropPrivilegeGroup(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.ListPrivilegeGroups(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
{
|
||||
r, err := client.OperatePrivilegeGroup(ctx, nil)
|
||||
retCheck(retNotNil, r, err)
|
||||
}
|
||||
}
|
||||
|
||||
client.(*Client).grpcClient = &mock.GRPCClientBase[rootcoordpb.RootCoordClient]{
|
||||
|
|
|
@ -550,3 +550,19 @@ func (s *Server) BackupRBAC(ctx context.Context, request *milvuspb.BackupRBACMet
|
|||
func (s *Server) RestoreRBAC(ctx context.Context, request *milvuspb.RestoreRBACMetaRequest) (*commonpb.Status, error) {
|
||||
return s.rootCoord.RestoreRBAC(ctx, request)
|
||||
}
|
||||
|
||||
func (s *Server) CreatePrivilegeGroup(ctx context.Context, request *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.rootCoord.CreatePrivilegeGroup(ctx, request)
|
||||
}
|
||||
|
||||
func (s *Server) DropPrivilegeGroup(ctx context.Context, request *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.rootCoord.DropPrivilegeGroup(ctx, request)
|
||||
}
|
||||
|
||||
func (s *Server) ListPrivilegeGroups(ctx context.Context, request *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
return s.rootCoord.ListPrivilegeGroups(ctx, request)
|
||||
}
|
||||
|
||||
func (s *Server) OperatePrivilegeGroup(ctx context.Context, request *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
return s.rootCoord.OperatePrivilegeGroup(ctx, request)
|
||||
}
|
||||
|
|
|
@ -86,6 +86,11 @@ type RootCoordCatalog interface {
|
|||
BackupRBAC(ctx context.Context, tenant string) (*milvuspb.RBACMeta, error)
|
||||
RestoreRBAC(ctx context.Context, tenant string, meta *milvuspb.RBACMeta) error
|
||||
|
||||
GetPrivilegeGroup(ctx context.Context, groupName string) (*milvuspb.PrivilegeGroupInfo, error)
|
||||
DropPrivilegeGroup(ctx context.Context, groupName string) error
|
||||
SavePrivilegeGroup(ctx context.Context, data *milvuspb.PrivilegeGroupInfo) error
|
||||
ListPrivilegeGroups(ctx context.Context) ([]*milvuspb.PrivilegeGroupInfo, error)
|
||||
|
||||
Close()
|
||||
}
|
||||
|
||||
|
|
|
@ -1332,10 +1332,16 @@ func (kc *Catalog) BackupRBAC(ctx context.Context, tenant string) (*milvuspb.RBA
|
|||
grantsEntity = append(grantsEntity, grants...)
|
||||
}
|
||||
|
||||
privGroups, err := kc.ListPrivilegeGroups(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &milvuspb.RBACMeta{
|
||||
Users: userInfos,
|
||||
Roles: roleEntity,
|
||||
Grants: grantsEntity,
|
||||
Users: userInfos,
|
||||
Roles: roleEntity,
|
||||
Grants: grantsEntity,
|
||||
PrivilegeGroups: privGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1344,6 +1350,7 @@ func (kc *Catalog) RestoreRBAC(ctx context.Context, tenant string, meta *milvusp
|
|||
needRollbackUser := make([]*milvuspb.UserInfo, 0)
|
||||
needRollbackRole := make([]*milvuspb.RoleEntity, 0)
|
||||
needRollbackGrants := make([]*milvuspb.GrantEntity, 0)
|
||||
needRollbackPrivilegeGroups := make([]*milvuspb.PrivilegeGroupInfo, 0)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.Warn("failed to restore rbac, try to rollback", zap.Error(err))
|
||||
|
@ -1370,6 +1377,14 @@ func (kc *Catalog) RestoreRBAC(ctx context.Context, tenant string, meta *milvusp
|
|||
log.Warn("failed to rollback users after restore failed", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// roll back privilege group
|
||||
for _, group := range needRollbackPrivilegeGroups {
|
||||
err = kc.DropPrivilegeGroup(ctx, group.GroupName)
|
||||
if err != nil {
|
||||
log.Warn("failed to rollback privilege groups after restore failed", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -1392,9 +1407,42 @@ func (kc *Catalog) RestoreRBAC(ctx context.Context, tenant string, meta *milvusp
|
|||
needRollbackRole = append(needRollbackRole, role)
|
||||
}
|
||||
|
||||
// restore grant
|
||||
// restore privilege group
|
||||
existPrivGroups, err := kc.ListPrivilegeGroups(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existPrivGroupMap := lo.SliceToMap(existPrivGroups, func(entity *milvuspb.PrivilegeGroupInfo) (string, struct{}) { return entity.GroupName, struct{}{} })
|
||||
for _, group := range meta.PrivilegeGroups {
|
||||
if _, ok := existPrivGroupMap[group.GroupName]; ok {
|
||||
log.Warn("failed to restore, privilege group already exists", zap.String("group", group.GroupName))
|
||||
err = errors.Newf("privilege group [%s] already exists", group.GroupName)
|
||||
return err
|
||||
}
|
||||
err = kc.SavePrivilegeGroup(ctx, group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
needRollbackPrivilegeGroups = append(needRollbackPrivilegeGroups, group)
|
||||
}
|
||||
|
||||
// restore grant, list latest privilege group first
|
||||
existPrivGroups, err = kc.ListPrivilegeGroups(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existPrivGroupMap = lo.SliceToMap(existPrivGroups, func(entity *milvuspb.PrivilegeGroupInfo) (string, struct{}) { return entity.GroupName, struct{}{} })
|
||||
for _, grant := range meta.Grants {
|
||||
grant.Grantor.Privilege.Name = util.PrivilegeNameForMetastore(grant.Grantor.Privilege.Name)
|
||||
privName := grant.Grantor.Privilege.Name
|
||||
if util.IsPrivilegeNameDefined(privName) {
|
||||
grant.Grantor.Privilege.Name = util.PrivilegeNameForMetastore(privName)
|
||||
} else if _, ok := existPrivGroupMap[privName]; ok {
|
||||
grant.Grantor.Privilege.Name = util.PrivilegeGroupNameForMetastore(privName)
|
||||
} else {
|
||||
log.Warn("failed to restore, privilege group does not exist", zap.String("group", privName))
|
||||
err = errors.Newf("privilege group [%s] does not exist", privName)
|
||||
return err
|
||||
}
|
||||
err = kc.AlterGrant(ctx, tenant, grant, milvuspb.OperatePrivilegeType_Grant)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1439,6 +1487,72 @@ func (kc *Catalog) RestoreRBAC(ctx context.Context, tenant string, meta *milvusp
|
|||
return err
|
||||
}
|
||||
|
||||
func (kc *Catalog) GetPrivilegeGroup(ctx context.Context, groupName string) (*milvuspb.PrivilegeGroupInfo, error) {
|
||||
k := BuildPrivilegeGroupkey(groupName)
|
||||
val, err := kc.Txn.Load(k)
|
||||
if err != nil {
|
||||
if errors.Is(err, merr.ErrIoKeyNotFound) {
|
||||
return nil, fmt.Errorf("privilege group [%s] does not exist", groupName)
|
||||
}
|
||||
log.Error("failed to load privilege group", zap.String("group", groupName), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
privGroupInfo := &milvuspb.PrivilegeGroupInfo{}
|
||||
err = proto.Unmarshal([]byte(val), privGroupInfo)
|
||||
if err != nil {
|
||||
log.Error("failed to unmarshal privilege group info", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return privGroupInfo, nil
|
||||
}
|
||||
|
||||
func (kc *Catalog) DropPrivilegeGroup(ctx context.Context, groupName string) error {
|
||||
k := BuildPrivilegeGroupkey(groupName)
|
||||
err := kc.Txn.Remove(k)
|
||||
if err != nil {
|
||||
log.Warn("fail to drop privilege group", zap.String("key", k), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kc *Catalog) SavePrivilegeGroup(ctx context.Context, data *milvuspb.PrivilegeGroupInfo) error {
|
||||
k := BuildPrivilegeGroupkey(data.GroupName)
|
||||
groupInfo := &milvuspb.PrivilegeGroupInfo{
|
||||
GroupName: data.GroupName,
|
||||
Privileges: lo.Uniq(data.Privileges),
|
||||
}
|
||||
v, err := proto.Marshal(groupInfo)
|
||||
if err != nil {
|
||||
log.Error("failed to marshal privilege group info", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if err = kc.Txn.Save(k, string(v)); err != nil {
|
||||
log.Warn("fail to put privilege group", zap.String("key", k), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kc *Catalog) ListPrivilegeGroups(ctx context.Context) ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
_, vals, err := kc.Txn.LoadWithPrefix(PrivilegeGroupPrefix)
|
||||
if err != nil {
|
||||
log.Error("failed to list privilege groups", zap.String("prefix", PrivilegeGroupPrefix), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
privGroups := make([]*milvuspb.PrivilegeGroupInfo, 0, len(vals))
|
||||
for _, val := range vals {
|
||||
privGroupInfo := &milvuspb.PrivilegeGroupInfo{}
|
||||
err = proto.Unmarshal([]byte(val), privGroupInfo)
|
||||
if err != nil {
|
||||
log.Error("failed to unmarshal privilege group info", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
privGroups = append(privGroups, privGroupInfo)
|
||||
}
|
||||
return privGroups, nil
|
||||
}
|
||||
|
||||
func (kc *Catalog) Close() {
|
||||
// do nothing
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -2701,6 +2702,11 @@ func TestRBAC_Backup(t *testing.T) {
|
|||
})
|
||||
c.AlterUserRole(ctx, util.DefaultTenant, &milvuspb.UserEntity{Name: "user1"}, &milvuspb.RoleEntity{Name: "role1"}, milvuspb.OperateUserRoleType_AddUserToRole)
|
||||
|
||||
c.SavePrivilegeGroup(ctx, &milvuspb.PrivilegeGroupInfo{
|
||||
GroupName: "custom_group",
|
||||
Privileges: []*milvuspb.PrivilegeEntity{{Name: "CreateCollection"}},
|
||||
})
|
||||
|
||||
// test backup success
|
||||
backup, err := c.BackupRBAC(ctx, util.DefaultTenant)
|
||||
assert.NoError(t, err)
|
||||
|
@ -2711,6 +2717,9 @@ func TestRBAC_Backup(t *testing.T) {
|
|||
assert.Equal(t, "user1", backup.Users[0].User)
|
||||
assert.Equal(t, 1, len(backup.Users[0].Roles))
|
||||
assert.Equal(t, 1, len(backup.Roles))
|
||||
assert.Equal(t, 1, len(backup.PrivilegeGroups))
|
||||
assert.Equal(t, "custom_group", backup.PrivilegeGroups[0].GroupName)
|
||||
assert.Equal(t, "CreateCollection", backup.PrivilegeGroups[0].Privileges[0].Name)
|
||||
}
|
||||
|
||||
func TestRBAC_Restore(t *testing.T) {
|
||||
|
@ -2756,10 +2765,17 @@ func TestRBAC_Restore(t *testing.T) {
|
|||
DbName: util.DefaultDBName,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: "user1"},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "PrivilegeLoad"},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Load"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
PrivilegeGroups: []*milvuspb.PrivilegeGroupInfo{
|
||||
{
|
||||
GroupName: "custom_group",
|
||||
Privileges: []*milvuspb.PrivilegeEntity{{Name: "CreateCollection"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
// test restore success
|
||||
err := c.RestoreRBAC(ctx, util.DefaultTenant, rbacMeta)
|
||||
|
@ -2785,6 +2801,13 @@ func TestRBAC_Restore(t *testing.T) {
|
|||
assert.Equal(t, "obj_name1", grants[0].ObjectName)
|
||||
assert.Equal(t, "role1", grants[0].Role.Name)
|
||||
assert.Equal(t, "user1", grants[0].Grantor.User.Name)
|
||||
assert.Equal(t, "Load", grants[0].Grantor.Privilege.Name)
|
||||
// check privilege group
|
||||
privGroups, err := c.ListPrivilegeGroups(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, privGroups, 1)
|
||||
assert.Equal(t, "custom_group", privGroups[0].GroupName)
|
||||
assert.Equal(t, "CreateCollection", privGroups[0].Privileges[0].Name)
|
||||
|
||||
rbacMeta2 := &milvuspb.RBACMeta{
|
||||
Users: []*milvuspb.UserInfo{
|
||||
|
@ -2821,10 +2844,17 @@ func TestRBAC_Restore(t *testing.T) {
|
|||
DbName: util.DefaultDBName,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: "user2"},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "PrivilegeLoad"},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Load"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
PrivilegeGroups: []*milvuspb.PrivilegeGroupInfo{
|
||||
{
|
||||
GroupName: "custom_group2",
|
||||
Privileges: []*milvuspb.PrivilegeEntity{{Name: "DropCollection"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// test restore failed and roll back
|
||||
|
@ -2846,6 +2876,145 @@ func TestRBAC_Restore(t *testing.T) {
|
|||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, grants, 1)
|
||||
assert.Equal(t, grants[0].Grantor.Privilege.Name, "Load")
|
||||
// check privilege group
|
||||
privGroups, err = c.ListPrivilegeGroups(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, privGroups, 1)
|
||||
assert.Equal(t, "custom_group", privGroups[0].GroupName)
|
||||
assert.Equal(t, "CreateCollection", privGroups[0].Privileges[0].Name)
|
||||
}
|
||||
|
||||
func TestRBAC_PrivilegeGroup(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
group1 := "group1"
|
||||
group2 := "group2"
|
||||
key1 := BuildPrivilegeGroupkey(group1)
|
||||
key2 := BuildPrivilegeGroupkey(group2)
|
||||
privGroupInfo1 := &milvuspb.PrivilegeGroupInfo{GroupName: group1, Privileges: []*milvuspb.PrivilegeEntity{{Name: "priv10"}, {Name: "priv11"}}}
|
||||
privGroupInfo2 := &milvuspb.PrivilegeGroupInfo{GroupName: group2, Privileges: []*milvuspb.PrivilegeEntity{{Name: "priv20"}, {Name: "priv21"}}}
|
||||
v1, _ := proto.Marshal(privGroupInfo1)
|
||||
v2, _ := proto.Marshal(privGroupInfo2)
|
||||
|
||||
t.Run("test GetPrivilegeGroup", func(t *testing.T) {
|
||||
var (
|
||||
kvmock = mocks.NewTxnKV(t)
|
||||
c = &Catalog{Txn: kvmock}
|
||||
)
|
||||
kvmock.EXPECT().Load(key1).Return(string(v1), nil)
|
||||
kvmock.EXPECT().Load(key2).Return("", merr.ErrIoKeyNotFound)
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
expectedErr error
|
||||
groupName string
|
||||
expectedPrivileges []string
|
||||
}{
|
||||
{"group not found", fmt.Errorf("privilege group [%s] does not exist", group2), group2, nil},
|
||||
{"valid group", nil, group1, []string{"priv10", "priv11"}},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
group, err := c.GetPrivilegeGroup(ctx, test.groupName)
|
||||
if test.expectedErr != nil {
|
||||
assert.Error(t, err, test.expectedErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, getPrivilegeNames(group.Privileges), test.expectedPrivileges)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("test DropPrivilegeGroup", func(t *testing.T) {
|
||||
var (
|
||||
kvmock = mocks.NewTxnKV(t)
|
||||
c = &Catalog{Txn: kvmock}
|
||||
)
|
||||
|
||||
kvmock.EXPECT().Remove(key1).Return(nil)
|
||||
kvmock.EXPECT().Remove(key2).Return(errors.New("Mock remove failure"))
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
isValid bool
|
||||
groupName string
|
||||
}{
|
||||
{"valid group", true, group1},
|
||||
{"remove failure", false, group2},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
err := c.DropPrivilegeGroup(ctx, test.groupName)
|
||||
if test.isValid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("test SavePrivilegeGroup", func(t *testing.T) {
|
||||
var (
|
||||
kvmock = mocks.NewTxnKV(t)
|
||||
c = &Catalog{Txn: kvmock}
|
||||
)
|
||||
|
||||
kvmock.EXPECT().Save(key1, mock.Anything).Return(nil)
|
||||
kvmock.EXPECT().Save(key2, mock.Anything).Return(nil)
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
isValid bool
|
||||
group *milvuspb.PrivilegeGroupInfo
|
||||
}{
|
||||
{"valid group with existing key", true, &milvuspb.PrivilegeGroupInfo{GroupName: group1, Privileges: []*milvuspb.PrivilegeEntity{{Name: "priv10"}, {Name: "priv11"}}}},
|
||||
{"valid group without existing key", true, &milvuspb.PrivilegeGroupInfo{GroupName: group2, Privileges: []*milvuspb.PrivilegeEntity{{Name: "priv10"}, {Name: "priv11"}}}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
err := c.SavePrivilegeGroup(ctx, test.group)
|
||||
if test.isValid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("test ListPrivilegeGroups", func(t *testing.T) {
|
||||
var (
|
||||
kvmock = mocks.NewTxnKV(t)
|
||||
c = &Catalog{Txn: kvmock}
|
||||
)
|
||||
|
||||
kvmock.EXPECT().LoadWithPrefix(PrivilegeGroupPrefix).Return(
|
||||
[]string{key1, key2},
|
||||
[]string{string(v1), string(v2)},
|
||||
nil,
|
||||
)
|
||||
groups, err := c.ListPrivilegeGroups(ctx)
|
||||
assert.NoError(t, err)
|
||||
groupNames := lo.Map(groups, func(g *milvuspb.PrivilegeGroupInfo, _ int) string {
|
||||
return g.GroupName
|
||||
})
|
||||
assert.ElementsMatch(t, groupNames, []string{group1, group2})
|
||||
assert.ElementsMatch(t, getPrivilegeNames(groups[0].Privileges), []string{"priv10", "priv11"})
|
||||
assert.ElementsMatch(t, getPrivilegeNames(groups[1].Privileges), []string{"priv20", "priv21"})
|
||||
})
|
||||
}
|
||||
|
||||
func getPrivilegeNames(privileges []*milvuspb.PrivilegeEntity) []string {
|
||||
if len(privileges) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
return lo.Map(privileges, func(p *milvuspb.PrivilegeEntity, _ int) string {
|
||||
return p.Name
|
||||
})
|
||||
}
|
||||
|
||||
func TestCatalog_AlterDatabase(t *testing.T) {
|
||||
|
|
|
@ -50,6 +50,9 @@ const (
|
|||
|
||||
// GranteeIDPrefix prefix for mapping among privilege and grantor
|
||||
GranteeIDPrefix = ComponentPrefix + CommonCredentialPrefix + "/grantee-id"
|
||||
|
||||
// PrivilegeGroupPrefix prefix for privilege group
|
||||
PrivilegeGroupPrefix = ComponentPrefix + "/privilege-group"
|
||||
)
|
||||
|
||||
func BuildDatabasePrefixWithDBID(dbID int64) string {
|
||||
|
@ -70,3 +73,7 @@ func getDatabasePrefix(dbID int64) string {
|
|||
}
|
||||
return CollectionMetaPrefix
|
||||
}
|
||||
|
||||
func BuildPrivilegeGroupkey(groupName string) string {
|
||||
return fmt.Sprintf("%s/%s", PrivilegeGroupPrefix, groupName)
|
||||
}
|
||||
|
|
|
@ -1828,3 +1828,198 @@ func NewRootCoordCatalog(t interface {
|
|||
|
||||
return mock
|
||||
}
|
||||
|
||||
// GetPrivilegeGroup provides a mock function with given fields: ctx, groupName
|
||||
func (_m *RootCoordCatalog) GetPrivilegeGroup(ctx context.Context, groupName string) (*milvuspb.PrivilegeGroupInfo, error) {
|
||||
ret := _m.Called(ctx, groupName)
|
||||
|
||||
var r0 *milvuspb.PrivilegeGroupInfo
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*milvuspb.PrivilegeGroupInfo, error)); ok {
|
||||
return rf(ctx, groupName)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *milvuspb.PrivilegeGroupInfo); ok {
|
||||
r0 = rf(ctx, groupName)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*milvuspb.PrivilegeGroupInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, groupName)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoordCatalog_GetPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPrivilegeGroup'
|
||||
type RootCoordCatalog_GetPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetPrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - groupName string
|
||||
func (_e *RootCoordCatalog_Expecter) GetPrivilegeGroup(ctx interface{}, groupName interface{}) *RootCoordCatalog_GetPrivilegeGroup_Call {
|
||||
return &RootCoordCatalog_GetPrivilegeGroup_Call{Call: _e.mock.On("GetPrivilegeGroup", ctx, groupName)}
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_GetPrivilegeGroup_Call) Run(run func(ctx context.Context, groupName string)) *RootCoordCatalog_GetPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_GetPrivilegeGroup_Call) Return(_a0 *milvuspb.PrivilegeGroupInfo, _a1 error) *RootCoordCatalog_GetPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_GetPrivilegeGroup_Call) RunAndReturn(run func(context.Context, string) (*milvuspb.PrivilegeGroupInfo,error)) *RootCoordCatalog_GetPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup provides a mock function with given fields: ctx, groupName, privileges
|
||||
func (_m *RootCoordCatalog) DropPrivilegeGroup(ctx context.Context, groupName string) error {
|
||||
ret := _m.Called(ctx, groupName)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, groupName)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RootCoordCatalog_DropPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropPrivilegeGroup'
|
||||
type RootCoordCatalog_DropPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - groupName string
|
||||
func (_e *RootCoordCatalog_Expecter) DropPrivilegeGroup(ctx interface{}, groupName interface{}) *RootCoordCatalog_DropPrivilegeGroup_Call {
|
||||
return &RootCoordCatalog_DropPrivilegeGroup_Call{Call: _e.mock.On("DropPrivilegeGroup", ctx, groupName)}
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_DropPrivilegeGroup_Call) Run(run func(ctx context.Context, groupName string)) *RootCoordCatalog_DropPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_DropPrivilegeGroup_Call) Return(_a0 error) *RootCoordCatalog_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_DropPrivilegeGroup_Call) RunAndReturn(run func(context.Context, string) error) *RootCoordCatalog_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SavePrivilegeGroup provides a mock function with given fields: ctx, groupName, privileges
|
||||
func (_m *RootCoordCatalog) SavePrivilegeGroup(ctx context.Context, data *milvuspb.PrivilegeGroupInfo) error {
|
||||
ret := _m.Called(ctx, data)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.PrivilegeGroupInfo) error); ok {
|
||||
r0 = rf(ctx, data)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RootCoordCatalog_SavePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SavePrivilegeGroup'
|
||||
type RootCoordCatalog_SavePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// SavePrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - groupName string
|
||||
func (_e *RootCoordCatalog_Expecter) SavePrivilegeGroup(ctx interface{}, data interface{}) *RootCoordCatalog_SavePrivilegeGroup_Call {
|
||||
return &RootCoordCatalog_SavePrivilegeGroup_Call{Call: _e.mock.On("SavePrivilegeGroup", ctx, data)}
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_SavePrivilegeGroup_Call) Run(run func(ctx context.Context, data *milvuspb.PrivilegeGroupInfo)) *RootCoordCatalog_SavePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.PrivilegeGroupInfo))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_SavePrivilegeGroup_Call) Return(_a0 error) *RootCoordCatalog_SavePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_SavePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.PrivilegeGroupInfo) error) *RootCoordCatalog_SavePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups provides a mock function with given fields: ctx
|
||||
func (_m *RootCoordCatalog) ListPrivilegeGroups(ctx context.Context) ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 []*milvuspb.PrivilegeGroupInfo
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) ([]*milvuspb.PrivilegeGroupInfo, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) []*milvuspb.PrivilegeGroupInfo); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*milvuspb.PrivilegeGroupInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoordCatalog_ListPrivilegeGroups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListPrivilegeGroups'
|
||||
type RootCoordCatalog_ListPrivilegeGroups_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *RootCoordCatalog_Expecter) ListPrivilegeGroups(ctx interface{}) *RootCoordCatalog_ListPrivilegeGroups_Call {
|
||||
return &RootCoordCatalog_ListPrivilegeGroups_Call{Call: _e.mock.On("ListPrivilegeGroups", ctx)}
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_ListPrivilegeGroups_Call) Run(run func(ctx context.Context)) *RootCoordCatalog_ListPrivilegeGroups_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_ListPrivilegeGroups_Call) Return(_a0 []*milvuspb.PrivilegeGroupInfo, _a1 error) *RootCoordCatalog_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoordCatalog_ListPrivilegeGroups_Call) RunAndReturn(run func(context.Context) ([]*milvuspb.PrivilegeGroupInfo, error)) *RootCoordCatalog_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
|
|
@ -211,6 +211,65 @@ func (_c *MockProxy_AlterCollection_Call) RunAndReturn(run func(context.Context,
|
|||
return _c
|
||||
}
|
||||
|
||||
// AlterCollectionField provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) AlterCollectionField(_a0 context.Context, _a1 *milvuspb.AlterCollectionFieldRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AlterCollectionField")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.AlterCollectionFieldRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.AlterCollectionFieldRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.AlterCollectionFieldRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_AlterCollectionField_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AlterCollectionField'
|
||||
type MockProxy_AlterCollectionField_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AlterCollectionField is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.AlterCollectionFieldRequest
|
||||
func (_e *MockProxy_Expecter) AlterCollectionField(_a0 interface{}, _a1 interface{}) *MockProxy_AlterCollectionField_Call {
|
||||
return &MockProxy_AlterCollectionField_Call{Call: _e.mock.On("AlterCollectionField", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_AlterCollectionField_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.AlterCollectionFieldRequest)) *MockProxy_AlterCollectionField_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.AlterCollectionFieldRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_AlterCollectionField_Call) Return(_a0 *commonpb.Status, _a1 error) *MockProxy_AlterCollectionField_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_AlterCollectionField_Call) RunAndReturn(run func(context.Context, *milvuspb.AlterCollectionFieldRequest) (*commonpb.Status, error)) *MockProxy_AlterCollectionField_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// AlterDatabase provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) AlterDatabase(_a0 context.Context, _a1 *milvuspb.AlterDatabaseRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -919,6 +978,65 @@ func (_c *MockProxy_CreatePartition_Call) RunAndReturn(run func(context.Context,
|
|||
return _c
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) CreatePrivilegeGroup(_a0 context.Context, _a1 *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_CreatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePrivilegeGroup'
|
||||
type MockProxy_CreatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.CreatePrivilegeGroupRequest
|
||||
func (_e *MockProxy_Expecter) CreatePrivilegeGroup(_a0 interface{}, _a1 interface{}) *MockProxy_CreatePrivilegeGroup_Call {
|
||||
return &MockProxy_CreatePrivilegeGroup_Call{Call: _e.mock.On("CreatePrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_CreatePrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.CreatePrivilegeGroupRequest)) *MockProxy_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.CreatePrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_CreatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockProxy_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_CreatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error)) *MockProxy_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateResourceGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) CreateResourceGroup(_a0 context.Context, _a1 *milvuspb.CreateResourceGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -1804,6 +1922,65 @@ func (_c *MockProxy_DropPartition_Call) RunAndReturn(run func(context.Context, *
|
|||
return _c
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) DropPrivilegeGroup(_a0 context.Context, _a1 *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DropPrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_DropPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropPrivilegeGroup'
|
||||
type MockProxy_DropPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.DropPrivilegeGroupRequest
|
||||
func (_e *MockProxy_Expecter) DropPrivilegeGroup(_a0 interface{}, _a1 interface{}) *MockProxy_DropPrivilegeGroup_Call {
|
||||
return &MockProxy_DropPrivilegeGroup_Call{Call: _e.mock.On("DropPrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_DropPrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.DropPrivilegeGroupRequest)) *MockProxy_DropPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.DropPrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_DropPrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockProxy_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_DropPrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error)) *MockProxy_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DropResourceGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) DropResourceGroup(_a0 context.Context, _a1 *milvuspb.DropResourceGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -4488,6 +4665,65 @@ func (_c *MockProxy_ListIndexedSegment_Call) RunAndReturn(run func(context.Conte
|
|||
return _c
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) ListPrivilegeGroups(_a0 context.Context, _a1 *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListPrivilegeGroups")
|
||||
}
|
||||
|
||||
var r0 *milvuspb.ListPrivilegeGroupsResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) *milvuspb.ListPrivilegeGroupsResponse); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*milvuspb.ListPrivilegeGroupsResponse)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_ListPrivilegeGroups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListPrivilegeGroups'
|
||||
type MockProxy_ListPrivilegeGroups_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.ListPrivilegeGroupsRequest
|
||||
func (_e *MockProxy_Expecter) ListPrivilegeGroups(_a0 interface{}, _a1 interface{}) *MockProxy_ListPrivilegeGroups_Call {
|
||||
return &MockProxy_ListPrivilegeGroups_Call{Call: _e.mock.On("ListPrivilegeGroups", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_ListPrivilegeGroups_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.ListPrivilegeGroupsRequest)) *MockProxy_ListPrivilegeGroups_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.ListPrivilegeGroupsRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_ListPrivilegeGroups_Call) Return(_a0 *milvuspb.ListPrivilegeGroupsResponse, _a1 error) *MockProxy_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_ListPrivilegeGroups_Call) RunAndReturn(run func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error)) *MockProxy_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListResourceGroups provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) ListResourceGroups(_a0 context.Context, _a1 *milvuspb.ListResourceGroupsRequest) (*milvuspb.ListResourceGroupsResponse, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -4842,6 +5078,65 @@ func (_c *MockProxy_OperatePrivilege_Call) RunAndReturn(run func(context.Context
|
|||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) OperatePrivilegeGroup(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OperatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_OperatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OperatePrivilegeGroup'
|
||||
type MockProxy_OperatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.OperatePrivilegeGroupRequest
|
||||
func (_e *MockProxy_Expecter) OperatePrivilegeGroup(_a0 interface{}, _a1 interface{}) *MockProxy_OperatePrivilegeGroup_Call {
|
||||
return &MockProxy_OperatePrivilegeGroup_Call{Call: _e.mock.On("OperatePrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_OperatePrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeGroupRequest)) *MockProxy_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.OperatePrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_OperatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockProxy_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_OperatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error)) *MockProxy_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperateUserRole provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) OperateUserRole(_a0 context.Context, _a1 *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
|
|
@ -744,6 +744,65 @@ func (_c *RootCoord_CreatePartition_Call) RunAndReturn(run func(context.Context,
|
|||
return _c
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) CreatePrivilegeGroup(_a0 context.Context, _a1 *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoord_CreatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePrivilegeGroup'
|
||||
type RootCoord_CreatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.CreatePrivilegeGroupRequest
|
||||
func (_e *RootCoord_Expecter) CreatePrivilegeGroup(_a0 interface{}, _a1 interface{}) *RootCoord_CreatePrivilegeGroup_Call {
|
||||
return &RootCoord_CreatePrivilegeGroup_Call{Call: _e.mock.On("CreatePrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *RootCoord_CreatePrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.CreatePrivilegeGroupRequest)) *RootCoord_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.CreatePrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_CreatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *RootCoord_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_CreatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error)) *RootCoord_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateRole provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) CreateRole(_a0 context.Context, _a1 *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -1334,6 +1393,65 @@ func (_c *RootCoord_DropPartition_Call) RunAndReturn(run func(context.Context, *
|
|||
return _c
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) DropPrivilegeGroup(_a0 context.Context, _a1 *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DropPrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoord_DropPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropPrivilegeGroup'
|
||||
type RootCoord_DropPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.DropPrivilegeGroupRequest
|
||||
func (_e *RootCoord_Expecter) DropPrivilegeGroup(_a0 interface{}, _a1 interface{}) *RootCoord_DropPrivilegeGroup_Call {
|
||||
return &RootCoord_DropPrivilegeGroup_Call{Call: _e.mock.On("DropPrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *RootCoord_DropPrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.DropPrivilegeGroupRequest)) *RootCoord_DropPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.DropPrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_DropPrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *RootCoord_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_DropPrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error)) *RootCoord_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DropRole provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) DropRole(_a0 context.Context, _a1 *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -2205,6 +2323,65 @@ func (_c *RootCoord_ListPolicy_Call) RunAndReturn(run func(context.Context, *int
|
|||
return _c
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) ListPrivilegeGroups(_a0 context.Context, _a1 *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListPrivilegeGroups")
|
||||
}
|
||||
|
||||
var r0 *milvuspb.ListPrivilegeGroupsResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) *milvuspb.ListPrivilegeGroupsResponse); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*milvuspb.ListPrivilegeGroupsResponse)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoord_ListPrivilegeGroups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListPrivilegeGroups'
|
||||
type RootCoord_ListPrivilegeGroups_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.ListPrivilegeGroupsRequest
|
||||
func (_e *RootCoord_Expecter) ListPrivilegeGroups(_a0 interface{}, _a1 interface{}) *RootCoord_ListPrivilegeGroups_Call {
|
||||
return &RootCoord_ListPrivilegeGroups_Call{Call: _e.mock.On("ListPrivilegeGroups", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *RootCoord_ListPrivilegeGroups_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.ListPrivilegeGroupsRequest)) *RootCoord_ListPrivilegeGroups_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.ListPrivilegeGroupsRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_ListPrivilegeGroups_Call) Return(_a0 *milvuspb.ListPrivilegeGroupsResponse, _a1 error) *RootCoord_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_ListPrivilegeGroups_Call) RunAndReturn(run func(context.Context, *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error)) *RootCoord_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilege provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) OperatePrivilege(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
@ -2264,6 +2441,65 @@ func (_c *RootCoord_OperatePrivilege_Call) RunAndReturn(run func(context.Context
|
|||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) OperatePrivilegeGroup(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OperatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCoord_OperatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OperatePrivilegeGroup'
|
||||
type RootCoord_OperatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.OperatePrivilegeGroupRequest
|
||||
func (_e *RootCoord_Expecter) OperatePrivilegeGroup(_a0 interface{}, _a1 interface{}) *RootCoord_OperatePrivilegeGroup_Call {
|
||||
return &RootCoord_OperatePrivilegeGroup_Call{Call: _e.mock.On("OperatePrivilegeGroup", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *RootCoord_OperatePrivilegeGroup_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeGroupRequest)) *RootCoord_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.OperatePrivilegeGroupRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_OperatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *RootCoord_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RootCoord_OperatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error)) *RootCoord_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperateUserRole provides a mock function with given fields: _a0, _a1
|
||||
func (_m *RootCoord) OperateUserRole(_a0 context.Context, _a1 *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
|
|
@ -966,6 +966,80 @@ func (_c *MockRootCoordClient_CreatePartition_Call) RunAndReturn(run func(contex
|
|||
return _c
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) CreatePrivilegeGroup(ctx context.Context, in *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)); ok {
|
||||
return rf(ctx, in, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest, ...grpc.CallOption) *commonpb.Status); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.CreatePrivilegeGroupRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRootCoordClient_CreatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePrivilegeGroup'
|
||||
type MockRootCoordClient_CreatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *milvuspb.CreatePrivilegeGroupRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *MockRootCoordClient_Expecter) CreatePrivilegeGroup(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_CreatePrivilegeGroup_Call {
|
||||
return &MockRootCoordClient_CreatePrivilegeGroup_Call{Call: _e.mock.On("CreatePrivilegeGroup",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_CreatePrivilegeGroup_Call) Run(run func(ctx context.Context, in *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption)) *MockRootCoordClient_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.CreatePrivilegeGroupRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_CreatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockRootCoordClient_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_CreatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.CreatePrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)) *MockRootCoordClient_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateRole provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) CreateRole(ctx context.Context, in *milvuspb.CreateRoleRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
|
@ -1706,6 +1780,80 @@ func (_c *MockRootCoordClient_DropPartition_Call) RunAndReturn(run func(context.
|
|||
return _c
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) DropPrivilegeGroup(ctx context.Context, in *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DropPrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)); ok {
|
||||
return rf(ctx, in, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest, ...grpc.CallOption) *commonpb.Status); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.DropPrivilegeGroupRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRootCoordClient_DropPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropPrivilegeGroup'
|
||||
type MockRootCoordClient_DropPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *milvuspb.DropPrivilegeGroupRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *MockRootCoordClient_Expecter) DropPrivilegeGroup(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_DropPrivilegeGroup_Call {
|
||||
return &MockRootCoordClient_DropPrivilegeGroup_Call{Call: _e.mock.On("DropPrivilegeGroup",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_DropPrivilegeGroup_Call) Run(run func(ctx context.Context, in *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption)) *MockRootCoordClient_DropPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.DropPrivilegeGroupRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_DropPrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockRootCoordClient_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_DropPrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.DropPrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)) *MockRootCoordClient_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DropRole provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) DropRole(ctx context.Context, in *milvuspb.DropRoleRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
|
@ -2742,6 +2890,80 @@ func (_c *MockRootCoordClient_ListPolicy_Call) RunAndReturn(run func(context.Con
|
|||
return _c
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) ListPrivilegeGroups(ctx context.Context, in *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListPrivilegeGroups")
|
||||
}
|
||||
|
||||
var r0 *milvuspb.ListPrivilegeGroupsResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest, ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error)); ok {
|
||||
return rf(ctx, in, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest, ...grpc.CallOption) *milvuspb.ListPrivilegeGroupsResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*milvuspb.ListPrivilegeGroupsResponse)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.ListPrivilegeGroupsRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRootCoordClient_ListPrivilegeGroups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListPrivilegeGroups'
|
||||
type MockRootCoordClient_ListPrivilegeGroups_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *milvuspb.ListPrivilegeGroupsRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *MockRootCoordClient_Expecter) ListPrivilegeGroups(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_ListPrivilegeGroups_Call {
|
||||
return &MockRootCoordClient_ListPrivilegeGroups_Call{Call: _e.mock.On("ListPrivilegeGroups",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_ListPrivilegeGroups_Call) Run(run func(ctx context.Context, in *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption)) *MockRootCoordClient_ListPrivilegeGroups_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.ListPrivilegeGroupsRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_ListPrivilegeGroups_Call) Return(_a0 *milvuspb.ListPrivilegeGroupsResponse, _a1 error) *MockRootCoordClient_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_ListPrivilegeGroups_Call) RunAndReturn(run func(context.Context, *milvuspb.ListPrivilegeGroupsRequest, ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error)) *MockRootCoordClient_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilege provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
|
@ -2816,6 +3038,80 @@ func (_c *MockRootCoordClient_OperatePrivilege_Call) RunAndReturn(run func(conte
|
|||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OperatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)); ok {
|
||||
return rf(ctx, in, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest, ...grpc.CallOption) *commonpb.Status); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.OperatePrivilegeGroupRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRootCoordClient_OperatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OperatePrivilegeGroup'
|
||||
type MockRootCoordClient_OperatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *milvuspb.OperatePrivilegeGroupRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *MockRootCoordClient_Expecter) OperatePrivilegeGroup(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_OperatePrivilegeGroup_Call {
|
||||
return &MockRootCoordClient_OperatePrivilegeGroup_Call{Call: _e.mock.On("OperatePrivilegeGroup",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_OperatePrivilegeGroup_Call) Run(run func(ctx context.Context, in *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption)) *MockRootCoordClient_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.OperatePrivilegeGroupRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_OperatePrivilegeGroup_Call) Return(_a0 *commonpb.Status, _a1 error) *MockRootCoordClient_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRootCoordClient_OperatePrivilegeGroup_Call) RunAndReturn(run func(context.Context, *milvuspb.OperatePrivilegeGroupRequest, ...grpc.CallOption) (*commonpb.Status, error)) *MockRootCoordClient_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperateUserRole provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockRootCoordClient) OperateUserRole(ctx context.Context, in *milvuspb.OperateUserRoleRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
|
|
|
@ -4,6 +4,7 @@ option go_package = "github.com/milvus-io/milvus/internal/proto/internalpb";
|
|||
|
||||
import "common.proto";
|
||||
import "schema.proto";
|
||||
import "milvus.proto";
|
||||
|
||||
message GetTimeTickChannelRequest {
|
||||
}
|
||||
|
@ -263,6 +264,7 @@ message ListPolicyResponse {
|
|||
common.Status status = 1;
|
||||
repeated string policy_infos = 2;
|
||||
repeated string user_roles = 3;
|
||||
repeated milvus.PrivilegeGroupInfo privilege_groups = 4;
|
||||
}
|
||||
|
||||
message ShowConfigurationsRequest {
|
||||
|
|
|
@ -126,6 +126,10 @@ service RootCoord {
|
|||
rpc ListPolicy(internal.ListPolicyRequest) returns (internal.ListPolicyResponse) {}
|
||||
rpc BackupRBAC(milvus.BackupRBACMetaRequest) returns (milvus.BackupRBACMetaResponse){}
|
||||
rpc RestoreRBAC(milvus.RestoreRBACMetaRequest) returns (common.Status){}
|
||||
rpc CreatePrivilegeGroup(milvus.CreatePrivilegeGroupRequest) returns (common.Status) {}
|
||||
rpc DropPrivilegeGroup(milvus.DropPrivilegeGroupRequest) returns (common.Status) {}
|
||||
rpc ListPrivilegeGroups(milvus.ListPrivilegeGroupsRequest) returns (milvus.ListPrivilegeGroupsResponse) {}
|
||||
rpc OperatePrivilegeGroup(milvus.OperatePrivilegeGroupRequest) returns (common.Status) {}
|
||||
|
||||
rpc CheckHealth(milvus.CheckHealthRequest) returns (milvus.CheckHealthResponse) {}
|
||||
|
||||
|
|
|
@ -6506,3 +6506,124 @@ func (node *Proxy) RegisterRestRouter(router gin.IRouter) {
|
|||
router.GET(http.DNSegmentsPath, getDataComponentMetrics(node, metricsinfo.DataSegments))
|
||||
router.GET(http.DNChannelsPath, getDataComponentMetrics(node, metricsinfo.DataChannels))
|
||||
}
|
||||
|
||||
func (node *Proxy) CreatePrivilegeGroup(ctx context.Context, req *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-CreatePrivilegeGroup")
|
||||
defer sp.End()
|
||||
|
||||
log := log.Ctx(ctx)
|
||||
|
||||
log.Info("CreatePrivilegeGroup", zap.Any("req", req))
|
||||
if err := merr.CheckHealthy(node.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if req.GroupName == "" {
|
||||
return merr.Status(fmt.Errorf("the group name in the drop privilege group request is nil")), nil
|
||||
}
|
||||
if req.Base == nil {
|
||||
req.Base = &commonpb.MsgBase{}
|
||||
}
|
||||
req.Base.MsgType = commonpb.MsgType_CreatePrivilegeGroup
|
||||
|
||||
result, err := node.rootCoord.CreatePrivilegeGroup(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("fail to create privilege group", zap.Error(err))
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if merr.Ok(result) {
|
||||
SendReplicateMessagePack(ctx, node.replicateMsgStream, req)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (node *Proxy) DropPrivilegeGroup(ctx context.Context, req *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-DropPrivilegeGroup")
|
||||
defer sp.End()
|
||||
|
||||
log := log.Ctx(ctx)
|
||||
|
||||
log.Info("DropPrivilegeGroup", zap.Any("req", req))
|
||||
if err := merr.CheckHealthy(node.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if req.GroupName == "" {
|
||||
return merr.Status(fmt.Errorf("the group name in the drop privilege group request is nil")), nil
|
||||
}
|
||||
if req.Base == nil {
|
||||
req.Base = &commonpb.MsgBase{}
|
||||
}
|
||||
req.Base.MsgType = commonpb.MsgType_DropPrivilegeGroup
|
||||
|
||||
result, err := node.rootCoord.DropPrivilegeGroup(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("fail to drop privilege group", zap.Error(err))
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if merr.Ok(result) {
|
||||
SendReplicateMessagePack(ctx, node.replicateMsgStream, req)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (node *Proxy) ListPrivilegeGroups(ctx context.Context, req *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-ListPrivilegeGroups")
|
||||
defer sp.End()
|
||||
|
||||
log := log.Ctx(ctx).With(
|
||||
zap.String("role", typeutil.ProxyRole))
|
||||
|
||||
log.Debug("ListPrivilegeGroups")
|
||||
if err := merr.CheckHealthy(node.GetStateCode()); err != nil {
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{Status: merr.Status(err)}, nil
|
||||
}
|
||||
if req.Base == nil {
|
||||
req.Base = &commonpb.MsgBase{}
|
||||
}
|
||||
req.Base.MsgType = commonpb.MsgType_ListPrivilegeGroups
|
||||
rootCoordReq := &milvuspb.ListPrivilegeGroupsRequest{
|
||||
Base: commonpbutil.NewMsgBase(
|
||||
commonpbutil.WithMsgType(commonpb.MsgType_ListPrivilegeGroups),
|
||||
),
|
||||
}
|
||||
resp, err := node.rootCoord.ListPrivilegeGroups(ctx, rootCoordReq)
|
||||
if err != nil {
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{
|
||||
Status: merr.Status(err),
|
||||
}, nil
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (node *Proxy) OperatePrivilegeGroup(ctx context.Context, req *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-OperatePrivilegeGroup")
|
||||
defer sp.End()
|
||||
|
||||
log := log.Ctx(ctx)
|
||||
|
||||
log.Info("OperatePrivilegeGroup", zap.Any("req", req))
|
||||
if err := merr.CheckHealthy(node.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if req.GroupName == "" {
|
||||
return merr.Status(fmt.Errorf("the group name in the drop privilege group request is nil")), nil
|
||||
}
|
||||
for _, priv := range req.GetPrivileges() {
|
||||
if err := ValidatePrivilege(priv.Name); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
}
|
||||
if req.Base == nil {
|
||||
req.Base = &commonpb.MsgBase{}
|
||||
}
|
||||
req.Base.MsgType = commonpb.MsgType_OperatePrivilegeGroup
|
||||
|
||||
result, err := node.rootCoord.OperatePrivilegeGroup(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("fail to operate privilege group", zap.Error(err))
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
if merr.Ok(result) {
|
||||
SendReplicateMessagePack(ctx, node.replicateMsgStream, req)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
|
|
@ -1123,9 +1123,15 @@ func (m *MetaCache) RefreshPolicyInfo(op typeutil.CacheOp) (err error) {
|
|||
|
||||
switch op.OpType {
|
||||
case typeutil.CacheGrantPrivilege:
|
||||
m.privilegeInfos[op.OpKey] = struct{}{}
|
||||
keys := funcutil.PrivilegesForPolicy(op.OpKey)
|
||||
for _, key := range keys {
|
||||
m.privilegeInfos[key] = struct{}{}
|
||||
}
|
||||
case typeutil.CacheRevokePrivilege:
|
||||
delete(m.privilegeInfos, op.OpKey)
|
||||
keys := funcutil.PrivilegesForPolicy(op.OpKey)
|
||||
for _, key := range keys {
|
||||
delete(m.privilegeInfos, key)
|
||||
}
|
||||
case typeutil.CacheAddUserToRole:
|
||||
user, role, err := funcutil.DecodeUserRoleCache(op.OpKey)
|
||||
if err != nil {
|
||||
|
|
|
@ -1134,6 +1134,22 @@ func (coord *RootCoordMock) RestoreRBAC(ctx context.Context, in *milvuspb.Restor
|
|||
return &commonpb.Status{}, nil
|
||||
}
|
||||
|
||||
func (coord *RootCoordMock) CreatePrivilegeGroup(ctx context.Context, req *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, nil
|
||||
}
|
||||
|
||||
func (coord *RootCoordMock) DropPrivilegeGroup(ctx context.Context, req *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, nil
|
||||
}
|
||||
|
||||
func (coord *RootCoordMock) ListPrivilegeGroups(ctx context.Context, req *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{}, nil
|
||||
}
|
||||
|
||||
func (coord *RootCoordMock) OperatePrivilegeGroup(ctx context.Context, req *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, nil
|
||||
}
|
||||
|
||||
type DescribeCollectionFunc func(ctx context.Context, request *milvuspb.DescribeCollectionRequest, opts ...grpc.CallOption) (*milvuspb.DescribeCollectionResponse, error)
|
||||
|
||||
type ShowPartitionsFunc func(ctx context.Context, request *milvuspb.ShowPartitionsRequest, opts ...grpc.CallOption) (*milvuspb.ShowPartitionsResponse, error)
|
||||
|
|
|
@ -1071,14 +1071,6 @@ func ValidateObjectType(entity string) error {
|
|||
return validateName(entity, "ObjectType")
|
||||
}
|
||||
|
||||
func ValidatePrincipalName(entity string) error {
|
||||
return validateName(entity, "PrincipalName")
|
||||
}
|
||||
|
||||
func ValidatePrincipalType(entity string) error {
|
||||
return validateName(entity, "PrincipalType")
|
||||
}
|
||||
|
||||
func ValidatePrivilege(entity string) error {
|
||||
if util.IsAnyWord(entity) {
|
||||
return nil
|
||||
|
|
|
@ -804,8 +804,6 @@ func TestValidateName(t *testing.T) {
|
|||
assert.Nil(t, ValidateRoleName(name))
|
||||
assert.Nil(t, ValidateObjectName(name))
|
||||
assert.Nil(t, ValidateObjectType(name))
|
||||
assert.Nil(t, ValidatePrincipalName(name))
|
||||
assert.Nil(t, ValidatePrincipalType(name))
|
||||
assert.Nil(t, ValidatePrivilege(name))
|
||||
}
|
||||
|
||||
|
@ -828,8 +826,6 @@ func TestValidateName(t *testing.T) {
|
|||
assert.NotNil(t, validateName(name, nameType))
|
||||
assert.NotNil(t, ValidateRoleName(name))
|
||||
assert.NotNil(t, ValidateObjectType(name))
|
||||
assert.NotNil(t, ValidatePrincipalName(name))
|
||||
assert.NotNil(t, ValidatePrincipalType(name))
|
||||
assert.NotNil(t, ValidatePrivilege(name))
|
||||
}
|
||||
assert.NotNil(t, ValidateObjectName(" "))
|
||||
|
|
|
@ -365,6 +365,10 @@ func (_c *MockScheduler_GetSegmentTaskNum_Call) RunAndReturn(run func() int) *Mo
|
|||
func (_m *MockScheduler) GetTasksJSON() string {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetTasksJSON")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
|
|
|
@ -99,6 +99,12 @@ type IMetaTable interface {
|
|||
ListUserRole(tenant string) ([]string, error)
|
||||
BackupRBAC(ctx context.Context, tenant string) (*milvuspb.RBACMeta, error)
|
||||
RestoreRBAC(ctx context.Context, tenant string, meta *milvuspb.RBACMeta) error
|
||||
IsCustomPrivilegeGroup(groupName string) (bool, error)
|
||||
CreatePrivilegeGroup(groupName string) error
|
||||
DropPrivilegeGroup(groupName string) error
|
||||
ListPrivilegeGroups() ([]*milvuspb.PrivilegeGroupInfo, error)
|
||||
OperatePrivilegeGroup(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error
|
||||
GetPrivilegeGroupRoles(groupName string) ([]*milvuspb.RoleEntity, error)
|
||||
}
|
||||
|
||||
// MetaTable is a persistent meta set of all databases, collections and partitions.
|
||||
|
@ -1456,3 +1462,187 @@ func (mt *MetaTable) RestoreRBAC(ctx context.Context, tenant string, meta *milvu
|
|||
|
||||
return mt.catalog.RestoreRBAC(mt.ctx, tenant, meta)
|
||||
}
|
||||
|
||||
// check if the privielge group name is defined by users
|
||||
func (mt *MetaTable) IsCustomPrivilegeGroup(groupName string) (bool, error) {
|
||||
privGroups, err := mt.catalog.ListPrivilegeGroups(mt.ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, group := range privGroups {
|
||||
if group.GroupName == groupName {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mt *MetaTable) CreatePrivilegeGroup(groupName string) error {
|
||||
if funcutil.IsEmptyString(groupName) {
|
||||
return fmt.Errorf("the privilege group name is empty")
|
||||
}
|
||||
mt.permissionLock.Lock()
|
||||
defer mt.permissionLock.Unlock()
|
||||
|
||||
definedByUsers, err := mt.IsCustomPrivilegeGroup(groupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if definedByUsers {
|
||||
return merr.WrapErrParameterInvalidMsg("privilege group name [%s] is defined by users", groupName)
|
||||
}
|
||||
if util.IsPrivilegeNameDefined(groupName) {
|
||||
return merr.WrapErrParameterInvalidMsg("privilege group name [%s] is defined by built in privileges or privilege groups in system", groupName)
|
||||
}
|
||||
data := &milvuspb.PrivilegeGroupInfo{
|
||||
GroupName: groupName,
|
||||
Privileges: make([]*milvuspb.PrivilegeEntity, 0),
|
||||
}
|
||||
return mt.catalog.SavePrivilegeGroup(mt.ctx, data)
|
||||
}
|
||||
|
||||
func (mt *MetaTable) DropPrivilegeGroup(groupName string) error {
|
||||
if funcutil.IsEmptyString(groupName) {
|
||||
return fmt.Errorf("the privilege group name is empty")
|
||||
}
|
||||
mt.permissionLock.Lock()
|
||||
defer mt.permissionLock.Unlock()
|
||||
|
||||
definedByUsers, err := mt.IsCustomPrivilegeGroup(groupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !definedByUsers {
|
||||
return nil
|
||||
}
|
||||
// check if the group is used by any role
|
||||
roles, err := mt.catalog.ListRole(mt.ctx, util.DefaultTenant, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roleEntity := lo.Map(roles, func(entity *milvuspb.RoleResult, _ int) *milvuspb.RoleEntity {
|
||||
return entity.GetRole()
|
||||
})
|
||||
for _, role := range roleEntity {
|
||||
grants, err := mt.catalog.ListGrant(mt.ctx, util.DefaultTenant, &milvuspb.GrantEntity{
|
||||
Role: role,
|
||||
DbName: util.AnyWord,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, grant := range grants {
|
||||
if grant.Grantor.Privilege.Name == groupName {
|
||||
return errors.Newf("privilege group [%s] is used by role [%s], Use REVOKE API to revoke it first", groupName, role.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
return mt.catalog.DropPrivilegeGroup(mt.ctx, groupName)
|
||||
}
|
||||
|
||||
func (mt *MetaTable) ListPrivilegeGroups() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
mt.permissionLock.Lock()
|
||||
defer mt.permissionLock.Unlock()
|
||||
|
||||
return mt.catalog.ListPrivilegeGroups(mt.ctx)
|
||||
}
|
||||
|
||||
func (mt *MetaTable) OperatePrivilegeGroup(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error {
|
||||
if funcutil.IsEmptyString(groupName) {
|
||||
return fmt.Errorf("the privilege group name is empty")
|
||||
}
|
||||
mt.permissionLock.Lock()
|
||||
defer mt.permissionLock.Unlock()
|
||||
|
||||
// validate input params
|
||||
definedByUsers, err := mt.IsCustomPrivilegeGroup(groupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !definedByUsers {
|
||||
return merr.WrapErrParameterInvalidMsg("there is no privilege group name [%s] to operate", groupName)
|
||||
}
|
||||
groups, err := mt.catalog.ListPrivilegeGroups(mt.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range privileges {
|
||||
if util.IsPrivilegeNameDefined(p.Name) {
|
||||
continue
|
||||
}
|
||||
for _, group := range groups {
|
||||
// add privileges for custom privilege group
|
||||
if group.GroupName == p.Name {
|
||||
privileges = append(privileges, group.Privileges...)
|
||||
} else {
|
||||
return merr.WrapErrParameterInvalidMsg("there is no privilege name or privielge group name [%s] defined in system to operate", p.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge with current privileges
|
||||
group, err := mt.catalog.GetPrivilegeGroup(mt.ctx, groupName)
|
||||
if err != nil {
|
||||
log.Warn("fail to get privilege group", zap.String("privilege_group", groupName), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
privSet := lo.SliceToMap(group.Privileges, func(p *milvuspb.PrivilegeEntity) (string, struct{}) {
|
||||
return p.Name, struct{}{}
|
||||
})
|
||||
switch operateType {
|
||||
case milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup:
|
||||
for _, p := range privileges {
|
||||
privSet[p.Name] = struct{}{}
|
||||
}
|
||||
case milvuspb.OperatePrivilegeGroupType_RemovePrivilegesFromGroup:
|
||||
for _, p := range privileges {
|
||||
delete(privSet, p.Name)
|
||||
}
|
||||
default:
|
||||
log.Warn("unsupported operate type", zap.Any("operate_type", operateType))
|
||||
return fmt.Errorf("unsupported operate type: %v", operateType)
|
||||
}
|
||||
|
||||
mergedPrivs := lo.Map(lo.Keys(privSet), func(priv string, _ int) *milvuspb.PrivilegeEntity {
|
||||
return &milvuspb.PrivilegeEntity{Name: priv}
|
||||
})
|
||||
data := &milvuspb.PrivilegeGroupInfo{
|
||||
GroupName: groupName,
|
||||
Privileges: mergedPrivs,
|
||||
}
|
||||
return mt.catalog.SavePrivilegeGroup(mt.ctx, data)
|
||||
}
|
||||
|
||||
func (mt *MetaTable) GetPrivilegeGroupRoles(groupName string) ([]*milvuspb.RoleEntity, error) {
|
||||
if funcutil.IsEmptyString(groupName) {
|
||||
return nil, fmt.Errorf("the privilege group name is empty")
|
||||
}
|
||||
mt.permissionLock.RLock()
|
||||
defer mt.permissionLock.RUnlock()
|
||||
|
||||
// get all roles
|
||||
roles, err := mt.catalog.ListRole(mt.ctx, util.DefaultTenant, nil, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roleEntity := lo.Map(roles, func(entity *milvuspb.RoleResult, _ int) *milvuspb.RoleEntity {
|
||||
return entity.GetRole()
|
||||
})
|
||||
|
||||
rolesMap := make(map[*milvuspb.RoleEntity]struct{})
|
||||
for _, role := range roleEntity {
|
||||
grants, err := mt.catalog.ListGrant(mt.ctx, util.DefaultTenant, &milvuspb.GrantEntity{
|
||||
Role: role,
|
||||
DbName: util.AnyWord,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, grant := range grants {
|
||||
if grant.Grantor.Privilege.Name == groupName {
|
||||
rolesMap[role] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
return lo.Keys(rolesMap), nil
|
||||
}
|
||||
|
|
|
@ -2071,3 +2071,32 @@ func TestMetaTable_RestoreRBAC(t *testing.T) {
|
|||
err = mt.RestoreRBAC(context.TODO(), util.DefaultTenant, &milvuspb.RBACMeta{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestMetaTable_PrivilegeGroup(t *testing.T) {
|
||||
catalog := mocks.NewRootCoordCatalog(t)
|
||||
catalog.EXPECT().ListPrivilegeGroups(mock.Anything).Return([]*milvuspb.PrivilegeGroupInfo{
|
||||
{
|
||||
GroupName: "pg1",
|
||||
Privileges: []*milvuspb.PrivilegeEntity{{Name: "CreateCollection"}, {Name: "DescribeCollection"}},
|
||||
},
|
||||
}, nil)
|
||||
catalog.EXPECT().ListRole(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||
catalog.EXPECT().SavePrivilegeGroup(mock.Anything, mock.Anything).Return(nil)
|
||||
catalog.EXPECT().DropPrivilegeGroup(mock.Anything, mock.Anything).Return(nil)
|
||||
mt := &MetaTable{
|
||||
dbName2Meta: map[string]*model.Database{
|
||||
"not_commit": model.NewDatabase(1, "not_commit", pb.DatabaseState_DatabaseCreated, nil),
|
||||
},
|
||||
names: newNameDb(),
|
||||
aliases: newNameDb(),
|
||||
catalog: catalog,
|
||||
}
|
||||
err := mt.CreatePrivilegeGroup("pg1")
|
||||
assert.Error(t, err)
|
||||
err = mt.CreatePrivilegeGroup("pg2")
|
||||
assert.NoError(t, err)
|
||||
err = mt.DropPrivilegeGroup("pg1")
|
||||
assert.NoError(t, err)
|
||||
_, err = mt.ListPrivilegeGroups()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
|
@ -97,6 +97,10 @@ type mockMetaTable struct {
|
|||
ListPolicyFunc func(tenant string) ([]string, error)
|
||||
ListUserRoleFunc func(tenant string) ([]string, error)
|
||||
DescribeDatabaseFunc func(ctx context.Context, dbName string) (*model.Database, error)
|
||||
CreatePrivilegeGroupFunc func(groupName string) error
|
||||
DropPrivilegeGroupFunc func(groupName string) error
|
||||
ListPrivilegeGroupsFunc func() ([]*milvuspb.PrivilegeGroupInfo, error)
|
||||
OperatePrivilegeGroupFunc func(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error
|
||||
}
|
||||
|
||||
func (m mockMetaTable) GetDatabaseByName(ctx context.Context, dbName string, ts Timestamp) (*model.Database, error) {
|
||||
|
@ -251,6 +255,22 @@ func (m mockMetaTable) ListUserRole(tenant string) ([]string, error) {
|
|||
return m.ListUserRoleFunc(tenant)
|
||||
}
|
||||
|
||||
func (m mockMetaTable) CreatePrivilegeGroup(groupName string) error {
|
||||
return m.CreatePrivilegeGroupFunc(groupName)
|
||||
}
|
||||
|
||||
func (m mockMetaTable) DropPrivilegeGroup(groupName string) error {
|
||||
return m.DropPrivilegeGroupFunc(groupName)
|
||||
}
|
||||
|
||||
func (m mockMetaTable) ListPrivilegeGroups() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
return m.ListPrivilegeGroupsFunc()
|
||||
}
|
||||
|
||||
func (m mockMetaTable) OperatePrivilegeGroup(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error {
|
||||
return m.OperatePrivilegeGroupFunc(groupName, privileges, operateType)
|
||||
}
|
||||
|
||||
func newMockMetaTable() *mockMetaTable {
|
||||
return &mockMetaTable{}
|
||||
}
|
||||
|
@ -527,6 +547,18 @@ func withInvalidMeta() Opt {
|
|||
meta.DescribeDatabaseFunc = func(ctx context.Context, dbName string) (*model.Database, error) {
|
||||
return nil, errors.New("error mock DescribeDatabase")
|
||||
}
|
||||
meta.CreatePrivilegeGroupFunc = func(groupName string) error {
|
||||
return errors.New("error mock CreatePrivilegeGroup")
|
||||
}
|
||||
meta.DropPrivilegeGroupFunc = func(groupName string) error {
|
||||
return errors.New("error mock DropPrivilegeGroup")
|
||||
}
|
||||
meta.ListPrivilegeGroupsFunc = func() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
return nil, errors.New("error mock ListPrivilegeGroups")
|
||||
}
|
||||
meta.OperatePrivilegeGroupFunc = func(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error {
|
||||
return errors.New("error mock OperatePrivilegeGroup")
|
||||
}
|
||||
return withMeta(meta)
|
||||
}
|
||||
|
||||
|
|
|
@ -620,6 +620,52 @@ func (_c *IMetaTable_CreateDatabase_Call) RunAndReturn(run func(context.Context,
|
|||
return _c
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup provides a mock function with given fields: groupName
|
||||
func (_m *IMetaTable) CreatePrivilegeGroup(groupName string) error {
|
||||
ret := _m.Called(groupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(groupName)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IMetaTable_CreatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePrivilegeGroup'
|
||||
type IMetaTable_CreatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - groupName string
|
||||
func (_e *IMetaTable_Expecter) CreatePrivilegeGroup(groupName interface{}) *IMetaTable_CreatePrivilegeGroup_Call {
|
||||
return &IMetaTable_CreatePrivilegeGroup_Call{Call: _e.mock.On("CreatePrivilegeGroup", groupName)}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_CreatePrivilegeGroup_Call) Run(run func(groupName string)) *IMetaTable_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_CreatePrivilegeGroup_Call) Return(_a0 error) *IMetaTable_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_CreatePrivilegeGroup_Call) RunAndReturn(run func(string) error) *IMetaTable_CreatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateRole provides a mock function with given fields: tenant, entity
|
||||
func (_m *IMetaTable) CreateRole(tenant string, entity *milvuspb.RoleEntity) error {
|
||||
ret := _m.Called(tenant, entity)
|
||||
|
@ -916,6 +962,52 @@ func (_c *IMetaTable_DropGrant_Call) RunAndReturn(run func(string, *milvuspb.Rol
|
|||
return _c
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup provides a mock function with given fields: groupName
|
||||
func (_m *IMetaTable) DropPrivilegeGroup(groupName string) error {
|
||||
ret := _m.Called(groupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DropPrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(groupName)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IMetaTable_DropPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropPrivilegeGroup'
|
||||
type IMetaTable_DropPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DropPrivilegeGroup is a helper method to define mock.On call
|
||||
// - groupName string
|
||||
func (_e *IMetaTable_Expecter) DropPrivilegeGroup(groupName interface{}) *IMetaTable_DropPrivilegeGroup_Call {
|
||||
return &IMetaTable_DropPrivilegeGroup_Call{Call: _e.mock.On("DropPrivilegeGroup", groupName)}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_DropPrivilegeGroup_Call) Run(run func(groupName string)) *IMetaTable_DropPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_DropPrivilegeGroup_Call) Return(_a0 error) *IMetaTable_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_DropPrivilegeGroup_Call) RunAndReturn(run func(string) error) *IMetaTable_DropPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DropRole provides a mock function with given fields: tenant, roleName
|
||||
func (_m *IMetaTable) DropRole(tenant string, roleName string) error {
|
||||
ret := _m.Called(tenant, roleName)
|
||||
|
@ -1419,6 +1511,64 @@ func (_c *IMetaTable_GetPChannelInfo_Call) RunAndReturn(run func(string) *rootco
|
|||
return _c
|
||||
}
|
||||
|
||||
// GetPrivilegeGroupRoles provides a mock function with given fields: groupName
|
||||
func (_m *IMetaTable) GetPrivilegeGroupRoles(groupName string) ([]*milvuspb.RoleEntity, error) {
|
||||
ret := _m.Called(groupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetPrivilegeGroupRoles")
|
||||
}
|
||||
|
||||
var r0 []*milvuspb.RoleEntity
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) ([]*milvuspb.RoleEntity, error)); ok {
|
||||
return rf(groupName)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) []*milvuspb.RoleEntity); ok {
|
||||
r0 = rf(groupName)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*milvuspb.RoleEntity)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(groupName)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IMetaTable_GetPrivilegeGroupRoles_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPrivilegeGroupRoles'
|
||||
type IMetaTable_GetPrivilegeGroupRoles_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetPrivilegeGroupRoles is a helper method to define mock.On call
|
||||
// - groupName string
|
||||
func (_e *IMetaTable_Expecter) GetPrivilegeGroupRoles(groupName interface{}) *IMetaTable_GetPrivilegeGroupRoles_Call {
|
||||
return &IMetaTable_GetPrivilegeGroupRoles_Call{Call: _e.mock.On("GetPrivilegeGroupRoles", groupName)}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_GetPrivilegeGroupRoles_Call) Run(run func(groupName string)) *IMetaTable_GetPrivilegeGroupRoles_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_GetPrivilegeGroupRoles_Call) Return(_a0 []*milvuspb.RoleEntity, _a1 error) *IMetaTable_GetPrivilegeGroupRoles_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_GetPrivilegeGroupRoles_Call) RunAndReturn(run func(string) ([]*milvuspb.RoleEntity, error)) *IMetaTable_GetPrivilegeGroupRoles_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// IsAlias provides a mock function with given fields: db, name
|
||||
func (_m *IMetaTable) IsAlias(db string, name string) bool {
|
||||
ret := _m.Called(db, name)
|
||||
|
@ -1466,6 +1616,62 @@ func (_c *IMetaTable_IsAlias_Call) RunAndReturn(run func(string, string) bool) *
|
|||
return _c
|
||||
}
|
||||
|
||||
// IsCustomPrivilegeGroup provides a mock function with given fields: groupName
|
||||
func (_m *IMetaTable) IsCustomPrivilegeGroup(groupName string) (bool, error) {
|
||||
ret := _m.Called(groupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for IsCustomPrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (bool, error)); ok {
|
||||
return rf(groupName)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(groupName)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(groupName)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IMetaTable_IsCustomPrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsCustomPrivilegeGroup'
|
||||
type IMetaTable_IsCustomPrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// IsCustomPrivilegeGroup is a helper method to define mock.On call
|
||||
// - groupName string
|
||||
func (_e *IMetaTable_Expecter) IsCustomPrivilegeGroup(groupName interface{}) *IMetaTable_IsCustomPrivilegeGroup_Call {
|
||||
return &IMetaTable_IsCustomPrivilegeGroup_Call{Call: _e.mock.On("IsCustomPrivilegeGroup", groupName)}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_IsCustomPrivilegeGroup_Call) Run(run func(groupName string)) *IMetaTable_IsCustomPrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_IsCustomPrivilegeGroup_Call) Return(_a0 bool, _a1 error) *IMetaTable_IsCustomPrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_IsCustomPrivilegeGroup_Call) RunAndReturn(run func(string) (bool, error)) *IMetaTable_IsCustomPrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListAliases provides a mock function with given fields: ctx, dbName, collectionName, ts
|
||||
func (_m *IMetaTable) ListAliases(ctx context.Context, dbName string, collectionName string, ts uint64) ([]string, error) {
|
||||
ret := _m.Called(ctx, dbName, collectionName, ts)
|
||||
|
@ -1905,6 +2111,63 @@ func (_c *IMetaTable_ListPolicy_Call) RunAndReturn(run func(string) ([]string, e
|
|||
return _c
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups provides a mock function with given fields:
|
||||
func (_m *IMetaTable) ListPrivilegeGroups() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListPrivilegeGroups")
|
||||
}
|
||||
|
||||
var r0 []*milvuspb.PrivilegeGroupInfo
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func() ([]*milvuspb.PrivilegeGroupInfo, error)); ok {
|
||||
return rf()
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func() []*milvuspb.PrivilegeGroupInfo); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*milvuspb.PrivilegeGroupInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IMetaTable_ListPrivilegeGroups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListPrivilegeGroups'
|
||||
type IMetaTable_ListPrivilegeGroups_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListPrivilegeGroups is a helper method to define mock.On call
|
||||
func (_e *IMetaTable_Expecter) ListPrivilegeGroups() *IMetaTable_ListPrivilegeGroups_Call {
|
||||
return &IMetaTable_ListPrivilegeGroups_Call{Call: _e.mock.On("ListPrivilegeGroups")}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_ListPrivilegeGroups_Call) Run(run func()) *IMetaTable_ListPrivilegeGroups_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_ListPrivilegeGroups_Call) Return(_a0 []*milvuspb.PrivilegeGroupInfo, _a1 error) *IMetaTable_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_ListPrivilegeGroups_Call) RunAndReturn(run func() ([]*milvuspb.PrivilegeGroupInfo, error)) *IMetaTable_ListPrivilegeGroups_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListUserRole provides a mock function with given fields: tenant
|
||||
func (_m *IMetaTable) ListUserRole(tenant string) ([]string, error) {
|
||||
ret := _m.Called(tenant)
|
||||
|
@ -2011,6 +2274,54 @@ func (_c *IMetaTable_OperatePrivilege_Call) RunAndReturn(run func(string, *milvu
|
|||
return _c
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup provides a mock function with given fields: groupName, privileges, operateType
|
||||
func (_m *IMetaTable) OperatePrivilegeGroup(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType) error {
|
||||
ret := _m.Called(groupName, privileges, operateType)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OperatePrivilegeGroup")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, []*milvuspb.PrivilegeEntity, milvuspb.OperatePrivilegeGroupType) error); ok {
|
||||
r0 = rf(groupName, privileges, operateType)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IMetaTable_OperatePrivilegeGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OperatePrivilegeGroup'
|
||||
type IMetaTable_OperatePrivilegeGroup_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// OperatePrivilegeGroup is a helper method to define mock.On call
|
||||
// - groupName string
|
||||
// - privileges []*milvuspb.PrivilegeEntity
|
||||
// - operateType milvuspb.OperatePrivilegeGroupType
|
||||
func (_e *IMetaTable_Expecter) OperatePrivilegeGroup(groupName interface{}, privileges interface{}, operateType interface{}) *IMetaTable_OperatePrivilegeGroup_Call {
|
||||
return &IMetaTable_OperatePrivilegeGroup_Call{Call: _e.mock.On("OperatePrivilegeGroup", groupName, privileges, operateType)}
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_OperatePrivilegeGroup_Call) Run(run func(groupName string, privileges []*milvuspb.PrivilegeEntity, operateType milvuspb.OperatePrivilegeGroupType)) *IMetaTable_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].([]*milvuspb.PrivilegeEntity), args[2].(milvuspb.OperatePrivilegeGroupType))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_OperatePrivilegeGroup_Call) Return(_a0 error) *IMetaTable_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *IMetaTable_OperatePrivilegeGroup_Call) RunAndReturn(run func(string, []*milvuspb.PrivilegeEntity, milvuspb.OperatePrivilegeGroupType) error) *IMetaTable_OperatePrivilegeGroup_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// OperateUserRole provides a mock function with given fields: tenant, userEntity, roleEntity, operateType
|
||||
func (_m *IMetaTable) OperateUserRole(tenant string, userEntity *milvuspb.UserEntity, roleEntity *milvuspb.RoleEntity, operateType milvuspb.OperateUserRoleType) error {
|
||||
ret := _m.Called(tenant, userEntity, roleEntity, operateType)
|
||||
|
|
|
@ -635,7 +635,11 @@ func (c *Core) initBuiltinRoles() error {
|
|||
for _, privilege := range privilegesJSON[util.RoleConfigPrivileges] {
|
||||
privilegeName := privilege[util.RoleConfigPrivilege]
|
||||
if !util.IsAnyWord(privilege[util.RoleConfigPrivilege]) {
|
||||
privilegeName = util.PrivilegeNameForMetastore(privilege[util.RoleConfigPrivilege])
|
||||
dbPrivName, err := c.getMetastorePrivilegeName(privilege[util.RoleConfigPrivilege])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get metastore privilege name for: %s", privilege[util.RoleConfigPrivilege])
|
||||
}
|
||||
privilegeName = dbPrivName
|
||||
}
|
||||
err := c.meta.OperatePrivilege(util.DefaultTenant, &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: role},
|
||||
|
@ -2503,11 +2507,8 @@ func (c *Core) isValidGrantor(entity *milvuspb.GrantorEntity, object string) err
|
|||
if entity == nil {
|
||||
return errors.New("the grantor entity is nil")
|
||||
}
|
||||
if entity.User == nil {
|
||||
return errors.New("the user entity in the grantor entity is nil")
|
||||
}
|
||||
if entity.User.Name == "" {
|
||||
return errors.New("the name in the user entity of the grantor entity is empty")
|
||||
if entity.User == nil || entity.User.Name == "" {
|
||||
return errors.New("the user entity in the grantor entity is nil or empty")
|
||||
}
|
||||
if _, err := c.meta.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: entity.User.Name}, false); err != nil {
|
||||
log.Warn("fail to select the user", zap.String("username", entity.User.Name), zap.Error(err))
|
||||
|
@ -2519,17 +2520,25 @@ func (c *Core) isValidGrantor(entity *milvuspb.GrantorEntity, object string) err
|
|||
if util.IsAnyWord(entity.Privilege.Name) {
|
||||
return nil
|
||||
}
|
||||
if privilegeName := util.PrivilegeNameForMetastore(entity.Privilege.Name); privilegeName == "" {
|
||||
return fmt.Errorf("not found the privilege name[%s]", entity.Privilege.Name)
|
||||
}
|
||||
privileges, ok := util.ObjectPrivileges[object]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found the object type[name: %s], supported the object types: %v", object, lo.Keys(commonpb.ObjectType_value))
|
||||
}
|
||||
for _, privilege := range privileges {
|
||||
if privilege == entity.Privilege.Name {
|
||||
return nil
|
||||
// check object privileges for built-in privileges
|
||||
if util.IsPrivilegeNameDefined(entity.Privilege.Name) {
|
||||
privileges, ok := util.ObjectPrivileges[object]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found the object type[name: %s], supported the object types: %v", object, lo.Keys(commonpb.ObjectType_value))
|
||||
}
|
||||
for _, privilege := range privileges {
|
||||
if privilege == entity.Privilege.Name {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if it is a custom privilege group
|
||||
customPrivGroup, err := c.meta.IsCustomPrivilegeGroup(entity.Privilege.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if customPrivGroup {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("not found the privilege name[%s] in object[%s]", entity.Privilege.Name, object)
|
||||
}
|
||||
|
@ -2574,11 +2583,18 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
|
|||
return merr.StatusWithErrorCode(err, commonpb.ErrorCode_OperatePrivilegeFailure), nil
|
||||
}
|
||||
|
||||
ctxLog.Debug("before PrivilegeNameForMetastore", zap.String("privilege", in.Entity.Grantor.Privilege.Name))
|
||||
if !util.IsAnyWord(in.Entity.Grantor.Privilege.Name) {
|
||||
in.Entity.Grantor.Privilege.Name = util.PrivilegeNameForMetastore(in.Entity.Grantor.Privilege.Name)
|
||||
// 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", in.Entity.Grantor.Privilege.Name))
|
||||
ctxLog.Debug("after PrivilegeNameForMetastore", zap.String("privilege", privName))
|
||||
|
||||
if in.Entity.Object.Name == commonpb.ObjectType_Global.String() {
|
||||
in.Entity.ObjectName = util.AnyWord
|
||||
}
|
||||
|
@ -2626,6 +2642,22 @@ func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivile
|
|||
return merr.Success(), nil
|
||||
}
|
||||
|
||||
func (c *Core) getMetastorePrivilegeName(privName string) (string, error) {
|
||||
// if it is built-in privilege, return the privilege name directly
|
||||
if util.IsPrivilegeNameDefined(privName) {
|
||||
return util.PrivilegeNameForMetastore(privName), nil
|
||||
}
|
||||
// return the privilege group name if it is a custom privilege group
|
||||
customGroup, err := c.meta.IsCustomPrivilegeGroup(privName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if customGroup {
|
||||
return util.PrivilegeGroupNameForMetastore(privName), nil
|
||||
}
|
||||
return "", errors.New("not found the privilege name")
|
||||
}
|
||||
|
||||
// SelectGrant select grant
|
||||
// - check the node health
|
||||
// - check if the principal entity is valid
|
||||
|
@ -2718,14 +2750,23 @@ func (c *Core) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest)
|
|||
Status: merr.StatusWithErrorCode(errors.New(errMsg), commonpb.ErrorCode_ListPolicyFailure),
|
||||
}, nil
|
||||
}
|
||||
privGroups, err := c.meta.ListPrivilegeGroups()
|
||||
if err != nil {
|
||||
errMsg := "fail to list privilege groups"
|
||||
ctxLog.Warn(errMsg, zap.Error(err))
|
||||
return &internalpb.ListPolicyResponse{
|
||||
Status: merr.StatusWithErrorCode(errors.New(errMsg), commonpb.ErrorCode_ListPolicyFailure),
|
||||
}, nil
|
||||
}
|
||||
|
||||
ctxLog.Debug(method + " success")
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
|
||||
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
|
||||
return &internalpb.ListPolicyResponse{
|
||||
Status: merr.Success(),
|
||||
PolicyInfos: policies,
|
||||
UserRoles: userRoles,
|
||||
Status: merr.Success(),
|
||||
PolicyInfos: policies,
|
||||
UserRoles: userRoles,
|
||||
PrivilegeGroups: privGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -2926,3 +2967,236 @@ func (c *Core) CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest)
|
|||
|
||||
return &milvuspb.CheckHealthResponse{Status: merr.Success(), IsHealthy: true, Reasons: []string{}}, nil
|
||||
}
|
||||
|
||||
func (c *Core) CreatePrivilegeGroup(ctx context.Context, in *milvuspb.CreatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
method := "CreatePrivilegeGroup"
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
|
||||
tr := timerecord.NewTimeRecorder(method)
|
||||
ctxLog := log.Ctx(ctx).With(zap.String("role", typeutil.RootCoordRole), zap.Any("in", in))
|
||||
ctxLog.Debug(method)
|
||||
|
||||
if err := merr.CheckHealthy(c.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
|
||||
if err := c.meta.CreatePrivilegeGroup(in.GroupName); err != nil {
|
||||
ctxLog.Warn("fail to create privilege group", zap.Error(err))
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
|
||||
ctxLog.Debug(method + " success")
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
|
||||
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
|
||||
metrics.RootCoordNumOfPrivilegeGroups.Inc()
|
||||
return merr.Success(), nil
|
||||
}
|
||||
|
||||
func (c *Core) DropPrivilegeGroup(ctx context.Context, in *milvuspb.DropPrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
method := "DropPrivilegeGroup"
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
|
||||
tr := timerecord.NewTimeRecorder(method)
|
||||
ctxLog := log.Ctx(ctx).With(zap.String("role", typeutil.RootCoordRole), zap.Any("in", in))
|
||||
ctxLog.Debug(method)
|
||||
|
||||
if err := merr.CheckHealthy(c.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
|
||||
if err := c.meta.DropPrivilegeGroup(in.GroupName); err != nil {
|
||||
ctxLog.Warn("fail to drop privilege group", zap.Error(err))
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
|
||||
ctxLog.Debug(method + " success")
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
|
||||
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
|
||||
metrics.RootCoordNumOfPrivilegeGroups.Desc()
|
||||
return merr.Success(), nil
|
||||
}
|
||||
|
||||
func (c *Core) ListPrivilegeGroups(ctx context.Context, in *milvuspb.ListPrivilegeGroupsRequest) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
method := "ListPrivilegeGroups"
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
|
||||
tr := timerecord.NewTimeRecorder(method)
|
||||
ctxLog := log.Ctx(ctx).With(zap.String("role", typeutil.RootCoordRole), zap.Any("in", in))
|
||||
ctxLog.Debug(method)
|
||||
|
||||
if err := merr.CheckHealthy(c.GetStateCode()); err != nil {
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{
|
||||
Status: merr.Status(err),
|
||||
}, nil
|
||||
}
|
||||
|
||||
privGroups, err := c.meta.ListPrivilegeGroups()
|
||||
if err != nil {
|
||||
ctxLog.Warn("fail to list privilege group", zap.Error(err))
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{
|
||||
Status: merr.StatusWithErrorCode(err, commonpb.ErrorCode_ListPrivilegeGroupsFailure),
|
||||
}, nil
|
||||
}
|
||||
|
||||
ctxLog.Debug(method + " success")
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
|
||||
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{
|
||||
Status: merr.Success(),
|
||||
PrivilegeGroups: privGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Core) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePrivilegeGroupRequest) (*commonpb.Status, error) {
|
||||
method := "OperatePrivilegeGroup-" + in.Type.String()
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
|
||||
tr := timerecord.NewTimeRecorder(method)
|
||||
ctxLog := log.Ctx(ctx).With(zap.String("role", typeutil.RootCoordRole), zap.Any("in", in))
|
||||
ctxLog.Debug(method)
|
||||
|
||||
if err := merr.CheckHealthy(c.GetStateCode()); err != nil {
|
||||
return merr.Status(err), nil
|
||||
}
|
||||
|
||||
redoTask := newBaseRedoTask(c.stepExecutor)
|
||||
redoTask.AddSyncStep(NewSimpleStep("operate privilege group", func(ctx context.Context) ([]nestedStep, error) {
|
||||
groups, err := c.meta.ListPrivilegeGroups()
|
||||
if err != nil && !common.IsIgnorableError(err) {
|
||||
log.Warn("fail to list privilege groups", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
currGroups := lo.SliceToMap(groups, func(group *milvuspb.PrivilegeGroupInfo) (string, []*milvuspb.PrivilegeEntity) {
|
||||
return group.GroupName, group.Privileges
|
||||
})
|
||||
|
||||
// get roles granted to the group
|
||||
roles, err := c.meta.GetPrivilegeGroupRoles(in.GroupName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newGroups := make(map[string][]*milvuspb.PrivilegeEntity)
|
||||
for k, v := range currGroups {
|
||||
if k != in.GroupName {
|
||||
newGroups[k] = v
|
||||
continue
|
||||
}
|
||||
switch in.Type {
|
||||
case milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup:
|
||||
newPrivs := lo.Union(v, in.Privileges)
|
||||
newGroups[k] = lo.UniqBy(newPrivs, func(p *milvuspb.PrivilegeEntity) string {
|
||||
return p.Name
|
||||
})
|
||||
case milvuspb.OperatePrivilegeGroupType_RemovePrivilegesFromGroup:
|
||||
newPrivs, _ := lo.Difference(v, in.Privileges)
|
||||
newGroups[k] = newPrivs
|
||||
default:
|
||||
return nil, errors.New("invalid operate type")
|
||||
}
|
||||
}
|
||||
|
||||
rolesToRevoke := []*milvuspb.GrantEntity{}
|
||||
rolesToGrant := []*milvuspb.GrantEntity{}
|
||||
compareGrants := func(a, b *milvuspb.GrantEntity) bool {
|
||||
return a.Role.GetName() == b.Role.GetName() &&
|
||||
a.Object.GetName() == b.Object.GetName() &&
|
||||
a.ObjectName == b.ObjectName &&
|
||||
a.Grantor.GetUser().GetName() == b.Grantor.GetUser().GetName() &&
|
||||
a.Grantor.GetPrivilege().GetName() == b.Grantor.GetPrivilege().GetName() &&
|
||||
a.DbName == b.DbName
|
||||
}
|
||||
for _, role := range roles {
|
||||
grants, err := c.meta.SelectGrant(util.DefaultTenant, &milvuspb.GrantEntity{
|
||||
Role: role,
|
||||
DbName: util.AnyWord,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currGrants := c.expandPrivilegeGroups(grants, currGroups)
|
||||
newGrants := c.expandPrivilegeGroups(grants, newGroups)
|
||||
|
||||
toRevoke := lo.Filter(currGrants, func(item *milvuspb.GrantEntity, _ int) bool {
|
||||
return !lo.ContainsBy(newGrants, func(newItem *milvuspb.GrantEntity) bool {
|
||||
return compareGrants(item, newItem)
|
||||
})
|
||||
})
|
||||
|
||||
toGrant := lo.Filter(newGrants, func(item *milvuspb.GrantEntity, _ int) bool {
|
||||
return !lo.ContainsBy(currGrants, func(currItem *milvuspb.GrantEntity) bool {
|
||||
return compareGrants(item, currItem)
|
||||
})
|
||||
})
|
||||
|
||||
rolesToRevoke = append(rolesToRevoke, toRevoke...)
|
||||
rolesToGrant = append(rolesToGrant, toGrant...)
|
||||
}
|
||||
|
||||
if len(rolesToRevoke) > 0 {
|
||||
opType := int32(typeutil.CacheRevokePrivilege)
|
||||
if err := c.proxyClientManager.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
|
||||
OpType: opType,
|
||||
OpKey: funcutil.PolicyForPrivileges(rolesToRevoke),
|
||||
}); err != nil {
|
||||
log.Warn("fail to refresh policy info cache for revoke privileges in operate privilege group", zap.Any("in", in), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(rolesToGrant) > 0 {
|
||||
opType := int32(typeutil.CacheGrantPrivilege)
|
||||
if err := c.proxyClientManager.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
|
||||
OpType: opType,
|
||||
OpKey: funcutil.PolicyForPrivileges(rolesToGrant),
|
||||
}); err != nil {
|
||||
log.Warn("fail to refresh policy info cache for grants privilege in operate privilege group", zap.Any("in", in), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}))
|
||||
|
||||
redoTask.AddSyncStep(NewSimpleStep("operate privilege group meta data", func(ctx context.Context) ([]nestedStep, error) {
|
||||
err := c.meta.OperatePrivilegeGroup(in.GroupName, in.Privileges, in.Type)
|
||||
if err != nil && !common.IsIgnorableError(err) {
|
||||
log.Warn("fail to operate privilege group", zap.Error(err))
|
||||
}
|
||||
return nil, err
|
||||
}))
|
||||
|
||||
err := redoTask.Execute(ctx)
|
||||
if err != nil {
|
||||
errMsg := "fail to execute task when operate privilege group"
|
||||
ctxLog.Warn(errMsg, zap.Error(err))
|
||||
status := merr.StatusWithErrorCode(errors.New(errMsg), commonpb.ErrorCode_OperatePrivilegeGroupFailure)
|
||||
return status, nil
|
||||
}
|
||||
|
||||
ctxLog.Debug(method + " success")
|
||||
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
|
||||
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
|
||||
return merr.Success(), nil
|
||||
}
|
||||
|
||||
func (c *Core) expandPrivilegeGroups(grants []*milvuspb.GrantEntity, groups map[string][]*milvuspb.PrivilegeEntity) []*milvuspb.GrantEntity {
|
||||
newGrants := []*milvuspb.GrantEntity{}
|
||||
for _, grant := range grants {
|
||||
if groups[grant.Grantor.Privilege.Name] == nil {
|
||||
newGrants = append(newGrants, grant)
|
||||
} else {
|
||||
for _, priv := range groups[grant.Grantor.Privilege.Name] {
|
||||
newGrants = append(newGrants, &milvuspb.GrantEntity{
|
||||
Role: grant.Role,
|
||||
Object: grant.Object,
|
||||
ObjectName: grant.ObjectName,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: grant.Grantor.User,
|
||||
Privilege: priv,
|
||||
},
|
||||
DbName: grant.DbName,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1748,6 +1748,9 @@ func TestRootCoord_RBACError(t *testing.T) {
|
|||
mockMeta.SelectRoleFunc = func(tenant string, entity *milvuspb.RoleEntity, includeUserInfo bool) ([]*milvuspb.RoleResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
mockMeta.ListPrivilegeGroupsFunc = func() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
{
|
||||
resp, err := c.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: "foo"},
|
||||
|
@ -1879,6 +1882,9 @@ func TestRootCoord_BuiltinRoles(t *testing.T) {
|
|||
mockMeta.OperatePrivilegeFunc = func(tenant string, entity *milvuspb.GrantEntity, operateType milvuspb.OperatePrivilegeType) error {
|
||||
return nil
|
||||
}
|
||||
mockMeta.ListPrivilegeGroupsFunc = func() ([]*milvuspb.PrivilegeGroupInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
err := c.initBuiltinRoles()
|
||||
assert.Equal(t, nil, err)
|
||||
assert.True(t, util.IsBuiltinRole(roleDbAdmin))
|
||||
|
|
|
@ -274,6 +274,22 @@ func (m *GrpcRootCoordClient) RestoreRBAC(ctx context.Context, in *milvuspb.Rest
|
|||
return &commonpb.Status{}, m.Err
|
||||
}
|
||||
|
||||
func (m *GrpcRootCoordClient) CreatePrivilegeGroup(ctx context.Context, in *milvuspb.CreatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, m.Err
|
||||
}
|
||||
|
||||
func (m *GrpcRootCoordClient) DropPrivilegeGroup(ctx context.Context, in *milvuspb.DropPrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, m.Err
|
||||
}
|
||||
|
||||
func (m *GrpcRootCoordClient) ListPrivilegeGroups(ctx context.Context, in *milvuspb.ListPrivilegeGroupsRequest, opts ...grpc.CallOption) (*milvuspb.ListPrivilegeGroupsResponse, error) {
|
||||
return &milvuspb.ListPrivilegeGroupsResponse{}, m.Err
|
||||
}
|
||||
|
||||
func (m *GrpcRootCoordClient) OperatePrivilegeGroup(ctx context.Context, in *milvuspb.OperatePrivilegeGroupRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
|
||||
return &commonpb.Status{}, m.Err
|
||||
}
|
||||
|
||||
func (m *GrpcRootCoordClient) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -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.20241106083218-5de5d0cfb1c1
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620
|
||||
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.20241106083218-5de5d0cfb1c1 h1:GFS5AxKPcEstcfJgMGxRH+l/mKA0kK1sHDOxnOqMnoA=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241106083218-5de5d0cfb1c1/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620 h1:0IWUDtDloift7cQHalhdjuVkL/3qSeiXFqR7MofZBkg=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620/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=
|
||||
|
|
|
@ -146,6 +146,15 @@ var (
|
|||
Help: "The number of roles",
|
||||
})
|
||||
|
||||
// RootCoordNumOfPrivilegeGroups counts the number of credentials.
|
||||
RootCoordNumOfPrivilegeGroups = prometheus.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: milvusNamespace,
|
||||
Subsystem: typeutil.RootCoordRole,
|
||||
Name: "num_of_privilege_groups",
|
||||
Help: "The number of privilege groups",
|
||||
})
|
||||
|
||||
// RootCoordTtDelay records the max time tick delay of flow graphs in DataNodes and QueryNodes.
|
||||
RootCoordTtDelay = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
|
||||
"github.com/milvus-io/milvus/pkg/common"
|
||||
"github.com/milvus-io/milvus/pkg/util/typeutil"
|
||||
)
|
||||
|
||||
// Meta Prefix consts
|
||||
|
@ -114,6 +115,10 @@ var (
|
|||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGetFlushState.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupReadOnly.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupReadWrite.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListPrivilegeGroups.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeOperatePrivilegeGroup.String()),
|
||||
},
|
||||
commonpb.ObjectType_Global.String(): {
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeAll.String()),
|
||||
|
@ -151,6 +156,10 @@ var (
|
|||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDescribeAlias.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListAliases.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeGroupAdmin.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeCreatePrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeDropPrivilegeGroup.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeListPrivilegeGroups.String()),
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeOperatePrivilegeGroup.String()),
|
||||
},
|
||||
commonpb.ObjectType_User.String(): {
|
||||
MetaStore2API(commonpb.ObjectPrivilege_PrivilegeUpdateUser.String()),
|
||||
|
@ -306,6 +315,9 @@ func MetaStore2API(name string) string {
|
|||
func PrivilegeNameForAPI(name string) string {
|
||||
_, ok := commonpb.ObjectPrivilege_value[name]
|
||||
if !ok {
|
||||
if strings.HasPrefix(name, PrivilegeGroupWord) {
|
||||
return typeutil.After(name, PrivilegeGroupWord)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return MetaStore2API(name)
|
||||
|
@ -327,6 +339,15 @@ func PrivilegeNameForMetastore(name string) string {
|
|||
return dbPrivilege
|
||||
}
|
||||
|
||||
// check if the name is defined by built in privileges or privilege groups in system
|
||||
func IsPrivilegeNameDefined(name string) bool {
|
||||
return PrivilegeNameForMetastore(name) != ""
|
||||
}
|
||||
|
||||
func PrivilegeGroupNameForMetastore(name string) string {
|
||||
return PrivilegeGroupWord + name
|
||||
}
|
||||
|
||||
func IsAnyWord(word string) bool {
|
||||
return word == AnyWord
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/samber/lo"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
@ -114,6 +115,16 @@ func PolicyForPrivilege(roleName string, objectType string, objectName string, p
|
|||
return fmt.Sprintf(`{"PType":"p","V0":"%s","V1":"%s","V2":"%s"}`, roleName, PolicyForResource(dbName, objectType, objectName), privilege)
|
||||
}
|
||||
|
||||
func PolicyForPrivileges(grants []*milvuspb.GrantEntity) string {
|
||||
return strings.Join(lo.Map(grants, func(r *milvuspb.GrantEntity, _ int) string {
|
||||
return PolicyForPrivilege(r.Role.Name, r.Object.Name, r.ObjectName, r.Grantor.Privilege.Name, r.DbName)
|
||||
}), "|")
|
||||
}
|
||||
|
||||
func PrivilegesForPolicy(policy string) []string {
|
||||
return strings.Split(policy, "|")
|
||||
}
|
||||
|
||||
func PolicyForResource(dbName string, objectType string, objectName string) string {
|
||||
return fmt.Sprintf("%s-%s", objectType, CombineObjectName(dbName, objectName))
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package rbac
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
@ -41,94 +42,194 @@ func (s *PrivilegeGroupTestSuite) SetupSuite() {
|
|||
paramtable.Get().Save(paramtable.Get().CommonCfg.AuthorizationEnabled.Key, "true")
|
||||
}
|
||||
|
||||
func (s *PrivilegeGroupTestSuite) TestPrivilegeGroup() {
|
||||
func (s *PrivilegeGroupTestSuite) TestBuiltinPrivilegeGroup() {
|
||||
ctx := GetContext(context.Background(), "root:123456")
|
||||
// test empty rbac content
|
||||
|
||||
// Test empty RBAC content
|
||||
resp, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp.GetStatus()))
|
||||
s.Equal("", resp.GetRBACMeta().String())
|
||||
|
||||
// generate some rbac content
|
||||
// Generate some RBAC content
|
||||
roleName := "test_role"
|
||||
resp1, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
|
||||
Entity: &milvuspb.RoleEntity{
|
||||
Name: roleName,
|
||||
},
|
||||
createRoleResp, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
|
||||
Entity: &milvuspb.RoleEntity{Name: roleName},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp1))
|
||||
resp2, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Grant,
|
||||
s.True(merr.Ok(createRoleResp))
|
||||
|
||||
s.operatePrivilege(ctx, roleName, "ReadOnly", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
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.validateGrants(ctx, roleName, commonpb.ObjectType_Collection.String(), 2)
|
||||
}
|
||||
|
||||
/*
|
||||
create group1: query, search
|
||||
grant insert to role -> role: insert
|
||||
grant group1 to role -> role: insert, group1(query, search)
|
||||
create group2: query, delete
|
||||
grant group2 to role -> role: insert, group1(query, search), group2(query, delete)
|
||||
add query, load to group1 -> group1: query, search, load -> role: insert, group1(query, search, load), group2(query, delete)
|
||||
remove query from group1 -> group1: search, load -> role: insert, group1(search, load), group2(query, delete), role still have query privilege because of group2 granted.
|
||||
*/
|
||||
func (s *PrivilegeGroupTestSuite) TestCustomPrivilegeGroup() {
|
||||
ctx := GetContext(context.Background(), "root:123456")
|
||||
|
||||
// Helper function to operate on privilege groups
|
||||
operatePrivilegeGroup := func(groupName string, operateType milvuspb.OperatePrivilegeGroupType, privileges []*milvuspb.PrivilegeEntity) {
|
||||
resp, err := s.Cluster.Proxy.OperatePrivilegeGroup(ctx, &milvuspb.OperatePrivilegeGroupRequest{
|
||||
GroupName: groupName,
|
||||
Type: operateType,
|
||||
Privileges: privileges,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp))
|
||||
}
|
||||
|
||||
// Helper function to list privilege groups and return the target group and its privileges
|
||||
validatePrivilegeGroup := func(groupName string, privileges int) []*milvuspb.PrivilegeEntity {
|
||||
resp, err := s.Cluster.Proxy.ListPrivilegeGroups(ctx, &milvuspb.ListPrivilegeGroupsRequest{})
|
||||
s.NoError(err)
|
||||
for _, privGroup := range resp.PrivilegeGroups {
|
||||
if privGroup.GroupName == groupName {
|
||||
s.Equal(privileges, len(privGroup.Privileges))
|
||||
return privGroup.Privileges
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// create group1: query, search
|
||||
createResp, err := s.Cluster.Proxy.CreatePrivilegeGroup(ctx, &milvuspb.CreatePrivilegeGroupRequest{
|
||||
GroupName: "group1",
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(createResp))
|
||||
validatePrivilegeGroup("group1", 0)
|
||||
operatePrivilegeGroup("group1", milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup, []*milvuspb.PrivilegeEntity{
|
||||
{Name: "Query"},
|
||||
{Name: "Search"},
|
||||
})
|
||||
validatePrivilegeGroup("group1", 2)
|
||||
|
||||
// grant insert to role -> role: insert
|
||||
role := "role1"
|
||||
createRoleResp, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
|
||||
Entity: &milvuspb.RoleEntity{Name: role},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(createRoleResp))
|
||||
s.operatePrivilege(ctx, role, "Insert", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.validateGrants(ctx, role, commonpb.ObjectType_Collection.String(), 1)
|
||||
|
||||
// grant group1 to role -> role: insert, group1(query, search)
|
||||
s.operatePrivilege(ctx, role, "group1", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.validateGrants(ctx, role, commonpb.ObjectType_Collection.String(), 2)
|
||||
|
||||
// create group2: query, delete
|
||||
createResp2, err := s.Cluster.Proxy.CreatePrivilegeGroup(ctx, &milvuspb.CreatePrivilegeGroupRequest{
|
||||
GroupName: "group2",
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(createResp2))
|
||||
validatePrivilegeGroup("group2", 0)
|
||||
operatePrivilegeGroup("group2", milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup, []*milvuspb.PrivilegeEntity{
|
||||
{Name: "Query"},
|
||||
{Name: "Delete"},
|
||||
})
|
||||
validatePrivilegeGroup("group2", 2)
|
||||
|
||||
// grant group2 to role -> role: insert, group1(query, search), group2(query, delete)
|
||||
s.operatePrivilege(ctx, role, "group2", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Grant)
|
||||
s.validateGrants(ctx, role, commonpb.ObjectType_Collection.String(), 3)
|
||||
|
||||
// add query, load to group1 -> group1: query, search, load -> role: insert, group1(query, search, load), group2(query, delete)
|
||||
operatePrivilegeGroup("group1", milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup, []*milvuspb.PrivilegeEntity{
|
||||
{Name: "Query"},
|
||||
{Name: "Load"},
|
||||
})
|
||||
validatePrivilegeGroup("group1", 3)
|
||||
s.validateGrants(ctx, role, commonpb.ObjectType_Collection.String(), 3)
|
||||
|
||||
// remove query from group1 -> group1: search, load -> role: insert, group1(search, load), group2(query, delete), role still have query privilege because of group2 granted.
|
||||
operatePrivilegeGroup("group1", milvuspb.OperatePrivilegeGroupType_RemovePrivilegesFromGroup, []*milvuspb.PrivilegeEntity{
|
||||
{Name: "Query"},
|
||||
})
|
||||
validatePrivilegeGroup("group1", 2)
|
||||
s.validateGrants(ctx, role, commonpb.ObjectType_Collection.String(), 3)
|
||||
|
||||
// Drop the group during any role usage will cause error
|
||||
dropResp, _ := s.Cluster.Proxy.DropPrivilegeGroup(ctx, &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: "group1",
|
||||
})
|
||||
s.Error(merr.Error(dropResp))
|
||||
|
||||
// Revoke privilege group and privileges
|
||||
s.operatePrivilege(ctx, role, "group1", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Revoke)
|
||||
s.operatePrivilege(ctx, role, "group2", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Revoke)
|
||||
s.operatePrivilege(ctx, role, "Insert", commonpb.ObjectType_Collection.String(), milvuspb.OperatePrivilegeType_Revoke)
|
||||
|
||||
// Drop the privilege group after revoking the privilege will succeed
|
||||
dropResp, err = s.Cluster.Proxy.DropPrivilegeGroup(ctx, &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: "group1",
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(dropResp))
|
||||
|
||||
dropResp, err = s.Cluster.Proxy.DropPrivilegeGroup(ctx, &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: "group2",
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(dropResp))
|
||||
|
||||
// Validate the group was dropped
|
||||
resp, err := s.Cluster.Proxy.ListPrivilegeGroups(ctx, &milvuspb.ListPrivilegeGroupsRequest{})
|
||||
s.NoError(err)
|
||||
s.Equal(0, len(resp.PrivilegeGroups))
|
||||
|
||||
// Drop the role
|
||||
dropRoleResp, err := s.Cluster.Proxy.DropRole(ctx, &milvuspb.DropRoleRequest{
|
||||
RoleName: role,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(dropRoleResp))
|
||||
}
|
||||
|
||||
func (s *PrivilegeGroupTestSuite) operatePrivilege(ctx context.Context, role, privilege, objectType string, operateType milvuspb.OperatePrivilegeType) {
|
||||
resp, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: operateType,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
Role: &milvuspb.RoleEntity{Name: role},
|
||||
Object: &milvuspb.ObjectEntity{Name: objectType},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "ReadOnly"},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: privilege},
|
||||
},
|
||||
},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp2))
|
||||
s.True(merr.Ok(resp))
|
||||
}
|
||||
|
||||
resp3, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Grant,
|
||||
func (s *PrivilegeGroupTestSuite) validateGrants(ctx context.Context, roleName, objectType string, expectedCount int) {
|
||||
resp, err := s.Cluster.Proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "ReadWrite"},
|
||||
},
|
||||
},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp3))
|
||||
|
||||
resp4, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Grant,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Admin"},
|
||||
},
|
||||
},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp4))
|
||||
|
||||
resp5, err := s.Cluster.Proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
|
||||
Object: &milvuspb.ObjectEntity{Name: objectType},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
},
|
||||
})
|
||||
fmt.Println("!!!validateGrants: ", resp)
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp5.GetStatus()))
|
||||
s.Len(resp5.GetEntities(), 1)
|
||||
|
||||
resp6, err := s.Cluster.Proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp6.GetStatus()))
|
||||
s.Len(resp6.GetEntities(), 2)
|
||||
s.True(merr.Ok(resp.GetStatus()))
|
||||
s.Len(resp.GetEntities(), expectedCount)
|
||||
}
|
||||
|
||||
func TestPrivilegeGroup(t *testing.T) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
|
@ -63,131 +64,161 @@ func GetContext(ctx context.Context, originValue string) context.Context {
|
|||
|
||||
func (s *RBACBackupTestSuite) TestBackup() {
|
||||
ctx := GetContext(context.Background(), "root:123456")
|
||||
|
||||
createRole := func(name string) {
|
||||
resp, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
|
||||
Entity: &milvuspb.RoleEntity{Name: name},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp))
|
||||
}
|
||||
|
||||
operatePrivilege := func(role, privilege, objectName, dbName string, operateType milvuspb.OperatePrivilegeType) {
|
||||
resp, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: operateType,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: role},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: objectName,
|
||||
DbName: dbName,
|
||||
Grantor: &milvuspb.GrantorEntity{User: &milvuspb.UserEntity{Name: util.UserRoot}, Privilege: &milvuspb.PrivilegeEntity{Name: privilege}},
|
||||
},
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp))
|
||||
}
|
||||
|
||||
// test empty rbac content
|
||||
resp, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
emptyBackupRBACResp, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp.GetStatus()))
|
||||
s.Equal("", resp.GetRBACMeta().String())
|
||||
s.True(merr.Ok(emptyBackupRBACResp.GetStatus()))
|
||||
s.Equal("", emptyBackupRBACResp.GetRBACMeta().String())
|
||||
|
||||
// generate some rbac content
|
||||
// create role test_role
|
||||
roleName := "test_role"
|
||||
resp1, err := s.Cluster.Proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{
|
||||
Entity: &milvuspb.RoleEntity{
|
||||
Name: roleName,
|
||||
},
|
||||
createRole(roleName)
|
||||
|
||||
// grant collection level search privilege to role test_role
|
||||
operatePrivilege(roleName, "Search", util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Grant)
|
||||
|
||||
// create privielge group test_group
|
||||
groupName := "test_group"
|
||||
createPrivGroupResp, err := s.Cluster.Proxy.CreatePrivilegeGroup(ctx, &milvuspb.CreatePrivilegeGroupRequest{
|
||||
GroupName: groupName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp1))
|
||||
resp2, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Grant,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Search"},
|
||||
},
|
||||
},
|
||||
s.True(merr.Ok(createPrivGroupResp))
|
||||
|
||||
// add query and insert privilege to group test_group
|
||||
addPrivsToGroupResp, err := s.Cluster.Proxy.OperatePrivilegeGroup(ctx, &milvuspb.OperatePrivilegeGroupRequest{
|
||||
GroupName: groupName,
|
||||
Privileges: []*milvuspb.PrivilegeEntity{{Name: "Query"}, {Name: "Insert"}},
|
||||
Type: milvuspb.OperatePrivilegeGroupType_AddPrivilegesToGroup,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp2))
|
||||
s.Equal("", resp2.GetReason())
|
||||
s.True(merr.Ok(addPrivsToGroupResp))
|
||||
|
||||
// grant privilege group test_group to role test_role
|
||||
operatePrivilege(roleName, groupName, util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Grant)
|
||||
|
||||
userName := "test_user"
|
||||
passwd := "test_passwd"
|
||||
resp3, err := s.Cluster.Proxy.CreateCredential(ctx, &milvuspb.CreateCredentialRequest{
|
||||
createCredResp, err := s.Cluster.Proxy.CreateCredential(ctx, &milvuspb.CreateCredentialRequest{
|
||||
Username: userName,
|
||||
Password: crypto.Base64Encode(passwd),
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp3))
|
||||
resp4, err := s.Cluster.Proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{
|
||||
s.True(merr.Ok(createCredResp))
|
||||
operateUserRoleResp, err := s.Cluster.Proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{
|
||||
Username: userName,
|
||||
RoleName: roleName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp4))
|
||||
s.True(merr.Ok(operateUserRoleResp))
|
||||
|
||||
// test back up rbac
|
||||
resp5, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
// test back up rbac, grants should contain
|
||||
backupRBACResp, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp5.GetStatus()))
|
||||
s.True(merr.Ok(backupRBACResp.GetStatus()))
|
||||
s.Equal(2, len(backupRBACResp.GetRBACMeta().Grants))
|
||||
grants := lo.SliceToMap(backupRBACResp.GetRBACMeta().Grants, func(g *milvuspb.GrantEntity) (string, *milvuspb.GrantEntity) {
|
||||
return g.Grantor.Privilege.Name, g
|
||||
})
|
||||
s.True(grants["Search"] != nil)
|
||||
s.True(grants[groupName] != nil)
|
||||
s.Equal(groupName, backupRBACResp.GetRBACMeta().PrivilegeGroups[0].GroupName)
|
||||
s.Equal(2, len(backupRBACResp.GetRBACMeta().PrivilegeGroups[0].Privileges))
|
||||
|
||||
// test restore, expect to failed due to role/user already exist
|
||||
resp6, err := s.Cluster.Proxy.RestoreRBAC(ctx, &milvuspb.RestoreRBACMetaRequest{
|
||||
RBACMeta: resp5.GetRBACMeta(),
|
||||
restoreRBACResp, err := s.Cluster.Proxy.RestoreRBAC(ctx, &milvuspb.RestoreRBACMetaRequest{
|
||||
RBACMeta: backupRBACResp.GetRBACMeta(),
|
||||
})
|
||||
s.NoError(err)
|
||||
s.False(merr.Ok(resp6))
|
||||
s.False(merr.Ok(restoreRBACResp))
|
||||
|
||||
// drop exist role/user, successful to restore
|
||||
resp7, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Revoke,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Search"},
|
||||
},
|
||||
},
|
||||
// revoke privilege search from role test_role before dropping the role
|
||||
operatePrivilege(roleName, "Search", util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Revoke)
|
||||
|
||||
// revoke privilege group test_group from role test_role before dropping the role
|
||||
operatePrivilege(roleName, groupName, util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Revoke)
|
||||
|
||||
// drop privilege group test_group
|
||||
dropPrivGroupResp, err := s.Cluster.Proxy.DropPrivilegeGroup(ctx, &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: groupName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp7))
|
||||
resp8, err := s.Cluster.Proxy.DropRole(ctx, &milvuspb.DropRoleRequest{
|
||||
s.True(merr.Ok(dropPrivGroupResp))
|
||||
|
||||
// drop role test_role
|
||||
dropRoleResp, err := s.Cluster.Proxy.DropRole(ctx, &milvuspb.DropRoleRequest{
|
||||
RoleName: roleName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp8))
|
||||
resp9, err := s.Cluster.Proxy.DeleteCredential(ctx, &milvuspb.DeleteCredentialRequest{
|
||||
s.True(merr.Ok(dropRoleResp))
|
||||
|
||||
// delete credential
|
||||
delCredResp, err := s.Cluster.Proxy.DeleteCredential(ctx, &milvuspb.DeleteCredentialRequest{
|
||||
Username: userName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp9))
|
||||
s.True(merr.Ok(delCredResp))
|
||||
|
||||
resp10, err := s.Cluster.Proxy.RestoreRBAC(ctx, &milvuspb.RestoreRBACMetaRequest{
|
||||
RBACMeta: resp5.GetRBACMeta(),
|
||||
// restore rbac
|
||||
restoreRBACResp, err = s.Cluster.Proxy.RestoreRBAC(ctx, &milvuspb.RestoreRBACMetaRequest{
|
||||
RBACMeta: backupRBACResp.GetRBACMeta(),
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp10))
|
||||
s.True(merr.Ok(restoreRBACResp))
|
||||
|
||||
// check the restored rbac, should be same as the original one
|
||||
resp11, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
backupRBACResp2, err := s.Cluster.Proxy.BackupRBAC(ctx, &milvuspb.BackupRBACMetaRequest{})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp11.GetStatus()))
|
||||
s.Equal(resp11.GetRBACMeta().String(), resp5.GetRBACMeta().String())
|
||||
s.True(merr.Ok(backupRBACResp2.GetStatus()))
|
||||
s.Equal(backupRBACResp2.GetRBACMeta().String(), backupRBACResp.GetRBACMeta().String())
|
||||
|
||||
// clean rbac meta
|
||||
resp12, err := s.Cluster.Proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
|
||||
Type: milvuspb.OperatePrivilegeType_Revoke,
|
||||
Entity: &milvuspb.GrantEntity{
|
||||
Role: &milvuspb.RoleEntity{Name: roleName},
|
||||
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
|
||||
ObjectName: util.AnyWord,
|
||||
DbName: util.AnyWord,
|
||||
Grantor: &milvuspb.GrantorEntity{
|
||||
User: &milvuspb.UserEntity{Name: util.UserRoot},
|
||||
Privilege: &milvuspb.PrivilegeEntity{Name: "Search"},
|
||||
},
|
||||
},
|
||||
operatePrivilege(roleName, "Search", util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Revoke)
|
||||
|
||||
operatePrivilege(roleName, groupName, util.AnyWord, util.AnyWord, milvuspb.OperatePrivilegeType_Revoke)
|
||||
|
||||
dropPrivGroupResp2, err := s.Cluster.Proxy.DropPrivilegeGroup(ctx, &milvuspb.DropPrivilegeGroupRequest{
|
||||
GroupName: groupName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp12))
|
||||
s.True(merr.Ok(dropPrivGroupResp2))
|
||||
|
||||
resp13, err := s.Cluster.Proxy.DropRole(ctx, &milvuspb.DropRoleRequest{
|
||||
dropRoleResp2, err := s.Cluster.Proxy.DropRole(ctx, &milvuspb.DropRoleRequest{
|
||||
RoleName: roleName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp13))
|
||||
s.True(merr.Ok(dropRoleResp2))
|
||||
|
||||
resp14, err := s.Cluster.Proxy.DeleteCredential(ctx, &milvuspb.DeleteCredentialRequest{
|
||||
delCredResp2, err := s.Cluster.Proxy.DeleteCredential(ctx, &milvuspb.DeleteCredentialRequest{
|
||||
Username: userName,
|
||||
})
|
||||
s.NoError(err)
|
||||
s.True(merr.Ok(resp14))
|
||||
s.True(merr.Ok(delCredResp2))
|
||||
}
|
||||
|
||||
func TestRBACBackup(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue